diff --git a/DEPS b/DEPS
index 9e72239..637af68 100644
--- a/DEPS
+++ b/DEPS
@@ -39,11 +39,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'b988ecf639f1394ea5e821ac15b989e25e064534',
+  'skia_revision': '09aa1fce69b214714171db12c341aebd78dd29ea',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '0d3888a14530bfae7f76268e18e386016cf0ff40',
+  'v8_revision': '05c1f97eaca1185948b99a17f598ff345ff577ca',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -51,11 +51,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'ae2d0a0e865545fbc5f55bf2014d00bb8f4669c9',
+  'angle_revision': 'b0a531059e96765819c6230c6e8eb22a304bd2d8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
-  'buildtools_revision': '5378d73123b64907773cc5c1bb027b2f765ff00a',
+  'buildtools_revision': 'e84114dbe2b65428951c876349b6a3ff1afbfccd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -192,7 +192,7 @@
    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'beef68513861e11156899b1f763097c31808c418',
 
   'src/third_party/libjingle/source/talk':
-    Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + 'b6635d741fcb7030b62874f9bc8ae39628e127cc', # commit position 12291
+    Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + '6a9674787c1dac66a0f40df132da9028e3dfb886', # commit position 12410
 
   'src/third_party/usrsctp/usrsctplib':
     Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + 'c60ec8b35c3fe6027d7a3faae89d1c8d7dd3ce98',
@@ -216,7 +216,7 @@
    Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067',
 
   'src/third_party/webrtc':
-    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'cc6714b1ec7b4f6c7f0c37338aaca193b503c9cb', # commit position 12409
+    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'fcc3833d12a7f24dbe71f21791016ff4f10e04f8', # commit position 12447
 
   'src/third_party/openmax_dl':
     Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
diff --git a/android_webview/java/src/org/chromium/android_webview/AwGLFunctor.java b/android_webview/java/src/org/chromium/android_webview/AwGLFunctor.java
index e43b840..be319dd 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwGLFunctor.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwGLFunctor.java
@@ -33,7 +33,8 @@
     }
 
     private final long mNativeAwGLFunctor;
-    private final DestroyRunnable mDestroyRunnable;
+    // Same gc-life time as this, but does not reference any members like |mContainerView|.
+    private final Object mLifetimeObject;
     private final CleanupReference mCleanupReference;
     private final AwContents.NativeGLDelegate mNativeGLDelegate;
     private final ViewGroup mContainerView;
@@ -41,8 +42,9 @@
 
     public AwGLFunctor(AwContents.NativeGLDelegate nativeGLDelegate, ViewGroup containerView) {
         mNativeAwGLFunctor = nativeCreate(this);
-        mDestroyRunnable = new DestroyRunnable(mNativeAwGLFunctor);
-        mCleanupReference = new CleanupReference(mDestroyRunnable, mDestroyRunnable);
+        mLifetimeObject = new Object();
+        mCleanupReference =
+                new CleanupReference(mLifetimeObject, new DestroyRunnable(mNativeAwGLFunctor));
         mNativeGLDelegate = nativeGLDelegate;
         mContainerView = containerView;
         if (mNativeGLDelegate.supportsDrawGLFunctorReleasedCallback()) {
@@ -67,7 +69,7 @@
     }
 
     public Object getNativeLifetimeObject() {
-        return mDestroyRunnable;
+        return mLifetimeObject;
     }
 
     public boolean requestDrawGLForCanvas(Canvas canvas) {
diff --git a/android_webview/tools/system_webview_shell/apk/AndroidManifest.xml b/android_webview/tools/system_webview_shell/apk/AndroidManifest.xml
index 2224f83..70c6c379 100644
--- a/android_webview/tools/system_webview_shell/apk/AndroidManifest.xml
+++ b/android_webview/tools/system_webview_shell/apk/AndroidManifest.xml
@@ -61,7 +61,8 @@
             android:name="org.chromium.webview_shell.WebViewBrowserActivity"
             android:label="@string/title_activity_browser"
             android:exported="true"
-            android:windowSoftInputMode="adjustResize">
+            android:windowSoftInputMode="adjustResize"
+            android:configChanges="orientation|screenSize">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index f37c43c..dd6f76eb 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -81,6 +81,7 @@
       "//build/config/linux:xfixes",
     ]
     deps += [
+      "//ui/events/devices/x11",
       "//ui/events/platform",
       "//ui/gfx/x",
     ]
diff --git a/ash/ash.gyp b/ash/ash.gyp
index 5ff00c3..68af976b 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -1041,6 +1041,7 @@
           'dependencies': [
             '../build/linux/system.gyp:x11',
             '../build/linux/system.gyp:xfixes',
+            '../ui/events/devices/x11/events_devices_x11.gyp:events_devices_x11',
             '../ui/gfx/x/gfx_x11.gyp:gfx_x11',
            ],
         }],
diff --git a/ash/display/display_color_manager_chromeos_unittest.cc b/ash/display/display_color_manager_chromeos_unittest.cc
index e710c876..9766c10 100644
--- a/ash/display/display_color_manager_chromeos_unittest.cc
+++ b/ash/display/display_color_manager_chromeos_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "ash/display/display_color_manager_chromeos.h"
 
+#include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/memory/scoped_vector.h"
 #include "base/message_loop/message_loop.h"
@@ -14,6 +15,7 @@
 #include "base/test/sequenced_worker_pool_owner.h"
 #include "chromeos/chromeos_paths.h"
 #include "components/quirks/quirks_manager.h"
+#include "components/quirks/switches.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/display/chromeos/test/action_logger_util.h"
@@ -111,6 +113,9 @@
 class DisplayColorManagerTest : public testing::Test {
  public:
   void SetUp() override {
+    base::CommandLine::ForCurrentProcess()->AppendSwitch(
+        quirks::switches::kDisableQuirksClient);
+
     pool_owner_.reset(
         new base::SequencedWorkerPoolOwner(3, "DisplayColorManagerTest"));
     log_.reset(new ui::test::ActionLogger());
diff --git a/ash/shell/content/client/shell_browser_main_parts.cc b/ash/shell/content/client/shell_browser_main_parts.cc
index 09fa992..e0171545 100644
--- a/ash/shell/content/client/shell_browser_main_parts.cc
+++ b/ash/shell/content/client/shell_browser_main_parts.cc
@@ -37,7 +37,7 @@
 #include "ui/wm/core/wm_state.h"
 
 #if defined(USE_X11)
-#include "ui/events/devices/x11/touch_factory_x11.h"
+#include "ui/events/devices/x11/touch_factory_x11.h"  // nogncheck
 #endif
 
 #if defined(OS_CHROMEOS)
diff --git a/ash/touch/touch_hud_debug.cc b/ash/touch/touch_hud_debug.cc
index e690735ca..fcbc426 100644
--- a/ash/touch/touch_hud_debug.cc
+++ b/ash/touch/touch_hud_debug.cc
@@ -4,6 +4,10 @@
 
 #include "ash/touch/touch_hud_debug.h"
 
+#include <algorithm>
+#include <string>
+#include <vector>
+
 #include "ash/display/display_manager.h"
 #include "ash/root_window_controller.h"
 #include "ash/shell.h"
@@ -28,7 +32,7 @@
 #include <X11/extensions/XInput2.h>
 #include <X11/Xlib.h>
 
-#include "ui/events/devices/x11/device_data_manager_x11.h"
+#include "ui/events/devices/x11/device_data_manager_x11.h"  // nogncheck
 #endif
 
 namespace ash {
diff --git a/build/all.gyp b/build/all.gyp
index b51b9d9b..71ed6be 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -30,6 +30,7 @@
         '../sql/sql.gyp:*',
         '../testing/gmock.gyp:*',
         '../testing/gtest.gyp:*',
+        '../third_party/boringssl/boringssl.gyp:*',
         '../third_party/icu/icu.gyp:*',
         '../third_party/libxml/libxml.gyp:*',
         '../third_party/sqlite/sqlite.gyp:*',
@@ -167,11 +168,6 @@
             '<(libjpeg_gyp_path):*',
           ],
         }],
-        ['use_openssl==0 and OS=="ios"', {
-          'dependencies': [
-            '../third_party/nss/nss.gyp:*',
-           ],
-        }],
         ['OS=="win" or OS=="ios" or OS=="linux"', {
           'dependencies': [
             '../breakpad/breakpad.gyp:*',
@@ -254,17 +250,7 @@
             '../remoting/remoting_all.gyp:remoting_all',
           ],
         }],
-        ['use_openssl==0', {
-          'dependencies': [
-            '../net/third_party/nss/ssl.gyp:*',
-          ],
-        }],
-        ['use_openssl==1', {
-          'dependencies': [
-            '../third_party/boringssl/boringssl.gyp:*',
-          ],
-        }],
-        ['use_openssl==1 and OS!="ios"', {
+        ['OS!="ios"', {
           'dependencies': [
             '../third_party/boringssl/boringssl_tests.gyp:*',
           ],
diff --git a/build/android/buildbot/bb_device_steps.py b/build/android/buildbot/bb_device_steps.py
index 5d8731f..2e18e8d5 100755
--- a/build/android/buildbot/bb_device_steps.py
+++ b/build/android/buildbot/bb_device_steps.py
@@ -498,51 +498,54 @@
 
 
 def RunGPUTests(options):
+  exit_code = 0
   revision = _GetRevision(options)
   builder_name = options.build_properties.get('buildername', 'noname')
 
   bb_annotations.PrintNamedStep('pixel_tests')
-  RunCmd(['content/test/gpu/run_gpu_test.py',
-          'pixel', '-v',
-          '--browser',
-          'android-content-shell',
-          '--build-revision',
-          str(revision),
-          '--upload-refimg-to-cloud-storage',
-          '--refimg-cloud-storage-bucket',
-          'chromium-gpu-archive/reference-images',
-          '--os-type',
-          'android',
-          '--test-machine-name',
-          EscapeBuilderName(builder_name),
-          '--android-blacklist-file',
-          'out/bad_devices.json'])
+  exit_code = RunCmd(['content/test/gpu/run_gpu_test.py',
+                      'pixel', '-v',
+                      '--browser',
+                      'android-content-shell',
+                      '--build-revision',
+                      str(revision),
+                      '--upload-refimg-to-cloud-storage',
+                      '--refimg-cloud-storage-bucket',
+                      'chromium-gpu-archive/reference-images',
+                      '--os-type',
+                      'android',
+                      '--test-machine-name',
+                      EscapeBuilderName(builder_name),
+                      '--android-blacklist-file',
+                      'out/bad_devices.json']) or exit_code
 
   bb_annotations.PrintNamedStep('webgl_conformance_tests')
-  RunCmd(['content/test/gpu/run_gpu_test.py', '-v',
-          '--browser=android-content-shell', 'webgl_conformance',
-          '--webgl-conformance-version=1.0.1',
-          '--android-blacklist-file',
-          'out/bad_devices.json'])
+  exit_code = RunCmd(['content/test/gpu/run_gpu_test.py', '-v',
+                      '--browser=android-content-shell', 'webgl_conformance',
+                      '--webgl-conformance-version=1.0.1',
+                      '--android-blacklist-file',
+                      'out/bad_devices.json']) or exit_code
 
   bb_annotations.PrintNamedStep('android_webview_webgl_conformance_tests')
-  RunCmd(['content/test/gpu/run_gpu_test.py', '-v',
-          '--browser=android-webview-shell', 'webgl_conformance',
-          '--webgl-conformance-version=1.0.1',
-          '--android-blacklist-file',
-          'out/bad_devices.json'])
+  exit_code = RunCmd(['content/test/gpu/run_gpu_test.py', '-v',
+                      '--browser=android-webview-shell', 'webgl_conformance',
+                      '--webgl-conformance-version=1.0.1',
+                      '--android-blacklist-file',
+                      'out/bad_devices.json']) or exit_code
 
   bb_annotations.PrintNamedStep('gpu_rasterization_tests')
-  RunCmd(['content/test/gpu/run_gpu_test.py',
-          'gpu_rasterization', '-v',
-          '--browser',
-          'android-content-shell',
-          '--build-revision',
-          str(revision),
-          '--test-machine-name',
-          EscapeBuilderName(builder_name),
-          '--android-blacklist-file',
-          'out/bad_devices.json'])
+  exit_code = RunCmd(['content/test/gpu/run_gpu_test.py',
+                      'gpu_rasterization', '-v',
+                      '--browser',
+                      'android-content-shell',
+                      '--build-revision',
+                      str(revision),
+                      '--test-machine-name',
+                      EscapeBuilderName(builder_name),
+                      '--android-blacklist-file',
+                      'out/bad_devices.json']) or exit_code
+
+  return exit_code
 
 
 def RunPythonUnitTests(_options):
@@ -653,6 +656,7 @@
 
 
 def MainTestWrapper(options):
+  exit_code = 0
   try:
     # Spawn logcat monitor
     SpawnLogcatMonitor()
@@ -667,7 +671,8 @@
         InstallApk(options, install_obj, print_step=True)
 
     if options.test_filter:
-      bb_utils.RunSteps(options.test_filter, GetTestStepCmds(), options)
+      exit_code = bb_utils.RunSteps(
+          options.test_filter, GetTestStepCmds(), options) or exit_code
 
     if options.coverage_bucket:
       coverage_html = GenerateJavaCoverageReport(options)
@@ -676,7 +681,10 @@
       shutil.rmtree(coverage_html, ignore_errors=True)
 
     if options.experimental:
-      RunTestSuites(options, gtest_config.EXPERIMENTAL_TEST_SUITES)
+      exit_code = RunTestSuites(
+          options, gtest_config.EXPERIMENTAL_TEST_SUITES) or exit_code
+
+    return exit_code
 
   finally:
     # Run all post test steps
@@ -768,7 +776,7 @@
     setattr(options, 'coverage_dir',
             os.path.join(CHROME_OUT_DIR, options.target, 'coverage'))
 
-  MainTestWrapper(options)
+  return MainTestWrapper(options)
 
 
 if __name__ == '__main__':
diff --git a/build/android/buildbot/bb_utils.py b/build/android/buildbot/bb_utils.py
index 223f4ae..71ac7b2 100644
--- a/build/android/buildbot/bb_utils.py
+++ b/build/android/buildbot/bb_utils.py
@@ -96,6 +96,9 @@
     print >> sys.stderr, 'FATAL: Unknown steps %s' % list(unknown_steps)
     sys.exit(1)
 
+  exit_code = 0
   for step, cmd in step_cmds:
     if step in steps:
-      cmd(options)
+      exit_code = cmd(options) or exit_code
+
+  return exit_code
diff --git a/build/android/pylib/utils/isolator.py b/build/android/pylib/utils/isolator.py
index 832b4ad..c1281ff 100644
--- a/build/android/pylib/utils/isolator.py
+++ b/build/android/pylib/utils/isolator.py
@@ -47,7 +47,6 @@
     'use_custom_libcxx': '0',
     'use_instrumented_libraries': '0',
     'use_prebuilt_instrumented_libraries': '0',
-    'use_openssl': '0',
     'use_ozone': '0',
     'use_x11': '0',
     'v8_use_external_startup_data': '1',
@@ -174,4 +173,3 @@
         shutil.move(os.path.join(deps_product_dir, p), self._isolate_deps_dir)
       os.rmdir(deps_product_dir)
       os.rmdir(deps_out_dir)
-
diff --git a/build/common.gypi b/build/common.gypi
index bf6732a8..2fec6dd 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -744,15 +744,6 @@
           'use_nss_certs%': 0,
         }],
 
-        # NSS verifier usage.
-        # On non-OpenSSL iOS configurations, certificates use the operating
-        # system library, but the verifier uses the bundled copy of NSS.
-        ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris") or (OS=="ios" and use_openssl==0)', {
-          'use_nss_verifier%': 1,
-        }, {
-          'use_nss_verifier%': 0,
-        }],
-
         # libudev usage.  This currently only affects the content layer.
         ['OS=="linux" and embedded==0', {
           'use_udev%': 1,
@@ -1170,7 +1161,6 @@
     'use_openssl%': '<(use_openssl)',
     'use_openssl_certs%': '<(use_openssl_certs)',
     'use_nss_certs%': '<(use_nss_certs)',
-    'use_nss_verifier%': '<(use_nss_verifier)',
     'use_udev%': '<(use_udev)',
     'os_bsd%': '<(os_bsd)',
     'os_posix%': '<(os_posix)',
@@ -2139,9 +2129,6 @@
       ['use_nss_certs==1', {
         'grit_defines': ['-D', 'use_nss_certs'],
       }],
-      ['use_nss_verifier==1', {
-        'grit_defines': ['-D', 'use_nss_verifier'],
-      }],
       ['use_ozone==1', {
         'grit_defines': ['-D', 'use_ozone'],
       }],
@@ -3075,15 +3062,11 @@
       ['<(use_libpci)==1', {
         'defines': ['USE_LIBPCI=1'],
       }],
-      ['<(use_openssl)==1', {
-        'defines': ['USE_OPENSSL=1'],
-      }],
       ['<(use_openssl_certs)==1', {
         'defines': ['USE_OPENSSL_CERTS=1'],
       }],
       ['>(nacl_untrusted_build)==1', {
         'defines': [
-          'USE_OPENSSL=1',
           'USE_OPENSSL_CERTS=1',
         ],
       }],
@@ -3093,9 +3076,6 @@
       ['<(use_nss_certs)==1 and >(nacl_untrusted_build)==0', {
         'defines': ['USE_NSS_CERTS=1'],
       }],
-      ['<(use_nss_verifier)==1 and >(nacl_untrusted_build)==0', {
-        'defines': ['USE_NSS_VERIFIER=1'],
-      }],
       ['<(chromeos)==1 and >(nacl_untrusted_build)==0', {
         'defines': ['OS_CHROMEOS=1'],
       }],
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index b6d0b71f..d4caba48 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -124,18 +124,12 @@
   if (use_glib) {
     defines += [ "USE_GLIB=1" ]
   }
-  if (use_openssl) {
-    defines += [ "USE_OPENSSL=1" ]
-  }
   if (use_openssl_certs) {
     defines += [ "USE_OPENSSL_CERTS=1" ]
   }
   if (use_nss_certs) {
     defines += [ "USE_NSS_CERTS=1" ]
   }
-  if (use_nss_verifier) {
-    defines += [ "USE_NSS_VERIFIER=1" ]
-  }
   if (use_ozone) {
     defines += [ "USE_OZONE=1" ]
   }
diff --git a/build/config/crypto.gni b/build/config/crypto.gni
index 2b15b1c..5c940f2 100644
--- a/build/config/crypto.gni
+++ b/build/config/crypto.gni
@@ -22,12 +22,6 @@
 # is unsupported.
 use_openssl_certs = is_android || is_nacl
 
-# True if NSS is used for certificate handling. Note that this is independent
-# from use_openssl. It is possible to use OpenSSL for the crypto library, but
-# NSS for the platform certificate library.
+# True if NSS is used for certificate handling. It is possible to use OpenSSL
+# for the crypto library, but NSS for the platform certificate library.
 use_nss_certs = is_linux
-
-# True if NSS is used for certificate verification. On non-OpenSSL iOS
-# configurations, certificates use the operating system library, but the
-# verifier uses the bundled copy of NSS.
-use_nss_verifier = use_nss_certs || (is_ios && !use_openssl)
diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi
index 83cf2de..f413afb 100644
--- a/build/gn_migration.gypi
+++ b/build/gn_migration.gypi
@@ -83,6 +83,33 @@
         '../third_party/WebKit/Source/platform/blink_platform_tests.gyp:blink_platform_unittests',
         '../third_party/WebKit/Source/web/web_tests.gyp:webkit_unit_tests',
         '../third_party/WebKit/Source/wtf/wtf_tests.gyp:wtf_unittests',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_ecdsa_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_bn_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_pqueue_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_digest_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_cipher_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_hkdf_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_constant_time_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_thread_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_base64_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_gcm_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_bytestring_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_evp_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_dsa_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_rsa_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_hmac_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_aead_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_ssl_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_err_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_lhash_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_pbkdf_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_dh_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_pkcs12_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_example_mul',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_ec_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_bio_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_pkcs7_test',
+        '../third_party/boringssl/boringssl_tests.gyp:boringssl_unittests',
         '../third_party/leveldatabase/leveldatabase.gyp:env_chromium_unittests',
         '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_unittests',
         '../third_party/smhasher/smhasher.gyp:pmurhash',
@@ -641,38 +668,6 @@
             }],
           ],
         }],
-        ['use_openssl==1', {
-          'dependencies': [
-            # TODO(GYP): All of these targets still need to be converted.
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_ecdsa_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_bn_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_pqueue_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_digest_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_cipher_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_hkdf_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_constant_time_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_thread_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_base64_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_gcm_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_bytestring_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_evp_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_dsa_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_rsa_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_hmac_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_aead_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_ssl_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_err_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_lhash_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_pbkdf_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_dh_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_pkcs12_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_example_mul',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_ec_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_bio_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_pkcs7_test',
-            '../third_party/boringssl/boringssl_tests.gyp:boringssl_unittests',
-          ],
-        }],
         ['chromeos==1', {
           'dependencies': [
             '../content/content_shell_and_tests.gyp:jpeg_decode_accelerator_unittest',
diff --git a/build/isolate.gypi b/build/isolate.gypi
index ea3a91b..197e455 100644
--- a/build/isolate.gypi
+++ b/build/isolate.gypi
@@ -90,7 +90,6 @@
         '--config-variable', 'use_instrumented_libraries=<(use_instrumented_libraries)',
         '--config-variable',
         'use_prebuilt_instrumented_libraries=<(use_prebuilt_instrumented_libraries)',
-        '--config-variable', 'use_openssl=<(use_openssl)',
         '--config-variable', 'use_ozone=<(use_ozone)',
         '--config-variable', 'use_x11=<(use_x11)',
         '--config-variable', 'v8_use_external_startup_data=<(v8_use_external_startup_data)',
diff --git a/build/linux/system.gyp b/build/linux/system.gyp
index c4a3691..553a5a7 100644
--- a/build/linux/system.gyp
+++ b/build/linux/system.gyp
@@ -1246,27 +1246,13 @@
       'type': 'none',
       'conditions': [
         ['_toolset=="target"', {
+          'dependencies': [
+            '../../third_party/boringssl/boringssl.gyp:boringssl',
+          ],
           'conditions': [
-            ['use_openssl==1', {
-              'dependencies': [
-                '../../third_party/boringssl/boringssl.gyp:boringssl',
-              ],
-            }, {
-              'dependencies': [
-                '../../net/third_party/nss/ssl.gyp:libssl',
-              ],
-              'direct_dependent_settings': {
-                'include_dirs+': [
-                  # We need for our local copies of the libssl3 headers to come
-                  # before other includes, as we are shadowing system headers.
-                  '<(DEPTH)/net/third_party/nss/ssl',
-                ],
-              },
-            }],
-            # Link in the system NSS if it is used for either the internal
-            # crypto library (use_openssl==0) or platform certificate
+            # Link in the system NSS if it is used for the platform certificate
             # library (use_nss_certs==1).
-            ['use_openssl==0 or use_nss_certs==1', {
+            ['use_nss_certs==1', {
               'direct_dependent_settings': {
                 'cflags': [
                   '<!@(<(pkg-config) --cflags nss)',
diff --git a/cc/layers/render_surface_impl.cc b/cc/layers/render_surface_impl.cc
index 5ba1aad..bac8f243 100644
--- a/cc/layers/render_surface_impl.cc
+++ b/cc/layers/render_surface_impl.cc
@@ -150,6 +150,79 @@
   draw_properties_.content_rect = content_rect;
 }
 
+void RenderSurfaceImpl::SetContentRectForTesting(const gfx::Rect& rect) {
+  SetContentRect(rect);
+}
+
+gfx::Rect RenderSurfaceImpl::CalculateClippedAccumulatedContentRect() {
+  if (owning_layer_->replica_layer() || owning_layer_->HasCopyRequest() ||
+      !is_clipped())
+    return accumulated_content_rect();
+
+  if (accumulated_content_rect().IsEmpty())
+    return gfx::Rect();
+
+  // Calculate projection from the target surface rect to local
+  // space. Non-invertible draw transforms means no able to bring clipped rect
+  // in target space back to local space, early out without clip.
+  gfx::Transform target_to_surface(gfx::Transform::kSkipInitialization);
+  if (!draw_transform().GetInverse(&target_to_surface))
+    return accumulated_content_rect();
+
+  // Clip rect is in target space. Bring accumulated content rect to
+  // target space in preparation for clipping.
+  gfx::Rect accumulated_rect_in_target_space =
+      MathUtil::MapEnclosingClippedRect(draw_transform(),
+                                        accumulated_content_rect());
+  // If accumulated content rect is contained within clip rect, early out
+  // without clipping.
+  if (clip_rect().Contains(accumulated_rect_in_target_space))
+    return accumulated_content_rect();
+
+  gfx::Rect clipped_accumulated_rect_in_target_space = clip_rect();
+  clipped_accumulated_rect_in_target_space.Intersect(
+      accumulated_rect_in_target_space);
+
+  if (clipped_accumulated_rect_in_target_space.IsEmpty())
+    return gfx::Rect();
+
+  gfx::Rect clipped_accumulated_rect_in_local_space =
+      MathUtil::ProjectEnclosingClippedRect(
+          target_to_surface, clipped_accumulated_rect_in_target_space);
+  // Bringing clipped accumulated rect back to local space may result
+  // in inflation due to axis-alignment.
+  clipped_accumulated_rect_in_local_space.Intersect(accumulated_content_rect());
+  return clipped_accumulated_rect_in_local_space;
+}
+
+void RenderSurfaceImpl::CalculateContentRectFromAccumulatedContentRect(
+    int max_texture_size) {
+  // Root render surface use viewport, and does not calculate content rect.
+  DCHECK_NE(render_target(), this);
+
+  // Surface's content rect is the clipped accumulated content rect. By default
+  // use accumulated content rect, and then try to clip it.
+  gfx::Rect surface_content_rect = CalculateClippedAccumulatedContentRect();
+
+  // The RenderSurfaceImpl backing texture cannot exceed the maximum
+  // supported texture size.
+  surface_content_rect.set_width(
+      std::min(surface_content_rect.width(), max_texture_size));
+  surface_content_rect.set_height(
+      std::min(surface_content_rect.height(), max_texture_size));
+
+  SetContentRect(surface_content_rect);
+}
+
+void RenderSurfaceImpl::SetContentRectToViewport() {
+  // Only root render surface use viewport as content rect.
+  DCHECK_EQ(render_target(), this);
+  gfx::Rect viewport = gfx::ToEnclosingRect(owning_layer_->layer_tree_impl()
+                                                ->property_trees()
+                                                ->clip_tree.ViewportClip());
+  SetContentRect(viewport);
+}
+
 void RenderSurfaceImpl::ClearAccumulatedContentRect() {
   accumulated_content_rect_ = gfx::Rect();
 }
diff --git a/cc/layers/render_surface_impl.h b/cc/layers/render_surface_impl.h
index d738646..488cd5f 100644
--- a/cc/layers/render_surface_impl.h
+++ b/cc/layers/render_surface_impl.h
@@ -117,7 +117,9 @@
     contributes_to_drawn_surface_ = contributes_to_drawn_surface;
   }
 
-  void SetContentRect(const gfx::Rect& content_rect);
+  void CalculateContentRectFromAccumulatedContentRect(int max_texture_size);
+  void SetContentRectToViewport();
+  void SetContentRectForTesting(const gfx::Rect& rect);
   gfx::Rect content_rect() const { return draw_properties_.content_rect; }
 
   void ClearAccumulatedContentRect();
@@ -167,6 +169,9 @@
   int EffectTreeIndex() const;
 
  private:
+  void SetContentRect(const gfx::Rect& content_rect);
+  gfx::Rect CalculateClippedAccumulatedContentRect();
+
   LayerImpl* owning_layer_;
 
   // Container for properties that render surfaces need to compute before they
diff --git a/cc/layers/render_surface_unittest.cc b/cc/layers/render_surface_unittest.cc
index df85cb0..2c211779 100644
--- a/cc/layers/render_surface_unittest.cc
+++ b/cc/layers/render_surface_unittest.cc
@@ -54,7 +54,8 @@
   // Currently, the content_rect, clip_rect, and
   // owning_layer->layerPropertyChanged() are the only sources of change.
   EXECUTE_AND_VERIFY_SURFACE_CHANGED(render_surface->SetClipRect(test_rect));
-  EXECUTE_AND_VERIFY_SURFACE_CHANGED(render_surface->SetContentRect(test_rect));
+  EXECUTE_AND_VERIFY_SURFACE_CHANGED(
+      render_surface->SetContentRectForTesting(test_rect));
 
   owning_layer->SetOpacity(0.5f);
   EXPECT_TRUE(render_surface->SurfacePropertyChanged());
@@ -66,7 +67,7 @@
   EXECUTE_AND_VERIFY_SURFACE_DID_NOT_CHANGE(
       render_surface->SetClipRect(test_rect));
   EXECUTE_AND_VERIFY_SURFACE_DID_NOT_CHANGE(
-      render_surface->SetContentRect(test_rect));
+      render_surface->SetContentRectForTesting(test_rect));
 
   std::unique_ptr<LayerImpl> dummy_mask =
       LayerImpl::Create(host_impl.active_tree(), 2);
@@ -110,7 +111,7 @@
   gfx::Transform origin;
   origin.Translate(30, 40);
 
-  render_surface->SetContentRect(content_rect);
+  render_surface->SetContentRectForTesting(content_rect);
   render_surface->SetClipRect(clip_rect);
   render_surface->SetDrawOpacity(1.f);
 
@@ -173,7 +174,7 @@
   origin.Translate(30.0, 40.0);
 
   render_surface->SetScreenSpaceTransform(origin);
-  render_surface->SetContentRect(content_rect);
+  render_surface->SetContentRectForTesting(content_rect);
 
   TestRenderPassSink pass_sink;
 
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index f86b301..8982605 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -473,8 +473,8 @@
     ClipNode* parent_clip_node = clip_tree->parent(clip_node);
 
     gfx::Transform parent_to_current;
-    const TransformNode* parent_transform_node =
-        transform_tree.Node(parent_clip_node->data.transform_id);
+    const TransformNode* parent_target_transform_node =
+        transform_tree.Node(parent_clip_node->data.target_id);
     bool success = true;
 
     // Clips must be combined in target space. We cannot, for example, combine
@@ -491,16 +491,17 @@
         parent_clip_node->data.combined_clip_in_target_space;
     gfx::RectF parent_clip_in_target_space =
         parent_clip_node->data.clip_in_target_space;
-    if (parent_clip_node->data.target_id != clip_node->data.target_id &&
+    if (parent_target_transform_node &&
+        parent_target_transform_node->id != clip_node->data.target_id &&
         non_root_surfaces_enabled) {
       success &= transform_tree.ComputeTransformWithDestinationSublayerScale(
-          parent_clip_node->data.target_id, clip_node->data.target_id,
+          parent_target_transform_node->id, clip_node->data.target_id,
           &parent_to_current);
-      if (parent_transform_node->data.sublayer_scale.x() > 0 &&
-          parent_transform_node->data.sublayer_scale.y() > 0)
+      if (parent_target_transform_node->data.sublayer_scale.x() > 0 &&
+          parent_target_transform_node->data.sublayer_scale.y() > 0)
         parent_to_current.Scale(
-            1.f / parent_transform_node->data.sublayer_scale.x(),
-            1.f / parent_transform_node->data.sublayer_scale.y());
+            1.f / parent_target_transform_node->data.sublayer_scale.x(),
+            1.f / parent_target_transform_node->data.sublayer_scale.y());
       // If we can't compute a transform, it's because we had to use the inverse
       // of a singular transform. We won't draw in this case, so there's no need
       // to compute clips.
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc
index b94c34a..5c3ef1d1 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -195,56 +195,6 @@
   top_controls_delta = proto.top_controls_delta();
 }
 
-inline gfx::Rect CalculateVisibleRectWithCachedLayerRect(
-    const gfx::Rect& target_surface_rect,
-    const gfx::Rect& layer_bound_rect,
-    const gfx::Rect& layer_rect_in_target_space,
-    const gfx::Transform& transform) {
-  if (layer_rect_in_target_space.IsEmpty())
-    return gfx::Rect();
-
-  // Is this layer fully contained within the target surface?
-  if (target_surface_rect.Contains(layer_rect_in_target_space))
-    return layer_bound_rect;
-
-  // If the layer doesn't fill up the entire surface, then find the part of
-  // the surface rect where the layer could be visible. This avoids trying to
-  // project surface rect points that are behind the projection point.
-  gfx::Rect minimal_surface_rect = target_surface_rect;
-  minimal_surface_rect.Intersect(layer_rect_in_target_space);
-
-  if (minimal_surface_rect.IsEmpty())
-    return gfx::Rect();
-
-  // Project the corners of the target surface rect into the layer space.
-  // This bounding rectangle may be larger than it needs to be (being
-  // axis-aligned), but is a reasonable filter on the space to consider.
-  // Non-invertible transforms will create an empty rect here.
-
-  gfx::Transform surface_to_layer(gfx::Transform::kSkipInitialization);
-  if (!transform.GetInverse(&surface_to_layer)) {
-    // Because we cannot use the surface bounds to determine what portion of
-    // the layer is visible, we must conservatively assume the full layer is
-    // visible.
-    return layer_bound_rect;
-  }
-
-  gfx::Rect layer_rect = MathUtil::ProjectEnclosingClippedRect(
-      surface_to_layer, minimal_surface_rect);
-  layer_rect.Intersect(layer_bound_rect);
-  return layer_rect;
-}
-
-gfx::Rect LayerTreeHostCommon::CalculateVisibleRect(
-    const gfx::Rect& target_surface_rect,
-    const gfx::Rect& layer_bound_rect,
-    const gfx::Transform& transform) {
-  gfx::Rect layer_in_surface_space =
-      MathUtil::MapEnclosingClippedRect(transform, layer_bound_rect);
-  return CalculateVisibleRectWithCachedLayerRect(
-      target_surface_rect, layer_bound_rect, layer_in_surface_space, transform);
-}
-
 static inline bool IsRootLayer(const Layer* layer) {
   return !layer->parent();
 }
@@ -617,36 +567,13 @@
   for (LayerImpl* layer : base::Reversed(*render_surface_layer_list)) {
     if (layer_tree_impl->IsRootLayer(layer)) {
       // The root layer's surface content rect is always the entire viewport.
-      gfx::Rect viewport =
-          gfx::ToEnclosingRect(property_trees->clip_tree.ViewportClip());
-      layer->render_surface()->SetContentRect(viewport);
+      layer->render_surface()->SetContentRectToViewport();
       continue;
     }
-
     RenderSurfaceImpl* surface = layer->render_surface();
-    gfx::Rect surface_content_rect = surface->accumulated_content_rect();
-
-    if (!layer->replica_layer() && !layer->HasCopyRequest() &&
-        surface->is_clipped()) {
-      // Here, we clip the render surface's content rect with its clip rect.
-      // As the clip rect of render surface is in the surface's target
-      // space, we first map the content rect into the target space,
-      // intersect it with clip rect and project back the result to the
-      // surface space.
-      if (!surface_content_rect.IsEmpty()) {
-        gfx::Rect surface_clip_rect = LayerTreeHostCommon::CalculateVisibleRect(
-            surface->clip_rect(), surface_content_rect,
-            surface->draw_transform());
-        surface_content_rect.Intersect(surface_clip_rect);
-      }
-    }
-    // The RenderSurfaceImpl backing texture cannot exceed the maximum
-    // supported texture size.
-    surface_content_rect.set_width(
-        std::min(surface_content_rect.width(), max_texture_size));
-    surface_content_rect.set_height(
-        std::min(surface_content_rect.height(), max_texture_size));
-    surface->SetContentRect(surface_content_rect);
+    // Now all contributing drawable content rect has been accumulated to this
+    // render surface, calculate the content rect.
+    surface->CalculateContentRectFromAccumulatedContentRect(max_texture_size);
 
     // Now the render surface's content rect is calculated correctly, it could
     // contribute to its render target.
diff --git a/cc/trees/layer_tree_host_common.h b/cc/trees/layer_tree_host_common.h
index c136f96..8d1b5e7 100644
--- a/cc/trees/layer_tree_host_common.h
+++ b/cc/trees/layer_tree_host_common.h
@@ -45,10 +45,6 @@
 
 class CC_EXPORT LayerTreeHostCommon {
  public:
-  static gfx::Rect CalculateVisibleRect(const gfx::Rect& target_surface_rect,
-                                        const gfx::Rect& layer_bound_rect,
-                                        const gfx::Transform& transform);
-
   struct CC_EXPORT CalcDrawPropsMainInputsForTesting {
    public:
     CalcDrawPropsMainInputsForTesting(Layer* root_layer,
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index bb3b18d..ce72cad 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -104,6 +104,41 @@
       : LayerTreeHostCommonTest(LayerTreeSettingsScaleContent()) {}
 };
 
+class LayerTreeHostCommonDrawRectsTest : public LayerTreeHostCommonTest {
+ public:
+  LayerTreeHostCommonDrawRectsTest() : LayerTreeHostCommonTest() {}
+
+  LayerImpl* TestVisibleRectAndDrawableContentRect(
+      const gfx::Rect& target_rect,
+      const gfx::Transform& layer_transform,
+      const gfx::Rect& layer_rect) {
+    LayerImpl* root = root_layer();
+    LayerImpl* target = AddChild<LayerImpl>(root);
+    LayerImpl* drawing_layer = AddChild<LayerImpl>(target);
+
+    root->SetDrawsContent(true);
+    target->SetDrawsContent(true);
+    target->SetMasksToBounds(true);
+    drawing_layer->SetDrawsContent(true);
+
+    gfx::Transform identity;
+
+    SetLayerPropertiesForTesting(root, identity, gfx::Point3F(), gfx::PointF(),
+                                 gfx::Size(500, 500), true, false, true);
+    SetLayerPropertiesForTesting(target, identity, gfx::Point3F(),
+                                 gfx::PointF(target_rect.origin()),
+                                 target_rect.size(), true, false, true);
+    SetLayerPropertiesForTesting(drawing_layer, layer_transform, gfx::Point3F(),
+                                 gfx::PointF(layer_rect.origin()),
+                                 layer_rect.size(), true, false, false);
+
+    host_impl()->active_tree()->property_trees()->needs_rebuild = true;
+    ExecuteCalculateDrawProperties(root);
+
+    return drawing_layer;
+  }
+};
+
 TEST_F(LayerTreeHostCommonTest, TransformsForNoOpLayer) {
   // Sanity check: For layers positioned at zero, with zero size,
   // and with identity transforms, then the draw transform,
@@ -2696,70 +2731,47 @@
   EXPECT_TRUE(great_grand_child->screen_space_transform_is_animating());
 }
 
-TEST_F(LayerTreeHostCommonTest, VisibleRectForIdentityTransform) {
-  // Test the calculateVisibleRect() function works correctly for identity
-  // transforms.
+TEST_F(LayerTreeHostCommonDrawRectsTest, DrawRectsForIdentityTransform) {
+  // Test visible layer rect and drawable content rect are calculated correctly
+  // correctly for identity transforms.
 
   gfx::Rect target_surface_rect = gfx::Rect(0, 0, 100, 100);
   gfx::Transform layer_to_surface_transform;
 
   // Case 1: Layer is contained within the surface.
   gfx::Rect layer_content_rect = gfx::Rect(10, 10, 30, 30);
-  gfx::Rect expected = gfx::Rect(10, 10, 30, 30);
-  gfx::Rect actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_EQ(expected, actual);
+  gfx::Rect expected_visible_layer_rect = gfx::Rect(30, 30);
+  gfx::Rect expected_drawable_content_rect = gfx::Rect(10, 10, 30, 30);
+  LayerImpl* drawing_layer = TestVisibleRectAndDrawableContentRect(
+      target_surface_rect, layer_to_surface_transform, layer_content_rect);
+  EXPECT_EQ(expected_visible_layer_rect, drawing_layer->visible_layer_rect());
+  EXPECT_EQ(expected_drawable_content_rect,
+            drawing_layer->drawable_content_rect());
 
   // Case 2: Layer is outside the surface rect.
   layer_content_rect = gfx::Rect(120, 120, 30, 30);
-  actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_TRUE(actual.IsEmpty());
+  expected_visible_layer_rect = gfx::Rect();
+  expected_drawable_content_rect = gfx::Rect();
+  drawing_layer = TestVisibleRectAndDrawableContentRect(
+      target_surface_rect, layer_to_surface_transform, layer_content_rect);
+  EXPECT_EQ(expected_visible_layer_rect, drawing_layer->visible_layer_rect());
+  EXPECT_EQ(expected_drawable_content_rect,
+            drawing_layer->drawable_content_rect());
 
   // Case 3: Layer is partially overlapping the surface rect.
   layer_content_rect = gfx::Rect(80, 80, 30, 30);
-  expected = gfx::Rect(80, 80, 20, 20);
-  actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_EQ(expected, actual);
+  expected_visible_layer_rect = gfx::Rect(20, 20);
+  expected_drawable_content_rect = gfx::Rect(80, 80, 20, 20);
+  drawing_layer = TestVisibleRectAndDrawableContentRect(
+      target_surface_rect, layer_to_surface_transform, layer_content_rect);
+  EXPECT_EQ(expected_visible_layer_rect, drawing_layer->visible_layer_rect());
+  EXPECT_EQ(expected_drawable_content_rect,
+            drawing_layer->drawable_content_rect());
 }
 
-TEST_F(LayerTreeHostCommonTest, VisibleRectForTranslations) {
-  // Test the calculateVisibleRect() function works correctly for scaling
-  // transforms.
-
-  gfx::Rect target_surface_rect = gfx::Rect(0, 0, 100, 100);
-  gfx::Rect layer_content_rect = gfx::Rect(0, 0, 30, 30);
-  gfx::Transform layer_to_surface_transform;
-
-  // Case 1: Layer is contained within the surface.
-  layer_to_surface_transform.MakeIdentity();
-  layer_to_surface_transform.Translate(10.0, 10.0);
-  gfx::Rect expected = gfx::Rect(0, 0, 30, 30);
-  gfx::Rect actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_EQ(expected, actual);
-
-  // Case 2: Layer is outside the surface rect.
-  layer_to_surface_transform.MakeIdentity();
-  layer_to_surface_transform.Translate(120.0, 120.0);
-  actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_TRUE(actual.IsEmpty());
-
-  // Case 3: Layer is partially overlapping the surface rect.
-  layer_to_surface_transform.MakeIdentity();
-  layer_to_surface_transform.Translate(80.0, 80.0);
-  expected = gfx::Rect(0, 0, 20, 20);
-  actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_EQ(expected, actual);
-}
-
-TEST_F(LayerTreeHostCommonTest, VisibleRectFor2DRotations) {
-  // Test the calculateVisibleRect() function works correctly for rotations
-  // about z-axis (i.e. 2D rotations).  Remember that calculateVisibleRect()
-  // should return the g in the layer's space.
+TEST_F(LayerTreeHostCommonDrawRectsTest, DrawRectsFor2DRotations) {
+  // Test visible layer rect and drawable content rect are calculated correctly
+  // for rotations about z-axis (i.e. 2D rotations).
 
   gfx::Rect target_surface_rect = gfx::Rect(0, 0, 100, 100);
   gfx::Rect layer_content_rect = gfx::Rect(0, 0, 30, 30);
@@ -2769,18 +2781,25 @@
   layer_to_surface_transform.MakeIdentity();
   layer_to_surface_transform.Translate(50.0, 50.0);
   layer_to_surface_transform.Rotate(45.0);
-  gfx::Rect expected = gfx::Rect(0, 0, 30, 30);
-  gfx::Rect actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_EQ(expected, actual);
+  gfx::Rect expected_visible_layer_rect = gfx::Rect(30, 30);
+  gfx::Rect expected_drawable_content_rect = gfx::Rect(28, 50, 44, 43);
+  LayerImpl* drawing_layer = TestVisibleRectAndDrawableContentRect(
+      target_surface_rect, layer_to_surface_transform, layer_content_rect);
+  EXPECT_EQ(expected_visible_layer_rect, drawing_layer->visible_layer_rect());
+  EXPECT_EQ(expected_drawable_content_rect,
+            drawing_layer->drawable_content_rect());
 
   // Case 2: Layer is outside the surface rect.
   layer_to_surface_transform.MakeIdentity();
   layer_to_surface_transform.Translate(-50.0, 0.0);
   layer_to_surface_transform.Rotate(45.0);
-  actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_TRUE(actual.IsEmpty());
+  expected_visible_layer_rect = gfx::Rect();
+  expected_drawable_content_rect = gfx::Rect();
+  drawing_layer = TestVisibleRectAndDrawableContentRect(
+      target_surface_rect, layer_to_surface_transform, layer_content_rect);
+  EXPECT_EQ(expected_visible_layer_rect, drawing_layer->visible_layer_rect());
+  EXPECT_EQ(expected_drawable_content_rect,
+            drawing_layer->drawable_content_rect());
 
   // Case 3: The layer is rotated about its top-left corner. In surface space,
   // the layer is oriented diagonally, with the left half outside of the render
@@ -2789,10 +2808,13 @@
   // and bottom-right corners of the layer are still visible.
   layer_to_surface_transform.MakeIdentity();
   layer_to_surface_transform.Rotate(45.0);
-  expected = gfx::Rect(0, 0, 30, 30);
-  actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_EQ(expected, actual);
+  expected_visible_layer_rect = gfx::Rect(30, 30);
+  expected_drawable_content_rect = gfx::Rect(22, 43);
+  drawing_layer = TestVisibleRectAndDrawableContentRect(
+      target_surface_rect, layer_to_surface_transform, layer_content_rect);
+  EXPECT_EQ(expected_visible_layer_rect, drawing_layer->visible_layer_rect());
+  EXPECT_EQ(expected_drawable_content_rect,
+            drawing_layer->drawable_content_rect());
 
   // Case 4: The layer is rotated about its top-left corner, and translated
   // upwards. In surface space, the layer is oriented diagonally, with only the
@@ -2802,15 +2824,19 @@
   layer_to_surface_transform.MakeIdentity();
   layer_to_surface_transform.Translate(0.0, -sqrt(2.0) * 15.0);
   layer_to_surface_transform.Rotate(45.0);
-  expected = gfx::Rect(15, 0, 15, 30);  // Right half of layer bounds.
-  actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_EQ(expected, actual);
+  // Right half of layer bounds.
+  expected_visible_layer_rect = gfx::Rect(15, 0, 15, 30);
+  expected_drawable_content_rect = gfx::Rect(22, 22);
+  drawing_layer = TestVisibleRectAndDrawableContentRect(
+      target_surface_rect, layer_to_surface_transform, layer_content_rect);
+  EXPECT_EQ(expected_visible_layer_rect, drawing_layer->visible_layer_rect());
+  EXPECT_EQ(expected_drawable_content_rect,
+            drawing_layer->drawable_content_rect());
 }
 
-TEST_F(LayerTreeHostCommonTest, VisibleRectFor3dOrthographicTransform) {
-  // Test that the calculateVisibleRect() function works correctly for 3d
-  // transforms.
+TEST_F(LayerTreeHostCommonDrawRectsTest, DrawRectsFor3dOrthographicTransform) {
+  // Test visible layer rect and drawable content rect are calculated correctly
+  // for 3d transforms.
 
   gfx::Rect target_surface_rect = gfx::Rect(0, 0, 100, 100);
   gfx::Rect layer_content_rect = gfx::Rect(0, 0, 100, 100);
@@ -2818,32 +2844,40 @@
 
   // Case 1: Orthographic projection of a layer rotated about y-axis by 45
   // degrees, should be fully contained in the render surface.
+  // 100 is the un-rotated layer width; divided by sqrt(2) is the rotated width.
   layer_to_surface_transform.MakeIdentity();
   layer_to_surface_transform.RotateAboutYAxis(45.0);
-  gfx::Rect expected = gfx::Rect(0, 0, 100, 100);
-  gfx::Rect actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_EQ(expected, actual);
+  gfx::Rect expected_visible_layer_rect = gfx::Rect(100, 100);
+  gfx::Rect expected_drawable_content_rect = gfx::Rect(71, 100);
+  LayerImpl* drawing_layer = TestVisibleRectAndDrawableContentRect(
+      target_surface_rect, layer_to_surface_transform, layer_content_rect);
+  EXPECT_EQ(expected_visible_layer_rect, drawing_layer->visible_layer_rect());
+  EXPECT_EQ(expected_drawable_content_rect,
+            drawing_layer->drawable_content_rect());
 
   // Case 2: Orthographic projection of a layer rotated about y-axis by 45
   // degrees, but shifted to the side so only the right-half the layer would be
   // visible on the surface.
-  // 100 is the un-rotated layer width; divided by sqrt(2) is the rotated width.
+  // 50 is the un-rotated layer width; divided by sqrt(2) is the rotated width.
   SkMScalar half_width_of_rotated_layer =
       SkDoubleToMScalar((100.0 / sqrt(2.0)) * 0.5);
   layer_to_surface_transform.MakeIdentity();
   layer_to_surface_transform.Translate(-half_width_of_rotated_layer, 0.0);
   layer_to_surface_transform.RotateAboutYAxis(45.0);  // Rotates about the left
                                                       // edge of the layer.
-  expected = gfx::Rect(50, 0, 50, 100);  // Tight half of the layer.
-  actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_EQ(expected, actual);
+  // Tight half of the layer.
+  expected_visible_layer_rect = gfx::Rect(50, 0, 50, 100);
+  expected_drawable_content_rect = gfx::Rect(36, 100);
+  drawing_layer = TestVisibleRectAndDrawableContentRect(
+      target_surface_rect, layer_to_surface_transform, layer_content_rect);
+  EXPECT_EQ(expected_visible_layer_rect, drawing_layer->visible_layer_rect());
+  EXPECT_EQ(expected_drawable_content_rect,
+            drawing_layer->drawable_content_rect());
 }
 
-TEST_F(LayerTreeHostCommonTest, VisibleRectFor3dPerspectiveTransform) {
-  // Test the calculateVisibleRect() function works correctly when the layer has
-  // a perspective projection onto the target surface.
+TEST_F(LayerTreeHostCommonDrawRectsTest, DrawRectsFor3dPerspectiveTransform) {
+  // Test visible layer rect and drawable content rect are calculated correctly
+  // when the layer has a perspective projection onto the target surface.
 
   gfx::Rect target_surface_rect = gfx::Rect(0, 0, 100, 100);
   gfx::Rect layer_content_rect = gfx::Rect(-50, -50, 200, 200);
@@ -2863,10 +2897,15 @@
   // This translate places the layer in front of the surface's projection plane.
   layer_to_surface_transform.Translate3d(0.0, 0.0, -27.0);
 
-  gfx::Rect expected = gfx::Rect(-50, -50, 200, 200);
-  gfx::Rect actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_EQ(expected, actual);
+  // Layer position is (-50, -50), visible rect in layer space is layer bounds
+  // offset by layer position.
+  gfx::Rect expected_visible_layer_rect = gfx::Rect(50, 50, 150, 150);
+  gfx::Rect expected_drawable_content_rect = gfx::Rect(38, 38);
+  LayerImpl* drawing_layer = TestVisibleRectAndDrawableContentRect(
+      target_surface_rect, layer_to_surface_transform, layer_content_rect);
+  EXPECT_EQ(expected_visible_layer_rect, drawing_layer->visible_layer_rect());
+  EXPECT_EQ(expected_drawable_content_rect,
+            drawing_layer->drawable_content_rect());
 
   // Case 2: same projection as before, except that the layer is also translated
   // to the side, so that only the right half of the layer should be visible.
@@ -2874,20 +2913,23 @@
   // Explanation of expected result: The perspective ratio is (z distance
   // between layer and camera origin) / (z distance between projection plane and
   // camera origin) == ((-27 - 9) / 9) Then, by similar triangles, if we want to
-  // move a layer by translating -50 units in projected surface units (so that
+  // move a layer by translating -25 units in projected surface units (so that
   // only half of it is visible), then we would need to translate by (-36 / 9) *
-  // -50 == -200 in the layer's units.
-  layer_to_surface_transform.Translate3d(-200.0, 0.0, 0.0);
-  expected = gfx::Rect(gfx::Point(50, -50),
-                       gfx::Size(100, 200));  // The right half of the layer's
-                                              // bounding rect.
-  actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_EQ(expected, actual);
+  // -25 == -100 in the layer's units.
+  layer_to_surface_transform.Translate3d(-100.0, 0.0, 0.0);
+  // Visible layer rect is moved by 100, and drawable content rect is in target
+  // space and is moved by 25.
+  expected_visible_layer_rect = gfx::Rect(150, 50, 50, 150);
+  expected_drawable_content_rect = gfx::Rect(13, 38);
+  drawing_layer = TestVisibleRectAndDrawableContentRect(
+      target_surface_rect, layer_to_surface_transform, layer_content_rect);
+  EXPECT_EQ(expected_visible_layer_rect, drawing_layer->visible_layer_rect());
+  EXPECT_EQ(expected_drawable_content_rect,
+            drawing_layer->drawable_content_rect());
 }
 
-TEST_F(LayerTreeHostCommonTest,
-       VisibleRectFor3dOrthographicIsNotClippedBehindSurface) {
+TEST_F(LayerTreeHostCommonDrawRectsTest,
+       DrawRectsFor3dOrthographicIsNotClippedBehindSurface) {
   // There is currently no explicit concept of an orthographic projection plane
   // in our code (nor in the CSS spec to my knowledge). Therefore, layers that
   // are technically behind the surface in an orthographic world should not be
@@ -2904,22 +2946,30 @@
   layer_to_surface_transform.RotateAboutYAxis(45.0);
   layer_to_surface_transform.Translate(-50.0, 0.0);
 
-  gfx::Rect expected = gfx::Rect(0, 0, 100, 100);
-  gfx::Rect actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_EQ(expected, actual);
+  // Layer is rotated about Y Axis, and its width is 100/sqrt(2) in surface
+  // space.
+  gfx::Rect expected_visible_layer_rect = gfx::Rect(100, 100);
+  gfx::Rect expected_drawable_content_rect = gfx::Rect(14, 0, 72, 100);
+  LayerImpl* drawing_layer = TestVisibleRectAndDrawableContentRect(
+      target_surface_rect, layer_to_surface_transform, layer_content_rect);
+  EXPECT_EQ(expected_visible_layer_rect, drawing_layer->visible_layer_rect());
+  EXPECT_EQ(expected_drawable_content_rect,
+            drawing_layer->drawable_content_rect());
 }
 
-TEST_F(LayerTreeHostCommonTest, VisibleRectFor3dPerspectiveWhenClippedByW) {
-  // Test the calculateVisibleRect() function works correctly when projecting a
-  // surface onto a layer, but the layer is partially behind the camera (not
-  // just behind the projection plane). In this case, the cartesian coordinates
-  // may seem to be valid, but actually they are not. The visible rect needs to
-  // be properly clipped by the w = 0 plane in homogeneous coordinates before
-  // converting to cartesian coordinates.
+TEST_F(LayerTreeHostCommonDrawRectsTest,
+       DrawRectsFor3dPerspectiveWhenClippedByW) {
+  // Test visible layer rect and drawable content rect are calculated correctly
+  // when projecting a surface onto a layer, but the layer is partially behind
+  // the camera (not just behind the projection plane). In this case, the
+  // cartesian coordinates may seem to be valid, but actually they are not. The
+  // visible rect needs to be properly clipped by the w = 0 plane in homogeneous
+  // coordinates before converting to cartesian coordinates. The drawable
+  // content rect would be entire surface rect because layer is rotated at the
+  // camera position.
 
-  gfx::Rect target_surface_rect = gfx::Rect(-50, -50, 100, 100);
-  gfx::Rect layer_content_rect = gfx::Rect(-10, -1, 20, 2);
+  gfx::Rect target_surface_rect = gfx::Rect(0, 0, 200, 200);
+  gfx::Rect layer_content_rect = gfx::Rect(0, 0, 20, 2);
   gfx::Transform layer_to_surface_transform;
 
   // The layer is positioned so that the right half of the layer should be in
@@ -2928,8 +2978,9 @@
   // perspective and rotation about the center of the layer.
   layer_to_surface_transform.MakeIdentity();
   layer_to_surface_transform.ApplyPerspectiveDepth(1.0);
-  layer_to_surface_transform.Translate3d(-2.0, 0.0, 1.0);
-  layer_to_surface_transform.RotateAboutYAxis(45.0);
+  layer_to_surface_transform.Translate3d(10.0, 0.0, 1.0);
+  layer_to_surface_transform.RotateAboutYAxis(-45.0);
+  layer_to_surface_transform.Translate(-10, -1);
 
   // Sanity check that this transform does indeed cause w < 0 when applying the
   // transform, otherwise this code is not testing the intended scenario.
@@ -2939,15 +2990,16 @@
                     &clipped);
   ASSERT_TRUE(clipped);
 
-  int expected_x_position = 0;
-  int expected_width = 10;
-  gfx::Rect actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_EQ(expected_x_position, actual.x());
-  EXPECT_EQ(expected_width, actual.width());
+  gfx::Rect expected_visible_layer_rect = gfx::Rect(0, 1, 10, 1);
+  gfx::Rect expected_drawable_content_rect = target_surface_rect;
+  LayerImpl* drawing_layer = TestVisibleRectAndDrawableContentRect(
+      target_surface_rect, layer_to_surface_transform, layer_content_rect);
+  EXPECT_EQ(expected_visible_layer_rect, drawing_layer->visible_layer_rect());
+  EXPECT_EQ(expected_drawable_content_rect,
+            drawing_layer->drawable_content_rect());
 }
 
-TEST_F(LayerTreeHostCommonTest, VisibleRectForPerspectiveUnprojection) {
+TEST_F(LayerTreeHostCommonDrawRectsTest, DrawRectsForPerspectiveUnprojection) {
   // To determine visible rect in layer space, there needs to be an
   // un-projection from surface space to layer space. When the original
   // transform was a perspective projection that was clipped, it returns a rect
@@ -2956,14 +3008,16 @@
 
   // This sequence of transforms causes one corner of the layer to protrude
   // across the w = 0 plane, and should be clipped.
-  gfx::Rect target_surface_rect = gfx::Rect(-50, -50, 100, 100);
-  gfx::Rect layer_content_rect = gfx::Rect(-10, -10, 20, 20);
+  gfx::Rect target_surface_rect = gfx::Rect(0, 0, 150, 150);
+  gfx::Rect layer_content_rect = gfx::Rect(0, 0, 20, 20);
   gfx::Transform layer_to_surface_transform;
   layer_to_surface_transform.MakeIdentity();
+  layer_to_surface_transform.Translate(10, 10);
   layer_to_surface_transform.ApplyPerspectiveDepth(1.0);
   layer_to_surface_transform.Translate3d(0.0, 0.0, -5.0);
   layer_to_surface_transform.RotateAboutYAxis(45.0);
   layer_to_surface_transform.RotateAboutXAxis(80.0);
+  layer_to_surface_transform.Translate(-10, -10);
 
   // Sanity check that un-projection does indeed cause w < 0, otherwise this
   // code is not testing the intended scenario.
@@ -2977,10 +3031,13 @@
   // Only the corner of the layer is not visible on the surface because of being
   // clipped. But, the net result of rounding visible region to an axis-aligned
   // rect is that the entire layer should still be considered visible.
-  gfx::Rect expected = gfx::Rect(-10, -10, 20, 20);
-  gfx::Rect actual = LayerTreeHostCommon::CalculateVisibleRect(
-      target_surface_rect, layer_content_rect, layer_to_surface_transform);
-  EXPECT_EQ(expected, actual);
+  gfx::Rect expected_visible_layer_rect = layer_content_rect;
+  gfx::Rect expected_drawable_content_rect = target_surface_rect;
+  LayerImpl* drawing_layer = TestVisibleRectAndDrawableContentRect(
+      target_surface_rect, layer_to_surface_transform, layer_content_rect);
+  EXPECT_EQ(expected_visible_layer_rect, drawing_layer->visible_layer_rect());
+  EXPECT_EQ(expected_drawable_content_rect,
+            drawing_layer->drawable_content_rect());
 }
 
 TEST_F(LayerTreeHostCommonTest,
@@ -9744,6 +9801,54 @@
                                   child->mask_layer()->ScreenSpaceTransform());
 }
 
+TEST_F(LayerTreeHostCommonTest,
+       SublayerScaleWithTransformNodeBetweenTwoTargets) {
+  LayerImpl* root = root_layer();
+  LayerImpl* render_surface1 = AddChild<LayerImpl>(root);
+  LayerImpl* between_targets = AddChild<LayerImpl>(render_surface1);
+  LayerImpl* render_surface2 = AddChild<LayerImpl>(between_targets);
+  LayerImpl* test_layer = AddChild<LayerImpl>(render_surface2);
+  const gfx::Transform identity_matrix;
+  test_layer->SetDrawsContent(true);
+
+  gfx::Transform scale;
+  scale.Scale(2.f, 2.f);
+  SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(30, 30), true, false,
+                               true);
+  SetLayerPropertiesForTesting(render_surface1, scale, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(30, 30), true, false,
+                               true);
+  SetLayerPropertiesForTesting(between_targets, identity_matrix, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(30, 30), true, false,
+                               false);
+  SetLayerPropertiesForTesting(render_surface2, identity_matrix, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(30, 30), true, false,
+                               true);
+  SetLayerPropertiesForTesting(test_layer, identity_matrix, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(30, 30), true, false,
+                               false);
+  // We want layer between the two targets to create a clip node and transform
+  // node but it shouldn't create a render surface.
+  between_targets->SetMasksToBounds(true);
+  between_targets->Set3dSortingContextId(2);
+
+  ExecuteCalculateDrawProperties(root);
+
+  TransformTree& tree =
+      root->layer_tree_impl()->property_trees()->transform_tree;
+  TransformNode* node = tree.Node(render_surface1->transform_tree_index());
+  EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(2.f, 2.f));
+
+  node = tree.Node(between_targets->transform_tree_index());
+  EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(1.f, 1.f));
+
+  node = tree.Node(render_surface2->transform_tree_index());
+  EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(2.f, 2.f));
+
+  EXPECT_EQ(gfx::Rect(15, 15), test_layer->visible_layer_rect());
+}
+
 TEST_F(LayerTreeHostCommonTest, LargeTransformTest) {
   LayerImpl* root = root_layer();
   LayerImpl* render_surface1 = AddChild<LayerImpl>(root);
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 5bfb96a..4f2f1e4 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -1054,10 +1054,6 @@
   if (input_handler_client_)
     input_handler_client_->ReconcileElasticOverscrollAndRootScroll();
 
-  UMA_HISTOGRAM_CUSTOM_COUNTS(
-      "Compositing.NumActiveLayers",
-      base::saturated_cast<int>(active_tree_->NumLayers()), 1, 400, 20);
-
   if (const char* client_name = GetClientNameForMetrics()) {
     size_t total_picture_memory = 0;
     for (const PictureLayerImpl* layer : active_tree()->picture_layers())
@@ -1070,6 +1066,11 @@
                              client_name),
           base::saturated_cast<int>(total_picture_memory / 1024));
     }
+    // GetClientNameForMetrics only returns one non-null value over the lifetime
+    // of the process, so this histogram name is runtime constant.
+    UMA_HISTOGRAM_CUSTOM_COUNTS(
+        base::StringPrintf("Compositing.%s.NumActiveLayers", client_name),
+        base::saturated_cast<int>(active_tree_->NumLayers()), 1, 400, 20);
   }
 
   bool update_lcd_text = false;
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index e41da4b4..9817125 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -834,6 +834,9 @@
               "Compositing.%s.LayerTreeImpl.CalculateDrawPropertiesUs",
               client_name),
           timer.Elapsed().InMicroseconds());
+      UMA_HISTOGRAM_COUNTS_100(
+          base::StringPrintf("Compositing.%s.NumRenderSurfaces", client_name),
+          base::saturated_cast<int>(render_surface_layer_list_.size()));
     }
   }
 
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 4579edd..50214b89 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -261,41 +261,8 @@
 
 # GYP: //chrome/chrome_tests.gypi:chrome_junit_tests
 junit_binary("chrome_junit_tests") {
-  java_files = [
-    "junit/src/org/chromium/chrome/browser/ShortcutHelperTest.java",
-    "junit/src/org/chromium/chrome/browser/SSLClientCertificateRequestTest.java",
-    "junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java",
-    "junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionControllerTest.java",
-    "junit/src/org/chromium/chrome/browser/crash/LogcatExtractionCallableTest.java",
-    "junit/src/org/chromium/chrome/browser/externalauth/ExternalAuthUtilsTest.java",
-    "junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java",
-    "junit/src/org/chromium/chrome/browser/gcore/GoogleApiClientHelperTest.java",
-    "junit/src/org/chromium/chrome/browser/invalidation/InvalidationControllerTest.java",
-    "junit/src/org/chromium/chrome/browser/media/remote/AbstractMediaRouteControllerTest.java",
-    "junit/src/org/chromium/chrome/browser/media/remote/MediaUrlResolverTest.java",
-    "junit/src/org/chromium/chrome/browser/media/remote/RemoteVideoInfoTest.java",
-    "junit/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterRouteTest.java",
-    "junit/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterSinkObservationTest.java",
-    "junit/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterTestBase.java",
-    "junit/src/org/chromium/chrome/browser/media/router/cast/CastMessageHandlerTest.java",
-    "junit/src/org/chromium/chrome/browser/media/router/cast/DiscoveryCallbackTest.java",
-    "junit/src/org/chromium/chrome/browser/media/router/cast/JSONTestUtils.java",
-    "junit/src/org/chromium/chrome/browser/media/router/cast/TestUtils.java",
-    "junit/src/org/chromium/chrome/browser/notifications/NotificationUIManagerUnitTest.java",
-    "junit/src/org/chromium/chrome/browser/ntp/NativePageFactoryTest.java",
-    "junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java",
-    "junit/src/org/chromium/chrome/browser/offlinepages/ClientIdTest.java",
-    "junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java",
-    "junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserverTest.java",
-    "junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java",
-    "junit/src/org/chromium/chrome/browser/omaha/ResponseParserTest.java",
-    "junit/src/org/chromium/chrome/browser/omaha/VersionNumberTest.java",
-    "junit/src/org/chromium/chrome/browser/snackbar/SnackbarCollectionUnitTest.java",
-    "junit/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProviderUnitTest.java",
-    "junit/src/org/chromium/chrome/browser/util/NonThreadSafeTest.java",
-    "junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java",
-    "junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java",
-  ]
+  # From java_sources.gni.
+  java_files = chrome_junit_test_java_sources
   deps = [
     ":chrome_java",
     ":chrome_java_resources",
@@ -569,19 +536,9 @@
 
 android_library("chrome_sync_shell_test_apk_java") {
   testonly = true
-  java_files = [
-    "sync_shell/javatests/src/org/chromium/chrome/browser/sync/AutofillTest.java",
-    "sync_shell/javatests/src/org/chromium/chrome/browser/sync/BookmarksTest.java",
-    "sync_shell/javatests/src/org/chromium/chrome/browser/sync/FakeServerHelper.java",
-    "sync_shell/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java",
-    "sync_shell/javatests/src/org/chromium/chrome/browser/sync/GmsCoreSyncListenerTest.java",
-    "sync_shell/javatests/src/org/chromium/chrome/browser/sync/OpenTabsTest.java",
-    "sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java",
-    "sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java",
-    "sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTestBase.java",
-    "sync_shell/javatests/src/org/chromium/chrome/browser/sync/TypedUrlsTest.java",
-    "sync_shell/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java",
-  ]
+
+  # From java_sources.jni.
+  java_files = sync_shell_test_java_sources
 
   deps = [
     "//base:base_java",
diff --git a/chrome/android/OWNERS b/chrome/android/OWNERS
index 7dd4fbab..792a9e471 100644
--- a/chrome/android/OWNERS
+++ b/chrome/android/OWNERS
@@ -7,4 +7,4 @@
 tedchoc@chromium.org
 yfriedman@chromium.org
 
-per-file java_sources.gni=twellington@chromium.org
+per-file java_sources.gni=*
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 2c78495..2394abe 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -465,7 +465,7 @@
       <message name="IDS_CLEAR_BROWSING_DATA_PROGRESS_TITLE" desc='Title for the progress dialog used when waiting for "clear browsing data" to complete.'>
         Clearing browsing data
       </message>
-      <message name="IDS_CLEAR_DATA_DELETE" desc="Button that allows the user to clear their browsing data. [CHAR-LIMIT=20]">
+      <message name="IDS_CLEAR_DATA_DELETE" desc="Button that allows the user to clear their browsing data. [CHAR-LIMIT=30]">
         Clear data
       </message>
       <message name="IDS_CLEAR_BROWSING_DATA_PROGRESS_MESSAGE" desc='Message on the progress dialog used when waiting for "clear browsing data" to complete.'>
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 84708ef..2dd3dab 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -1185,3 +1185,53 @@
   "javatests/src/org/chromium/chrome/test/util/ChromeSigninUtilsTest.java",
   "javatests/src/org/chromium/chrome/test/util/parameters/SigninParametersTest.java",
 ]
+
+chrome_junit_test_java_sources = [
+  "junit/src/org/chromium/chrome/browser/ShortcutHelperTest.java",
+  "junit/src/org/chromium/chrome/browser/SSLClientCertificateRequestTest.java",
+  "junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java",
+  "junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionControllerTest.java",
+  "junit/src/org/chromium/chrome/browser/crash/LogcatExtractionCallableTest.java",
+  "junit/src/org/chromium/chrome/browser/externalauth/ExternalAuthUtilsTest.java",
+  "junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java",
+  "junit/src/org/chromium/chrome/browser/gcore/GoogleApiClientHelperTest.java",
+  "junit/src/org/chromium/chrome/browser/invalidation/InvalidationControllerTest.java",
+  "junit/src/org/chromium/chrome/browser/media/remote/AbstractMediaRouteControllerTest.java",
+  "junit/src/org/chromium/chrome/browser/media/remote/MediaUrlResolverTest.java",
+  "junit/src/org/chromium/chrome/browser/media/remote/RemoteVideoInfoTest.java",
+  "junit/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterRouteTest.java",
+  "junit/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterSinkObservationTest.java",
+  "junit/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterTestBase.java",
+  "junit/src/org/chromium/chrome/browser/media/router/cast/CastMessageHandlerTest.java",
+  "junit/src/org/chromium/chrome/browser/media/router/cast/DiscoveryCallbackTest.java",
+  "junit/src/org/chromium/chrome/browser/media/router/cast/JSONTestUtils.java",
+  "junit/src/org/chromium/chrome/browser/media/router/cast/TestUtils.java",
+  "junit/src/org/chromium/chrome/browser/notifications/NotificationUIManagerUnitTest.java",
+  "junit/src/org/chromium/chrome/browser/ntp/NativePageFactoryTest.java",
+  "junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java",
+  "junit/src/org/chromium/chrome/browser/offlinepages/ClientIdTest.java",
+  "junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java",
+  "junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserverTest.java",
+  "junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java",
+  "junit/src/org/chromium/chrome/browser/omaha/ResponseParserTest.java",
+  "junit/src/org/chromium/chrome/browser/omaha/VersionNumberTest.java",
+  "junit/src/org/chromium/chrome/browser/snackbar/SnackbarCollectionUnitTest.java",
+  "junit/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProviderUnitTest.java",
+  "junit/src/org/chromium/chrome/browser/util/NonThreadSafeTest.java",
+  "junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java",
+  "junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java",
+]
+
+sync_shell_test_java_sources = [
+  "sync_shell/javatests/src/org/chromium/chrome/browser/sync/AutofillTest.java",
+  "sync_shell/javatests/src/org/chromium/chrome/browser/sync/BookmarksTest.java",
+  "sync_shell/javatests/src/org/chromium/chrome/browser/sync/FakeServerHelper.java",
+  "sync_shell/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java",
+  "sync_shell/javatests/src/org/chromium/chrome/browser/sync/GmsCoreSyncListenerTest.java",
+  "sync_shell/javatests/src/org/chromium/chrome/browser/sync/OpenTabsTest.java",
+  "sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java",
+  "sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java",
+  "sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTestBase.java",
+  "sync_shell/javatests/src/org/chromium/chrome/browser/sync/TypedUrlsTest.java",
+  "sync_shell/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java",
+]
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index e8bfe3d..723404c 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -1254,11 +1254,11 @@
   <message name="IDS_FLAGS_DISPLAY_COLOR_CALIBRATION_DESCRIPTION" desc="Description for the flag for the color calibration of the display.">
     Allow color calibration of the display if the display supports the feature.
   </message>
-  <message name="IDS_FLAGS_ENABLE_QUIRKS_CLIENT_NAME" desc="Name for the flag to enable the Quirks Client for calibration of the display and other hardware.">
-    Enable Quirks Client for display calibration.
+  <message name="IDS_FLAGS_DISABLE_QUIRKS_CLIENT_NAME" desc="Name for the flag to disable the Quirks Client for calibration of the display and other hardware.">
+    Disable Quirks Client for display calibration.
   </message>
-  <message name="IDS_FLAGS_ENABLE_QUIRKS_CLIENT_DESCRIPTION" desc="Description for the flag to enable the Quirks Client for calibration of the display and other hardware.">
-    Enable retrieval of icc display files from Quirks Server for display color calibration.
+  <message name="IDS_FLAGS_DISABLE_QUIRKS_CLIENT_DESCRIPTION" desc="Description for the flag to disable the Quirks Client for calibration of the display and other hardware.">
+    Disable retrieval of icc display files from Quirks Server for display color calibration.
   </message>
   <message name="IDS_FLAGS_MEMORY_PRESSURE_THRESHOLD_NAME" desc="Name for the flag which specifies which memory pressure strategy should be used on ChromeOS.">
     Memory discard strategy for advanced pressure handling
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 906ab3c..39b7e10 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5780,6 +5780,12 @@
       <message name="IDS_FLAGS_EXPERIMENTAL_WEB_PLATFORM_FEATURES_DESCRIPTION" desc="Description for the flag to enable experimental Web Platform features.">
         Enables experimental Web Platform features that are in development.
       </message>
+      <message name="IDS_FLAGS_EXPERIMENTAL_POINTER_EVENT_NAME" desc="Name for the flag to enable the experimental pointer events.">
+        Pointer Events
+      </message>
+      <message name="IDS_FLAGS_EXPERIMENTAL_POINTER_EVENT_DESCRIPTION" desc="Description for the flag to enable the experimental pointer events.">
+        Enables partial experimental support for the Pointer Events API.  This is intended only for testing by web developers, it will cause some websites to be subtly broken.
+      </message>
       <message name="IDS_FLAGS_EXPERIMENTAL_FRAMEWORK_NAME" desc="Name for the flag to enable the Experimental Framework.">
         Experimental Framework.
       </message>
@@ -11652,6 +11658,9 @@
         <message name="IDS_NOTIFICATION_BUTTON_CLOSE" desc="Button label to close a notification">
           Close
         </message>
+        <message name="IDS_NOTIFICATION_BUTTON_OPTIONS" desc="Button label to display more options like extra buttons or going to the site settings page.">
+          Options
+        </message>
         <message name="IDS_NOTIFICATION_SETTINGS" desc="Button label to go to the notification settings panel">
           Notification settings
         </message>
@@ -12922,7 +12931,7 @@
           Sorry, your password could not be verified because you are offline.
         </message>
         <message name="IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT" desc="Text to display in the password field for user pod when no password has been entered.">
-          Enter password
+          Password
         </message>
         <message name="IDS_LOGIN_POD_SIGNING_IN" desc="Text to display at the bottom of a user pod during signing in the user. The translation should be as short as possible because of limited UI space.">
           Signing in
@@ -12973,19 +12982,19 @@
           </message>
           <message name="IDS_LOGIN_POD_USER_REMOVE_WARNING_SYNC" desc="Main text shown as a warning when attempting to remove an user. This case is for synced profiles, with all statistics loaded correctly. The symbol $1 will be substituted with custom JS code, so it should not be replaced by a #.">
             {NUM_ITEMS, plural,
-            =1 {This will permanently delete $1 item from this device but will not clear synced items from other devices.}
-            other {This will permanently delete $1 items from this device but will not clear synced items from other devices.}}
+            =1 {This will permanently delete $1 item from this device. To retrieve your data later, sign in to chrome as $2.}
+            other {This will permanently delete $1 items from this device. To retrieve your data later, sign in to chrome as $2.}}
           </message>
           <message name="IDS_LOGIN_POD_USER_REMOVE_WARNING_SYNC_WITH_ERRORS" desc="Main text shown as a warning when attempting to remove an user. This case is for non-synced profiles, with some statistics failed to load. The symbol $1 will be substituted with custom JS code, so it should not be replaced by a #.">
             {NUM_ITEMS, plural,
-            =1 {This will permanently delete at least $1 item from this device but will not clear synced items from other devices.}
-            other {This will permanently delete at least $1 items from this device but will not clear synced items from other devices.}}
+            =1 {This will permanently delete at least $1 item from this device. To retrieve your data later, sign in to chrome as $2.}
+            other {This will permanently delete at least $1 items from this device. To retrieve your data later, sign in to chrome as $2.}}
           </message>
           <message name="IDS_LOGIN_POD_USER_REMOVE_WARNING_SYNC_NOSTATS" desc="Main text shown as a warning when attempting to remove an user. This case is for synced profiles with statistics unavailable. (Possible case: Chromium decided not to load the statistics of closed profiles.)">
-            This will permanently delete your browsing data from this device but will not clear synced items from other devices.
+            This will permanently delete your browsing data from this device. To retrieve your data later, sign in to chrome as $2.
           </message>
           <message name="IDS_LOGIN_POD_USER_REMOVE_WARNING_SYNC_CALCULATING" desc="Main text shown as a warning when attempting to remove an user. This case is for synced profiles when the statistics is still loading. $1 is always replaced by localized version of the ellipsis (...).">
-            This will permanently delete at least <ph name="TOTAL_COUNT">$1<ex>...</ex></ph> items from this device but will not clear synced items from other devices.
+            This will permanently delete at least <ph name="TOTAL_COUNT">$1<ex>...</ex></ph> items from this device. To retrieve your data later, sign in to chrome as $2.
           </message>
         </if>
 
@@ -14302,7 +14311,6 @@
       <message name="IDS_FLAGS_TOUCH_HOVER_DESCRIPTION" desc="Description of the 'Enable support for hover capable touchscreens' flag.">
         Enables hover feature by holding your finger just over the screen to experience a mouseover event.
       </message>
-
       <message name="IDS_ALLOW_INSECURE_LOCALHOST" desc="Name of the 'Allow insecure localhost' flag.">
         Allow invalid certificates for resources loaded from localhost.
       </message>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 39ca6ce..13471af 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -827,9 +827,9 @@
             ui::switches::kDisableDisplayColorCalibration),
     },
     {
-        "enable-quirks-client", IDS_FLAGS_ENABLE_QUIRKS_CLIENT_NAME,
-        IDS_FLAGS_ENABLE_QUIRKS_CLIENT_DESCRIPTION, kOsCrOS,
-        SINGLE_VALUE_TYPE(quirks::switches::kEnableQuirksClient),
+        "disable-quirks-client", IDS_FLAGS_DISABLE_QUIRKS_CLIENT_NAME,
+        IDS_FLAGS_DISABLE_QUIRKS_CLIENT_DESCRIPTION, kOsCrOS,
+        SINGLE_VALUE_TYPE(quirks::switches::kDisableQuirksClient),
     },
     {
         "ash-disable-screen-orientation-lock",
@@ -1819,6 +1819,11 @@
      IDS_FLAGS_MEDIA_STYLE_NOTIFICATION_DESCRIPTION, kOsAndroid,
      FEATURE_VALUE_TYPE(chrome::android::kMediaStyleNotification)},
 #endif
+    {"enable-pointer-events",  // FLAGS:RECORD_UMA
+      IDS_FLAGS_EXPERIMENTAL_POINTER_EVENT_NAME,
+      IDS_FLAGS_EXPERIMENTAL_POINTER_EVENT_DESCRIPTION,
+      kOsAll,
+      FEATURE_VALUE_TYPE(features::kPointerEvents)},
     // NOTE: Adding new command-line switches requires adding corresponding
     // entries to enum "LoginCustomFlags" in histograms.xml. See note in
     // histograms.xml and don't forget to run AboutFlagsHistogramTest unit test.
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index fd2692d..adaaf16b 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -141,7 +141,10 @@
   ]
   if (use_x11) {
     configs += [ "//build/config/linux:x11" ]
-    deps += [ "//ui/events/devices" ]
+    deps += [
+      "//ui/events/devices",
+      "//ui/events/devices/x11",
+    ]
     sources -= [
       "system/input_device_settings_impl_ozone.cc",
       "system_logs/touch_log_source_ozone.cc",
diff --git a/chrome/browser/chromeos/display/quirks_browsertest.cc b/chrome/browser/chromeos/display/quirks_browsertest.cc
index bd1489d..ed64aaa 100644
--- a/chrome/browser/chromeos/display/quirks_browsertest.cc
+++ b/chrome/browser/chromeos/display/quirks_browsertest.cc
@@ -2,13 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/quirks/quirks_manager.h"
-#include "components/quirks/switches.h"
 #include "content/public/test/test_utils.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 
@@ -83,11 +81,6 @@
     end_message_loop_.Run();
   }
 
-  // InProcessBrowserTest overrides.
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitch(switches::kEnableQuirksClient);
-  }
-
   void SetUpOnMainThread() override {
     // NOTE: QuirksManager::Initialize() isn't necessary here, since it'll be
     // called in ChromeBrowserMainPartsChromeos::PreMainMessageLoopRun().
diff --git a/chrome/browser/chromeos/policy/device_quirks_policy_browsertest.cc b/chrome/browser/chromeos/policy/device_quirks_policy_browsertest.cc
index 265b003..e7097e05 100644
--- a/chrome/browser/chromeos/policy/device_quirks_policy_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_quirks_policy_browsertest.cc
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
@@ -10,7 +9,6 @@
 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "components/quirks/quirks_manager.h"
-#include "components/quirks/switches.h"
 #include "content/public/test/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -24,10 +22,6 @@
  public:
   DeviceQuirksPolicyTest() {}
 
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitch(quirks::switches::kEnableQuirksClient);
-  }
-
   void SetUpInProcessBrowserTestFixture() override {
     InstallOwnerKey();
     DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
diff --git a/chrome/browser/notifications/notification_ui_manager_mac.mm b/chrome/browser/notifications/notification_ui_manager_mac.mm
index 74023f7..ef595dbf 100644
--- a/chrome/browser/notifications/notification_ui_manager_mac.mm
+++ b/chrome/browser/notifications/notification_ui_manager_mac.mm
@@ -147,8 +147,8 @@
       DCHECK(
           [toast respondsToSelector:@selector(_alternateActionButtonTitles)]);
 
-      // utf8 ellipsis:
-      [toast setActionButtonTitle:@"\u2026"];
+      [toast setActionButtonTitle:l10n_util::GetNSString(
+                                      IDS_NOTIFICATION_BUTTON_OPTIONS)];
       [toast setValue:@YES
                forKey:@"_alwaysShowAlternateActionMenu"];
 
diff --git a/chrome/browser/resources/md_user_manager/user_manager.js b/chrome/browser/resources/md_user_manager/user_manager.js
index caaf404f..6864f2c 100644
--- a/chrome/browser/resources/md_user_manager/user_manager.js
+++ b/chrome/browser/resources/md_user_manager/user_manager.js
@@ -6,6 +6,7 @@
 <include src="../../../../ui/login/bubble.js">
 <include src="../../../../ui/login/login_ui_tools.js">
 <include src="../../../../ui/login/display_manager.js">
+<include src="../../../../ui/login/account_picker/user_pod_template.js">
 <include src="../../../../ui/login/account_picker/screen_account_picker.js">
 <include src="../../../../ui/login/account_picker/user_pod_row.js">
 
@@ -14,6 +15,13 @@
   var DisplayManager = cr.ui.login.DisplayManager;
 
   /**
+   * Maximum possible height of the #login-header-bar, including the padding
+   * and the border.
+   * @const {number}
+   */
+  var MAX_LOGIN_HEADER_BAR_HEIGHT = 57;
+
+  /**
    * Manages initialization of screens, transitions, and error messages.
    * @constructor
    * @extends {DisplayManager}
@@ -24,6 +32,28 @@
 
   UserManager.prototype = {
     __proto__: DisplayManager.prototype,
+
+    /**
+     * Indicates that this is the Material Design Desktop User Manager.
+     * @type {boolean}
+     */
+    newDesktopUserManager: true,
+
+    /**
+     * @override
+     * Overrides clientAreaSize in DisplayManager. When a new profile is created
+     * the #outer-container page may not be visible yet, so user-pods cannot be
+     * placed correctly. Therefore, we use dimensions of the #animated-pages.
+     * @type {{width: number, height: number}}
+     */
+    get clientAreaSize() {
+      var userManagerPages = document.querySelector('user-manager-pages');
+      var width = userManagerPages.offsetWidth;
+      // Deduct the maximum possible height of the #login-header-bar from the
+      // height of #animated-pages. Result is the remaining visible height.
+      var height = userManagerPages.offsetHeight - MAX_LOGIN_HEADER_BAR_HEIGHT;
+      return {width: width, height: height};
+    }
   };
 
   /**
diff --git a/chrome/browser/resources/md_user_manager/user_manager_styles.html b/chrome/browser/resources/md_user_manager/user_manager_styles.html
index 7b0785b..200aad4 100644
--- a/chrome/browser/resources/md_user_manager/user_manager_styles.html
+++ b/chrome/browser/resources/md_user_manager/user_manager_styles.html
@@ -4,10 +4,10 @@
   <template>
     <style include="shared-styles">
       body {
-        background-color: #eee;
+        background-color: var(--paper-grey-200);
       }
 
-      /* Overrides for the desktop user manager screen. */
+      user-manager-pages,
       #login-header-bar {
         bottom: 0;
         left: 0;
@@ -15,8 +15,24 @@
         right: 0;
       }
 
+      user-manager-pages {
+        top: 0;
+      }
+
+      #login-header-bar.shadow {
+        box-shadow: 0 -1px 3px rgba(0, 0, 0, .2);
+      }
+
+      /* Overrides src/ui/login/screen_container.css for the desktop user
+       * manager. */
+
       #outer-container {
         min-height: 0;
+        overflow-x: hidden;
+        overflow-y: auto;
+        padding-bottom: 40px;
+        padding-top: 40px;
+        z-index: initial;
       }
 
       .bubble.faded {
@@ -24,193 +40,235 @@
       }
 
       .pod {
-        box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
-        height: 226px;
-        /* On non-retina desktop, the text is blurry if we use the scale3d()
-        inherited from user_pod_row.js */
-        transform: scale(0.9);
+        box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .24),
+                    0 0 2px 0 rgba(0, 0, 0, .12);
+        color: var(--paper-grey-800);
+        cursor: default;
+        height: auto;
+        transform: none;
+        width: auto;
       }
 
-      podrow[ncolumns='6'] .pod {
-        transform: scale(0.8);
-      }
-
-      /* Because of crbug.com/406529, the text in the .name div is janky if there's
-      both a transform:scale and a transition:opacity applied to a div, so we must
-      apply the opacity change to the children instead. */
       .pod.faded {
         opacity: 1;
       }
 
-      .pod.faded .user-image-pane,
-      .pod.faded .main-pane {
-        opacity: .4;
-      }
-
-      .pod.hovered:not(.focused) {
-        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
-      }
-
-      .pod.focused {
-        box-shadow: 0 16px 21px rgba(0, 0, 0, 0.2);
-        transform: scale(1) !important;
+      .pod.focused,
+      .pod.hovered {
+        box-shadow: 0 10px 10px 0 rgba(0, 0, 0, .26),
+                    0 14px 28px 0 rgba(0, 0, 0, .25);
       }
 
       .pod.focused.locked {
-        box-shadow: 0 12px 21px rgba(0, 0, 0, 0.2);
-        height: 220px;
+        box-shadow: 0 12px 21px rgba(0, 0, 0, .2);
+        height: auto;
       }
 
-      .user-image-pane {
+      .pod .user-image-pane {
         border-top-left-radius: 2px;
         border-top-right-radius: 2px;
-        height: 180px;
-        left: 0;
-        top: 0;
-        width: 180px;
-      }
-
-      html[dir=rtl] .user-image-pane {
-        right: 0;
-      }
-
-      .pod .name {
-        margin-top: 12px;
+        position: static;
       }
 
       .pod .user-image {
-        height: 180px;
-        width: 180px;
+        height: 160px;
+        width: 160px;
       }
 
-      .pod input[type='password'] {
-        height: 45px;  /* 1px shorter as to not overlap the pod's rounded corners */
-        top: 1px;
+      .pod .main-pane {
+        line-height: 20px;
+        padding: 10px;
+        position: static;
+      }
+
+      .pod .main-pane .name-container {
+        display: block;
+        position: static;
+        width: auto;
+      }
+
+      .pod .main-pane .name-container .name {
+        color: inherit;
+        font-size: inherit;
+        margin: 0;
+        padding: 0;
+        text-align: initial;
+        width: 118px;
       }
 
       .pod .indicator-container {
-        background-color: rgba(255, 255, 255, 0.85);
-        border-radius: 16px;
-        height: 32px;
-        left: 8px;
-        position: absolute;
-        top: 8px;
-      }
-
-      html[dir=rtl] .pod .indicators {
+        background-color: rgba(255, 255, 255, .85);
+        border-radius: 0;
+        bottom: 10px;
+        height: 20px;
         left: auto;
-        right: 8px;
+        position: absolute;
+        right: 10px;
+        top: auto;
+        width: 20px;
       }
 
-      .pod .indicator {
+      html[dir='rtl'] .pod .indicator-container {
+        left: 10px;
+        right: auto;
+      }
+
+      /* Using -webkit-mask on the indicators allows us to tweak the color. */
+      .pod .indicator-container > .indicator {
+        -webkit-mask-position: center;
+        -webkit-mask-repeat: no-repeat;
+        -webkit-mask-size: 20px;
+        background-color: var(--paper-grey-600);
         background-position: center;
         background-repeat: no-repeat;
         background-size: 18px;
         display: none;
         float: left;
-        height: 32px;
-        width: 32px;
-      }
-
-      /* Using -webkit-mask on the indicators allows us to tweak the color. */
-      .pod .indicator-container > div {
-        -webkit-mask-position: center;
-        -webkit-mask-repeat: no-repeat;
-        -webkit-mask-size: 24px;
+        height: 20px;
+        width: 20px;
       }
 
       .pod.locked .locked-indicator {
         -webkit-mask-image: url(../../../../ui/webui/resources/images/lock.svg);
-        background-color: var(--paper-grey-600);
         display: initial;
       }
 
       .pod.legacy-supervised .legacy-supervised-indicator {
         -webkit-mask-image:
             url(../../../../ui/webui/resources/images/supervisor_account.svg);
-        background-color: var(--google-blue-500);
         display: initial;
       }
 
       .pod.child .child-indicator {
         -webkit-mask-image:
             url(../../../../ui/webui/resources/images/account_child_invert.svg);
-        background-color: var(--google-blue-500);
         display: initial;
       }
 
-      .main-pane {
-        left: 0;
+      .action-box-area:focus ~ .user-image-gradient-area,
+      .action-box-area.hovered ~ .user-image-gradient-area {
+        background-image: linear-gradient(rgba(0, 0, 0, .4), transparent 100%);
+        display: initial;
+        height: 56px;
+        position: absolute;
         top: 0;
+        width: 100%;
       }
 
-      html[dir=rtl] .main-pane {
-        right: 0;
+      .action-box-area {
+        background-color: transparent;
       }
 
-      .name-container,
-      .pod.focused:not(.multiprofiles-policy-applied) .auth-container {
-        top: 180px;
-        width: 180px;
+      .action-box-area.menu-moved-up {
+        transform: none;
       }
 
-      .pod.focused:not(.locked) .name-container {
-        display: block;
+      .action-box-area .action-box-button {
+        display: none;
       }
 
-      .pod .name {
-        color: var(--paper-grey-800);
-        font-size: 15px;
-        margin-top: 11px;
+      .action-box-area .action-box-icon {
+        color: white;
+        display: inline-flex;
+        margin-top: 4px;
       }
 
       .pod.focused:not(.locked) .auth-container {
         display: none;
       }
 
-      .pod[auth-type='offlinePassword'].focused.locked .password-entry-container {
-        display: flex;
-        flex: auto;
+      .pod.focused:not(.multiprofiles-policy-applied) .auth-container {
+        left: 0;
       }
 
-      .action-box-area {
-        background-color: var(--google-grey-100);
-        height: 24px;
-        /* Because of crbug.com/406529, the text in the .name div is janky if there's
-        an opacity transition in this div. */
-        transition: none;
-        width: 24px;
+      .pod .auth-container input[type='password'] {
+        line-height: inherit;
+        padding: 10px;
+        top: 0;
+        width: 140px;
       }
 
-      .action-box-button,
-      .action-box-button:hover,
-      .action-box-area.active .action-box-button {
-        background-image: none;
-        border-left: 6px solid transparent;
-        border-right: 6px solid transparent;
-        border-top: 6px solid #989898;
-        height: 0;
-        left: 6px;
+      .pod .auth-container input[type='password']:focus {
+        outline: 0;
+      }
+
+      .pod[auth-type='onlineSignIn'] .reauth-hint-container {
         margin: 0;
-        position: absolute;
-        top: 9px;
-        width: 0;
+        padding: 10px 0;
       }
 
-      .action-box-button:hover,
+      .reauth-hint-container .reauth-warning {
+        height: 20px;
+        width: 20px;
+      }
+
+      .reauth-hint-container .reauth-name-hint {
+        color: inherit;
+        font-size: inherit;
+      }
+
       .action-box-area.active .action-box-button {
-        border-top: 6px solid #4c4c4c;
+        display: none;
+      }
+
+      .action-box-area.active ~ .action-box-menu:not(.menu-moved-up) {
+        top: 8px;
+      }
+
+      .action-box-area.active ~ .action-box-menu {
+        border: none;
+        box-shadow: 0 10px 20px 0 rgba(0, 0, 0, .19);
+        right: 8px;
+        width: 224px;
+      }
+
+      html[dir=rtl] .action-box-area.active ~ .action-box-menu {
+        left: 8px;
+        right: auto;
+      }
+
+      .action-box-menu-title {
+        color: inherit;
+        padding: 16px 12px;
+      }
+
+      .action-box-menu-title-name,
+      .action-box-menu-title-email {
+        height: auto;
+      }
+
+      .action-box-menu-title-email {
+        color: var(--paper-grey-600);
+      }
+
+      .action-box-menu-remove {
+        border-top: 1px solid rgba(0, 0, 0, .12);
+        line-height: 32px;
+        padding: 8px 12px;
+      }
+
+      .action-box-remove-user-warning {
+        border-top: 1px solid rgba(0, 0, 0, .12);
+        font-size: inherit;
+        line-height: 20px;
+        padding: 12px;
+        text-align: center;
+      }
+
+      .action-box-remove-user-warning > * {
+        text-align: initial;
+        word-wrap: break-word;
+      }
+
+      .total-count,
+      .pod:not(.synced) .action-box-remove-user-warning-text {
+        font-weight: 500;
       }
 
       .action-box-remove-user-warning .remove-warning-button {
-        height: 30px;
-      }
-
-      .action-box-remove-user-warning .remove-warning-button:focus {
-        /* Override the default blue border inherited from
-        button.custom-appearance:focus. */
-        border: 1px solid transparent !important;
-        box-shadow: inset 0 0 0 1px #fff;
+        background: var(--google-red-700);
+        min-width: 72px;
+        width: auto;
       }
     </style>
   </template>
diff --git a/chrome/browser/resources/user_manager/user_manager.css b/chrome/browser/resources/user_manager/user_manager.css
index eb3801f..3b76f2f 100644
--- a/chrome/browser/resources/user_manager/user_manager.css
+++ b/chrome/browser/resources/user_manager/user_manager.css
@@ -199,10 +199,3 @@
 .action-box-remove-user-warning .remove-warning-button {
   height: 30px;
 }
-
-.action-box-remove-user-warning .remove-warning-button:focus {
-  /* Override the default blue border inherited from
-  button.custom-appearance:focus. */
-  border: 1px solid transparent !important;
-  box-shadow: inset 0 0 0 1px #fff;
-}
diff --git a/chrome/browser/resources/user_manager/user_manager.js b/chrome/browser/resources/user_manager/user_manager.js
index 96ddf65..86c7ac8 100644
--- a/chrome/browser/resources/user_manager/user_manager.js
+++ b/chrome/browser/resources/user_manager/user_manager.js
@@ -6,6 +6,7 @@
 <include src="../../../../ui/login/login_ui_tools.js">
 <include src="../../../../ui/login/display_manager.js">
 <include src="control_bar.js">
+<include src="../../../../ui/login/account_picker/user_pod_template.js">
 <include src="../../../../ui/login/account_picker/screen_account_picker.js">
 <include src="../../../../ui/login/account_picker/user_pod_row.js">
 <include src="../../../../ui/login/resource_loader.js">
diff --git a/chrome/browser/ui/webui/options/chromeos/bluetooth_options_browsertest.js b/chrome/browser/ui/webui/options/chromeos/bluetooth_options_browsertest.js
index cf1c0e7..7dcf876 100644
--- a/chrome/browser/ui/webui/options/chromeos/bluetooth_options_browsertest.js
+++ b/chrome/browser/ui/webui/options/chromeos/bluetooth_options_browsertest.js
@@ -312,7 +312,8 @@
   }.bind(this));
 });
 
-TEST_F('BluetoothWebUITestAsync', 'testForget', function() {
+// TODO(crbug.com/605090): Disabled because of flakiness.
+TEST_F('BluetoothWebUITestAsync', 'DISABLED_testForget', function() {
   assertEquals(this.browsePreload, document.location.href);
 
   // Enable bluetooth.
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index 69f8e8e..a8690ab 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -3292,6 +3292,7 @@
                 '../build/linux/system.gyp:x11',
                 '../build/linux/system.gyp:gio',
                 '../ui/events/devices/events_devices.gyp:events_devices',
+                '../ui/events/devices/x11/events_devices_x11.gyp:events_devices_x11',
               ],
             }],
             ['use_udev==1', {
diff --git a/chrome/chrome_gpu.gypi b/chrome/chrome_gpu.gypi
index 3241e11..3d153e3 100644
--- a/chrome/chrome_gpu.gypi
+++ b/chrome/chrome_gpu.gypi
@@ -26,6 +26,8 @@
             '../components/components.gyp:arc_mojo_bindings',
           ],
           'sources': [
+            'gpu/arc_gpu_video_decode_accelerator.cc',
+            'gpu/arc_gpu_video_decode_accelerator.h',
             'gpu/arc_video_accelerator.h',
             'gpu/gpu_arc_video_service.cc',
             'gpu/gpu_arc_video_service.h',
diff --git a/chrome/common/OWNERS b/chrome/common/OWNERS
index 0d1d0612..849bf4d8 100644
--- a/chrome/common/OWNERS
+++ b/chrome/common/OWNERS
@@ -37,6 +37,7 @@
 # Instant/Search files.
 per-file instant_types*=file://chrome/browser/search/OWNERS
 per-file search_types.*=file://chrome/browser/search/OWNERS
+per-file search_urls*=file://chrome/browser/search/OWNERS
 
 #Content settings
 per-file content_settings*=markusheintz@chromium.org
diff --git a/chrome/common/search_urls.h b/chrome/common/search_urls.h
index c4bbacd..8840b5f2 100644
--- a/chrome/common/search_urls.h
+++ b/chrome/common/search_urls.h
@@ -9,7 +9,11 @@
 
 namespace search {
 
-// Returns true if |my_url| matches |other_url|.
+// Returns true if |my_url| matches |other_url| in terms of origin (i.e. host,
+// port, and scheme) and path. As a special case, this also matches if |my_url|
+// is "https://" and |other_url| is "http://" (and host, port, and path match).
+// This is so that "https://" URLs will be considered "Instant URLs" even if the
+// default search provider URL is "http://".
 bool MatchesOriginAndPath(const GURL& my_url, const GURL& other_url);
 
 }  // namespace search
diff --git a/chrome/gpu/BUILD.gn b/chrome/gpu/BUILD.gn
index 8ce64935..384b4186 100644
--- a/chrome/gpu/BUILD.gn
+++ b/chrome/gpu/BUILD.gn
@@ -16,6 +16,8 @@
   if (is_chromeos) {
     deps += [ "//components/arc:arc_bindings" ]
     sources += [
+      "arc_gpu_video_decode_accelerator.cc",
+      "arc_gpu_video_decode_accelerator.h",
       "arc_video_accelerator.h",
       "gpu_arc_video_service.cc",
       "gpu_arc_video_service.h",
diff --git a/chrome/gpu/arc_gpu_video_decode_accelerator.cc b/chrome/gpu/arc_gpu_video_decode_accelerator.cc
new file mode 100644
index 0000000..a2700b1e
--- /dev/null
+++ b/chrome/gpu/arc_gpu_video_decode_accelerator.cc
@@ -0,0 +1,425 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/callback_helpers.h"
+#include "base/logging.h"
+#include "base/run_loop.h"
+#include "chrome/gpu/arc_gpu_video_decode_accelerator.h"
+#include "content/public/gpu/gpu_video_decode_accelerator_factory.h"
+#include "media/base/video_frame.h"
+
+namespace chromeos {
+namespace arc {
+
+ArcGpuVideoDecodeAccelerator::InputRecord::InputRecord(
+    int32_t bitstream_buffer_id,
+    uint32_t buffer_index,
+    int64_t timestamp)
+    : bitstream_buffer_id(bitstream_buffer_id),
+      buffer_index(buffer_index),
+      timestamp(timestamp) {}
+
+ArcGpuVideoDecodeAccelerator::InputBufferInfo::InputBufferInfo()
+    : offset(0), length(0) {}
+
+ArcGpuVideoDecodeAccelerator::InputBufferInfo::InputBufferInfo(
+    InputBufferInfo&& other)
+    : handle(std::move(other.handle)),
+      offset(other.offset),
+      length(other.length) {}
+
+ArcGpuVideoDecodeAccelerator::InputBufferInfo::~InputBufferInfo() {}
+
+ArcGpuVideoDecodeAccelerator::ArcGpuVideoDecodeAccelerator()
+    : pending_eos_output_buffer_(false),
+      arc_client_(nullptr),
+      next_bitstream_buffer_id_(0),
+      output_buffer_size_(0) {}
+
+ArcGpuVideoDecodeAccelerator::~ArcGpuVideoDecodeAccelerator() {}
+
+namespace {
+
+// An arbitrary chosen limit of the number of buffers. The number of
+// buffers used is requested from the untrusted client side.
+const size_t kMaxBufferCount = 128;
+
+}  // anonymous namespace
+
+bool ArcGpuVideoDecodeAccelerator::Initialize(
+    const Config& config,
+    ArcVideoAccelerator::Client* client) {
+  DVLOG(5) << "Initialize(device=" << config.device_type
+           << ", input_pixel_format=" << config.input_pixel_format
+           << ", num_input_buffers=" << config.num_input_buffers << ")";
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (config.device_type != Config::DEVICE_DECODER)
+    return false;
+  DCHECK(client);
+
+  if (arc_client_) {
+    DLOG(ERROR) << "Re-Initialize() is not allowed";
+    return false;
+  }
+
+  arc_client_ = client;
+
+  if (config.num_input_buffers > kMaxBufferCount) {
+    DLOG(ERROR) << "Request too many buffers: " << config.num_input_buffers;
+    return false;
+  }
+  input_buffer_info_.resize(config.num_input_buffers);
+
+  media::VideoDecodeAccelerator::Config vda_config;
+  switch (config.input_pixel_format) {
+    case HAL_PIXEL_FORMAT_H264:
+      vda_config.profile = media::H264PROFILE_MAIN;
+      break;
+    case HAL_PIXEL_FORMAT_VP8:
+      vda_config.profile = media::VP8PROFILE_ANY;
+      break;
+    default:
+      DLOG(ERROR) << "Unsupported input format: " << config.input_pixel_format;
+      return false;
+  }
+  vda_config.output_mode =
+      media::VideoDecodeAccelerator::Config::OutputMode::IMPORT;
+
+  scoped_ptr<content::GpuVideoDecodeAcceleratorFactory> vda_factory =
+      content::GpuVideoDecodeAcceleratorFactory::CreateWithNoGL();
+  vda_ = vda_factory->CreateVDA(this, vda_config);
+  if (!vda_) {
+    DLOG(ERROR) << "Failed to create VDA.";
+    return false;
+  }
+  return true;
+}
+
+void ArcGpuVideoDecodeAccelerator::SetNumberOfOutputBuffers(size_t number) {
+  DVLOG(5) << "SetNumberOfOutputBuffers(" << number << ")";
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (!vda_) {
+    DLOG(ERROR) << "VDA not initialized";
+    return;
+  }
+
+  if (number > kMaxBufferCount) {
+    DLOG(ERROR) << "Too many buffers: " << number;
+    arc_client_->OnError(INVALID_ARGUMENT);
+    return;
+  }
+
+  std::vector<media::PictureBuffer> buffers;
+  for (size_t id = 0; id < number; ++id) {
+    media::PictureBuffer::TextureIds texture_ids;
+    texture_ids.push_back(0);
+
+    // TODO(owenlin): Make sure the |coded_size| is what we want.
+    buffers.push_back(media::PictureBuffer(base::checked_cast<int32_t>(id),
+                                           coded_size_, texture_ids));
+  }
+  vda_->AssignPictureBuffers(buffers);
+
+  buffers_pending_import_.clear();
+  buffers_pending_import_.resize(number);
+}
+
+void ArcGpuVideoDecodeAccelerator::BindSharedMemory(PortType port,
+                                                    uint32_t index,
+                                                    base::ScopedFD ashmem_fd,
+                                                    off_t offset,
+                                                    size_t length) {
+  DVLOG(5) << "ArcGVDA::BindSharedMemory, offset: " << offset
+           << ", length: " << length;
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (!vda_) {
+    DLOG(ERROR) << "VDA not initialized";
+    return;
+  }
+
+  if (port != PORT_INPUT) {
+    DLOG(ERROR) << "SharedBuffer is only supported for input";
+    arc_client_->OnError(INVALID_ARGUMENT);
+    return;
+  }
+  if (!ValidatePortAndIndex(port, index)) {
+    arc_client_->OnError(INVALID_ARGUMENT);
+    return;
+  }
+  InputBufferInfo* input_info = &input_buffer_info_[index];
+  input_info->handle = std::move(ashmem_fd);
+  input_info->offset = offset;
+  input_info->length = length;
+}
+
+void ArcGpuVideoDecodeAccelerator::BindDmabuf(PortType port,
+                                              uint32_t index,
+                                              base::ScopedFD dmabuf_fd) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  if (!vda_) {
+    DLOG(ERROR) << "VDA not initialized";
+    return;
+  }
+
+  if (port != PORT_OUTPUT) {
+    DLOG(ERROR) << "Dmabuf is only supported for input";
+    arc_client_->OnError(INVALID_ARGUMENT);
+    return;
+  }
+  if (!ValidatePortAndIndex(port, index)) {
+    arc_client_->OnError(INVALID_ARGUMENT);
+    return;
+  }
+  buffers_pending_import_[index] = std::move(dmabuf_fd);
+}
+
+void ArcGpuVideoDecodeAccelerator::UseBuffer(PortType port,
+                                             uint32_t index,
+                                             const BufferMetadata& metadata) {
+  DVLOG(5) << "UseBuffer(port=" << port << ", index=" << index
+           << ", metadata=(bytes_used=" << metadata.bytes_used
+           << ", timestamp=" << metadata.timestamp << ")";
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (!vda_) {
+    DLOG(ERROR) << "VDA not initialized";
+    return;
+  }
+  if (!ValidatePortAndIndex(port, index)) {
+    arc_client_->OnError(INVALID_ARGUMENT);
+    return;
+  }
+  switch (port) {
+    case PORT_INPUT: {
+      InputBufferInfo* input_info = &input_buffer_info_[index];
+      int32_t bitstream_buffer_id = next_bitstream_buffer_id_;
+      // Mask against 30 bits, to avoid (undefined) wraparound on signed
+      // integer.
+      next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
+      int dup_fd = HANDLE_EINTR(dup(input_info->handle.get()));
+      if (dup_fd < 0) {
+        DLOG(ERROR) << "dup() failed.";
+        arc_client_->OnError(PLATFORM_FAILURE);
+        return;
+      }
+      CreateInputRecord(bitstream_buffer_id, index, metadata.timestamp);
+      vda_->Decode(media::BitstreamBuffer(
+          bitstream_buffer_id, base::SharedMemoryHandle(dup_fd, true),
+          metadata.bytes_used, input_info->offset));
+      if (metadata.flags & BUFFER_FLAG_EOS) {
+        vda_->Flush();
+      }
+      break;
+    }
+    case PORT_OUTPUT: {
+      SendEosIfNeededOrReusePicture(index);
+      break;
+    }
+    default:
+      NOTREACHED();
+  }
+}
+
+void ArcGpuVideoDecodeAccelerator::Reset() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (!vda_) {
+    DLOG(ERROR) << "VDA not initialized";
+    return;
+  }
+  vda_->Reset();
+}
+
+void ArcGpuVideoDecodeAccelerator::ProvidePictureBuffers(
+    uint32_t requested_num_of_buffers,
+    uint32_t textures_per_buffer,
+    const gfx::Size& dimensions,
+    uint32_t texture_target) {
+  DVLOG(5) << "ProvidePictureBuffers("
+           << "requested_num_of_buffers=" << requested_num_of_buffers
+           << ", dimensions=" << dimensions.ToString() << ")";
+  DCHECK(thread_checker_.CalledOnValidThread());
+  coded_size_ = dimensions;
+
+  VideoFormat video_format;
+  media::VideoPixelFormat output_format = vda_->GetOutputFormat();
+  switch (output_format) {
+    case media::PIXEL_FORMAT_I420:
+    case media::PIXEL_FORMAT_YV12:
+    case media::PIXEL_FORMAT_NV12:
+    case media::PIXEL_FORMAT_NV21:
+      // HAL_PIXEL_FORMAT_YCbCr_420_888 is the flexible pixel format in Android
+      // which handles all 420 formats, with both orderings of chroma (CbCr and
+      // CrCb) as well as planar and semi-planar layouts.
+      video_format.pixel_format = HAL_PIXEL_FORMAT_YCbCr_420_888;
+      break;
+    default:
+      DLOG(ERROR) << "Format not supported: " << output_format;
+      arc_client_->OnError(PLATFORM_FAILURE);
+      return;
+  }
+  video_format.buffer_size =
+      media::VideoFrame::AllocationSize(output_format, coded_size_);
+  output_buffer_size_ = video_format.buffer_size;
+  video_format.min_num_buffers = requested_num_of_buffers;
+  video_format.coded_width = dimensions.width();
+  video_format.coded_height = dimensions.height();
+  // TODO(owenlin): How to get visible size?
+  video_format.crop_top = 0;
+  video_format.crop_left = 0;
+  video_format.crop_width = dimensions.width();
+  video_format.crop_height = dimensions.height();
+  arc_client_->OnOutputFormatChanged(video_format);
+}
+
+void ArcGpuVideoDecodeAccelerator::DismissPictureBuffer(
+    int32_t picture_buffer) {
+  // no-op
+}
+
+void ArcGpuVideoDecodeAccelerator::PictureReady(const media::Picture& picture) {
+  DVLOG(5) << "PictureReady(picture_buffer_id=" << picture.picture_buffer_id()
+           << ", bitstream_buffer_id=" << picture.bitstream_buffer_id();
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  // Empty buffer, returned in Flushing.
+  if (picture.bitstream_buffer_id() == -1) {
+    buffers_pending_eos_.push(picture.picture_buffer_id());
+    return;
+  }
+  InputRecord* input_record = FindInputRecord(picture.bitstream_buffer_id());
+  if (input_record == nullptr) {
+    DLOG(ERROR) << "Cannot find for bitstream buffer id: "
+                << picture.bitstream_buffer_id();
+    arc_client_->OnError(PLATFORM_FAILURE);
+    return;
+  }
+
+  BufferMetadata metadata;
+  metadata.timestamp = input_record->timestamp;
+  metadata.bytes_used = output_buffer_size_;
+  arc_client_->OnBufferDone(PORT_OUTPUT, picture.picture_buffer_id(), metadata);
+}
+
+void ArcGpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
+    int32_t bitstream_buffer_id) {
+  DVLOG(5) << "NotifyEndOfBitstreamBuffer(" << bitstream_buffer_id << ")";
+  DCHECK(thread_checker_.CalledOnValidThread());
+  InputRecord* input_record = FindInputRecord(bitstream_buffer_id);
+  if (input_record == nullptr) {
+    arc_client_->OnError(PLATFORM_FAILURE);
+    return;
+  }
+  arc_client_->OnBufferDone(PORT_INPUT, input_record->buffer_index,
+                            BufferMetadata());
+}
+
+void ArcGpuVideoDecodeAccelerator::NotifyFlushDone() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  pending_eos_output_buffer_ = true;
+  while (!buffers_pending_eos_.empty()) {
+    SendEosIfNeededOrReusePicture(buffers_pending_eos_.front());
+    buffers_pending_eos_.pop();
+  }
+}
+
+void ArcGpuVideoDecodeAccelerator::NotifyResetDone() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  arc_client_->OnResetDone();
+}
+
+static ArcVideoAccelerator::Error ConvertErrorCode(
+    media::VideoDecodeAccelerator::Error error) {
+  switch (error) {
+    case media::VideoDecodeAccelerator::ILLEGAL_STATE:
+      return ArcVideoAccelerator::ILLEGAL_STATE;
+    case media::VideoDecodeAccelerator::INVALID_ARGUMENT:
+      return ArcVideoAccelerator::INVALID_ARGUMENT;
+    case media::VideoDecodeAccelerator::UNREADABLE_INPUT:
+      return ArcVideoAccelerator::UNREADABLE_INPUT;
+    case media::VideoDecodeAccelerator::PLATFORM_FAILURE:
+      return ArcVideoAccelerator::PLATFORM_FAILURE;
+    default:
+      DLOG(ERROR) << "Unknown error: " << error;
+      return ArcVideoAccelerator::PLATFORM_FAILURE;
+  }
+}
+
+void ArcGpuVideoDecodeAccelerator::NotifyError(
+    media::VideoDecodeAccelerator::Error error) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DLOG(ERROR) << "Error notified: " << error;
+  arc_client_->OnError(ConvertErrorCode(error));
+}
+
+void ArcGpuVideoDecodeAccelerator::SendEosIfNeededOrReusePicture(
+    uint32_t index) {
+  if (pending_eos_output_buffer_) {
+    BufferMetadata metadata;
+    metadata.flags = BUFFER_FLAG_EOS;
+    arc_client_->OnBufferDone(PORT_OUTPUT, index, metadata);
+    pending_eos_output_buffer_ = false;
+  } else {
+    if (buffers_pending_import_[index].is_valid()) {
+      std::vector<gfx::GpuMemoryBufferHandle> buffers;
+      buffers.push_back(gfx::GpuMemoryBufferHandle());
+#if defined(USE_OZONE)
+      buffers.back().native_pixmap_handle.fd =
+          base::FileDescriptor(buffers_pending_import_[index].release(), true);
+#endif
+      vda_->ImportBufferForPicture(index, buffers);
+    } else {
+      vda_->ReusePictureBuffer(index);
+    }
+  }
+}
+
+void ArcGpuVideoDecodeAccelerator::CreateInputRecord(
+    int32_t bitstream_buffer_id,
+    uint32_t buffer_index,
+    int64_t timestamp) {
+  input_records_.push_front(
+      InputRecord(bitstream_buffer_id, buffer_index, timestamp));
+
+  // The same value copied from media::GpuVideoDecoder. The input record is
+  // needed when the input buffer or the corresponding output buffer are
+  // returned from VDA. However there is no guarantee how much buffers will be
+  // kept in the VDA. We kept the last |kMaxNumberOfInputRecords| in
+  // |input_records_| and drop the others.
+  const size_t kMaxNumberOfInputRecords = 128;
+  if (input_records_.size() > kMaxNumberOfInputRecords)
+    input_records_.pop_back();
+}
+
+ArcGpuVideoDecodeAccelerator::InputRecord*
+ArcGpuVideoDecodeAccelerator::FindInputRecord(int32_t bitstream_buffer_id) {
+  for (auto& record : input_records_) {
+    if (record.bitstream_buffer_id == bitstream_buffer_id)
+      return &record;
+  }
+  return nullptr;
+}
+
+bool ArcGpuVideoDecodeAccelerator::ValidatePortAndIndex(PortType port,
+                                                        uint32_t index) {
+  switch (port) {
+    case PORT_INPUT:
+      if (index >= input_buffer_info_.size()) {
+        DLOG(ERROR) << "Invalid index: " << index;
+        return false;
+      }
+      return true;
+    case PORT_OUTPUT:
+      if (index >= buffers_pending_import_.size()) {
+        DLOG(ERROR) << "Invalid index: " << index;
+        return false;
+      }
+      return true;
+    default:
+      DLOG(ERROR) << "Invalid port: " << port;
+      return false;
+  }
+}
+
+}  // namespace arc
+}  // namespace chromeos
diff --git a/chrome/gpu/arc_gpu_video_decode_accelerator.h b/chrome/gpu/arc_gpu_video_decode_accelerator.h
new file mode 100644
index 0000000..1959a1ebaf
--- /dev/null
+++ b/chrome/gpu/arc_gpu_video_decode_accelerator.h
@@ -0,0 +1,152 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_GPU_ARC_GPU_VIDEO_DECODE_ACCELERATOR_H_
+#define CHROME_GPU_ARC_GPU_VIDEO_DECODE_ACCELERATOR_H_
+
+#include <list>
+#include <queue>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "chrome/gpu/arc_video_accelerator.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
+#include "media/video/video_decode_accelerator.h"
+
+namespace chromeos {
+namespace arc {
+
+// This class is executed in the GPU process. It takes decoding requests from
+// ARC via IPC channels and translates and sends those requests to an
+// implementation of media::VideoDecodeAccelerator. It also returns the decoded
+// frames back to the ARC side.
+class ArcGpuVideoDecodeAccelerator
+    : public ArcVideoAccelerator,
+      public media::VideoDecodeAccelerator::Client,
+      public base::SupportsWeakPtr<ArcGpuVideoDecodeAccelerator> {
+ public:
+  ArcGpuVideoDecodeAccelerator();
+  ~ArcGpuVideoDecodeAccelerator() override;
+
+  // Implementation of the ArcVideoAccelerator interface.
+  bool Initialize(const Config& config,
+                  ArcVideoAccelerator::Client* client) override;
+  void SetNumberOfOutputBuffers(size_t number) override;
+  void BindSharedMemory(PortType port,
+                        uint32_t index,
+                        base::ScopedFD ashmem_fd,
+                        off_t offset,
+                        size_t length) override;
+  void BindDmabuf(PortType port,
+                  uint32_t index,
+                  base::ScopedFD dmabuf_fd) override;
+  void UseBuffer(PortType port,
+                 uint32_t index,
+                 const BufferMetadata& metadata) override;
+  void Reset() override;
+
+  // Implementation of the VideoDecodeAccelerator::Client interface.
+  void ProvidePictureBuffers(uint32_t requested_num_of_buffers,
+                             uint32_t textures_per_buffer,
+                             const gfx::Size& dimensions,
+                             uint32_t texture_target) override;
+  void DismissPictureBuffer(int32_t picture_buffer) override;
+  void PictureReady(const media::Picture& picture) override;
+  void NotifyEndOfBitstreamBuffer(int32_t bitstream_buffer_id) override;
+  void NotifyFlushDone() override;
+  void NotifyResetDone() override;
+  void NotifyError(media::VideoDecodeAccelerator::Error error) override;
+
+ private:
+  // Some information related to a bitstream buffer. The information is required
+  // when input or output buffers are returned back to the client.
+  struct InputRecord {
+    int32_t bitstream_buffer_id;
+    uint32_t buffer_index;
+    int64_t timestamp;
+
+    InputRecord(int32_t bitstream_buffer_id,
+                uint32_t buffer_index,
+                int64_t timestamp);
+  };
+
+  // The information about the shared memory used as an input buffer.
+  struct InputBufferInfo {
+    // The file handle to access the buffer. It is owned by this class and
+    // should be closed after use.
+    base::ScopedFD handle;
+    off_t offset;
+    size_t length;
+
+    InputBufferInfo();
+    InputBufferInfo(InputBufferInfo&& other);
+    ~InputBufferInfo();
+  };
+
+  // Helper function to Send the end-of-stream output buffer if
+  // |pending_eos_output_buffer_| is true, or reuse the picture in ArcVDA.
+  void SendEosIfNeededOrReusePicture(uint32_t index);
+
+  // Helper function to validate |port| and |index|.
+  bool ValidatePortAndIndex(PortType port, uint32_t index);
+
+  // Creates an InputRecord for the given |bitstream_buffer_id|. The
+  // |buffer_index| is the index of the associated input buffer. The |timestamp|
+  // is the time the video frame should be displayed.
+  void CreateInputRecord(int32_t bitstream_buffer_id,
+                         uint32_t buffer_index,
+                         int64_t timestamp);
+
+  // Finds the InputRecord which matches to given |bitstream_buffer_id|.
+  // Returns |nullptr| if it cannot be found.
+  InputRecord* FindInputRecord(int32_t bitstream_buffer_id);
+
+  // When true, an EOS output buffer need to be sent to |arc_client_| once an
+  // output buffer is available.
+  bool pending_eos_output_buffer_;
+
+  scoped_ptr<media::VideoDecodeAccelerator> vda_;
+
+  // It's safe to use the pointer here, the life cycle of the |arc_client_|
+  // is longer than this ArcGpuVideoDecodeAccelerator.
+  ArcVideoAccelerator::Client* arc_client_;
+
+  // The next ID for the bitstream buffer, started from 0.
+  int32_t next_bitstream_buffer_id_;
+
+  gfx::Size coded_size_;
+
+  // The |picture_buffer_id|s for Pictures that were returned to us from VDA
+  // via PictureReady() while flushing. We keep them until NotifyFlushDone();
+  // once it's called, we send one of the pending buffers from this queue (if
+  // not empty), marked with an EOS flag, to |arc_client_|, and return the rest
+  // to VDA for reuse.
+  std::queue<int32_t> buffers_pending_eos_;
+
+  // A list of most recent |kMaxNumberOfInputRecord| InputRecords.
+  // |kMaxNumberOfInputRecord| is defined in the cc file.
+  std::list<InputRecord> input_records_;
+
+  // The details of the shared memory of each input buffers.
+  std::vector<InputBufferInfo> input_buffer_info_;
+
+  // To keep those output buffers which have been bound by bindDmabuf() but not
+  // be used yet. Will call VDA::ImportBufferForPicture() when those buffers are
+  // used for the first time.
+  std::vector<base::ScopedFD> buffers_pending_import_;
+
+  base::ThreadChecker thread_checker_;
+  size_t output_buffer_size_;
+
+  gpu::GpuPreferences gpu_preferences_;
+
+  DISALLOW_COPY_AND_ASSIGN(ArcGpuVideoDecodeAccelerator);
+};
+
+}  // namespace arc
+}  // namespace chromeos
+
+#endif  // CHROME_GPU_ARC_GPU_VIDEO_DECODE_ACCELERATOR_H_
diff --git a/chrome/gpu/gpu_arc_video_service.cc b/chrome/gpu/gpu_arc_video_service.cc
index d53076d6..0ab69c7 100644
--- a/chrome/gpu/gpu_arc_video_service.cc
+++ b/chrome/gpu/gpu_arc_video_service.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/thread_task_runner_handle.h"
+#include "chrome/gpu/arc_gpu_video_decode_accelerator.h"
 #include "chrome/gpu/arc_video_accelerator.h"
 #include "components/arc/common/video_accelerator.mojom.h"
 #include "mojo/edk/embedder/embedder.h"
@@ -112,8 +113,7 @@
         base::Bind(&GpuArcVideoService::AcceleratorStub::OnConnectionError,
                    base::Unretained(this)));
 
-    // TODO(kcwu): create ArcGpuVideoDecodeAccelerator here.
-    // accelerator_.reset(new ArcGpuVideoDecodeAccelerator());
+    accelerator_.reset(new ArcGpuVideoDecodeAccelerator());
 
     ::arc::mojom::VideoAcceleratorServicePtr service;
     binding_.Bind(GetProxy(&service));
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn
index fe418eea..0f3906c1 100644
--- a/chromeos/BUILD.gn
+++ b/chromeos/BUILD.gn
@@ -19,7 +19,7 @@
                           [ "chromeos.gyp" ])
 
 component("chromeos") {
-  configs += [ "//net/third_party/nss/ssl:ssl_config" ]
+  configs += [ "//third_party/nss:system_nss_no_ssl_config" ]
   public_deps = [
     "//dbus",
   ]
@@ -138,7 +138,7 @@
 test("chromeos_unittests") {
   configs += [
     "//build/config/linux:dbus",
-    "//net/third_party/nss/ssl:ssl_config",
+    "//third_party/nss:system_nss_no_ssl_config",
   ]
   deps = [
     ":cryptohome_proto",
diff --git a/components/certificate_reporting/error_reporter.cc b/components/certificate_reporting/error_reporter.cc
index 6cfa629..9c8bb83 100644
--- a/components/certificate_reporting/error_reporter.cc
+++ b/components/certificate_reporting/error_reporter.cc
@@ -10,11 +10,7 @@
 
 #include "base/logging.h"
 #include "components/certificate_reporting/encrypted_cert_logger.pb.h"
-
-#if defined(USE_OPENSSL)
 #include "crypto/aead_openssl.h"
-#endif
-
 #include "crypto/curve25519.h"
 #include "crypto/hkdf.h"
 #include "crypto/random.h"
@@ -32,8 +28,6 @@
     0x31, 0x1a, 0x39, 0x5b, 0x76, 0xb1, 0x6b, 0x3d, 0x6a, 0x2b};
 static const uint32_t kServerPublicKeyVersion = 1;
 
-#if defined(USE_OPENSSL)
-
 static const char kHkdfLabel[] = "certificate report";
 
 bool GetHkdfSubkeySecret(size_t subkey_length,
@@ -101,7 +95,6 @@
       EncryptedCertLoggerRequest::AEAD_ECDH_AES_128_CTR_HMAC_SHA256);
   return true;
 }
-#endif
 
 }  // namespace
 
@@ -137,7 +130,6 @@
     certificate_report_sender_->Send(upload_url_, serialized_report);
   } else {
     DCHECK(IsHttpUploadUrlSupported());
-#if defined(USE_OPENSSL)
     EncryptedCertLoggerRequest encrypted_report;
     if (!EncryptSerializedReport(server_public_key_, server_public_key_version_,
                                  serialized_report, &encrypted_report)) {
@@ -147,20 +139,14 @@
     std::string serialized_encrypted_report;
     encrypted_report.SerializeToString(&serialized_encrypted_report);
     certificate_report_sender_->Send(upload_url_, serialized_encrypted_report);
-#endif
   }
 }
 
 bool ErrorReporter::IsHttpUploadUrlSupported() {
-#if defined(USE_OPENSSL)
   return true;
-#else
-  return false;
-#endif
 }
 
 // Used only by tests.
-#if defined(USE_OPENSSL)
 bool ErrorReporter::DecryptErrorReport(
     const uint8_t server_private_key[32],
     const EncryptedCertLoggerRequest& encrypted_report,
@@ -182,6 +168,5 @@
   return aead.Open(encrypted_report.encrypted_report(), nonce, std::string(),
                    decrypted_serialized_report);
 }
-#endif
 
 }  // namespace certificate_reporting
diff --git a/components/certificate_reporting/error_reporter.h b/components/certificate_reporting/error_reporter.h
index f090817..67e4bd3 100644
--- a/components/certificate_reporting/error_reporter.h
+++ b/components/certificate_reporting/error_reporter.h
@@ -68,13 +68,11 @@
   // Whether sending reports over HTTP is supported.
   static bool IsHttpUploadUrlSupported();
 
-#if defined(USE_OPENSSL)
   // Used by tests.
   static bool DecryptErrorReport(
       const uint8_t server_private_key[32],
       const EncryptedCertLoggerRequest& encrypted_report,
       std::string* decrypted_serialized_report);
-#endif
 
  private:
   scoped_ptr<net::CertificateReportSender> certificate_report_sender_;
diff --git a/components/certificate_reporting/error_reporter_unittest.cc b/components/certificate_reporting/error_reporter_unittest.cc
index ac8ec38..e38a47c 100644
--- a/components/certificate_reporting/error_reporter_unittest.cc
+++ b/components/certificate_reporting/error_reporter_unittest.cc
@@ -92,7 +92,6 @@
     EXPECT_EQ(http_mock_report_sender->latest_report_uri(), http_url);
 
     std::string uploaded_report;
-#if defined(USE_OPENSSL)
     EncryptedCertLoggerRequest encrypted_request;
     ASSERT_TRUE(encrypted_request.ParseFromString(
         http_mock_report_sender->latest_report()));
@@ -102,15 +101,11 @@
               encrypted_request.algorithm());
     ASSERT_TRUE(ErrorReporter::DecryptErrorReport(
         server_private_key_, encrypted_request, &uploaded_report));
-#else
-    ADD_FAILURE() << "Only supported in OpenSSL ports";
-#endif
 
     EXPECT_EQ(kDummyReport, uploaded_report);
   }
 }
 
-#if defined(USE_OPENSSL)
 // This test decrypts a "known gold" report. It's intentionally brittle
 // in order to catch changes in report encryption that could cause the
 // server to no longer be able to decrypt reports that it receives from
@@ -270,7 +265,6 @@
   ASSERT_TRUE(ErrorReporter::DecryptErrorReport(
       server_private_key_, encrypted_request, &decrypted_serialized_report));
 }
-#endif
 
 }  // namespace
 
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index 2039ad0..c5588b20 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -1286,6 +1286,7 @@
             'test_runner/test_runner.gyp:test_runner',
             'tracing.gyp:tracing',
             'webcrypto/webcrypto.gyp:webcrypto',
+            '../third_party/boringssl/boringssl.gyp:boringssl',
             '../third_party/re2/re2.gyp:re2',
           ],
           'conditions': [
@@ -1304,24 +1305,6 @@
                 'components.gyp:policy_java',
               ],
             }],
-            ['use_openssl==1', {
-              'dependencies': [
-                '../third_party/boringssl/boringssl.gyp:boringssl',
-              ],
-            }, {
-              'conditions': [
-                ['os_posix == 1 and OS != "mac" and OS != "ios" and OS != "android"', {
-                  'dependencies': [
-                    '../build/linux/system.gyp:ssl',
-                  ],
-                }, {
-                  'dependencies': [
-                    '../third_party/nss/nss.gyp:nspr',
-                    '../third_party/nss/nss.gyp:nss',
-                  ],
-                }],
-              ],
-            }],
             ['safe_browsing == 2 and OS != "ios"', {
               'dependencies': [
                 'components.gyp:safe_browsing_db_mobile',
diff --git a/components/gcm_driver.gypi b/components/gcm_driver.gypi
index 042397f..1531dd1 100644
--- a/components/gcm_driver.gypi
+++ b/components/gcm_driver.gypi
@@ -226,6 +226,7 @@
         '../components/components.gyp:leveldb_proto',
         '../crypto/crypto.gyp:crypto',
         '../net/net.gyp:net',
+        '../third_party/boringssl/boringssl.gyp:boringssl',
       ],
       'include_dirs': [
         '..',
@@ -240,29 +241,11 @@
         'gcm_driver/crypto/gcm_key_store.h',
         'gcm_driver/crypto/gcm_message_cryptographer.cc',
         'gcm_driver/crypto/gcm_message_cryptographer.h',
-        'gcm_driver/crypto/gcm_message_cryptographer_nss.cc',
         'gcm_driver/crypto/gcm_message_cryptographer_openssl.cc',
         'gcm_driver/crypto/p256_key_util.cc',
         'gcm_driver/crypto/p256_key_util.h',
-        'gcm_driver/crypto/p256_key_util_nss.cc',
         'gcm_driver/crypto/p256_key_util_openssl.cc',
       ],
-      'conditions': [
-        ['use_openssl==1', {
-          'sources!': [
-            'gcm_driver/crypto/gcm_message_cryptographer_nss.cc',
-            'gcm_driver/crypto/p256_key_util_nss.cc',
-          ],
-          'dependencies': [
-            '../third_party/boringssl/boringssl.gyp:boringssl',
-          ],
-        }, {
-          'sources!': [
-            'gcm_driver/crypto/gcm_message_cryptographer_openssl.cc',
-            'gcm_driver/crypto/p256_key_util_openssl.cc',
-          ],
-        }],
-      ],
     },
     {
       # GN version: //components/gcm_driver/crypto/proto
diff --git a/components/gcm_driver/crypto/BUILD.gn b/components/gcm_driver/crypto/BUILD.gn
index 778c1c8..7dd4d73 100644
--- a/components/gcm_driver/crypto/BUILD.gn
+++ b/components/gcm_driver/crypto/BUILD.gn
@@ -15,11 +15,9 @@
     "gcm_key_store.h",
     "gcm_message_cryptographer.cc",
     "gcm_message_cryptographer.h",
-    "gcm_message_cryptographer_nss.cc",
     "gcm_message_cryptographer_openssl.cc",
     "p256_key_util.cc",
     "p256_key_util.h",
-    "p256_key_util_nss.cc",
     "p256_key_util_openssl.cc",
   ]
 
@@ -33,18 +31,6 @@
     "//net",
     "//third_party/protobuf:protobuf_lite",
   ]
-
-  if (use_openssl) {
-    sources -= [
-      "gcm_message_cryptographer_nss.cc",
-      "p256_key_util_nss.cc",
-    ]
-  } else {
-    sources -= [
-      "gcm_message_cryptographer_openssl.cc",
-      "p256_key_util_openssl.cc",
-    ]
-  }
 }
 
 # GYP version: components/gcm_driver.gypi:gcm_driver_crypto_test_support
diff --git a/components/gcm_driver/crypto/gcm_message_cryptographer_nss.cc b/components/gcm_driver/crypto/gcm_message_cryptographer_nss.cc
deleted file mode 100644
index accf456..0000000
--- a/components/gcm_driver/crypto/gcm_message_cryptographer_nss.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/gcm_driver/crypto/gcm_message_cryptographer.h"
-
-#include <pk11pub.h>
-#include <secerr.h>
-#include <stddef.h>
-
-#include "base/logging.h"
-#include "base/numerics/safe_math.h"
-#include "base/strings/string_util.h"
-#include "crypto/scoped_nss_types.h"
-
-namespace gcm {
-
-bool GCMMessageCryptographer::EncryptDecryptRecordInternal(
-    Mode mode,
-    const base::StringPiece& input,
-    const base::StringPiece& key,
-    const base::StringPiece& nonce,
-    std::string* output) const {
-  DCHECK(output);
-
-  SECItem key_item;
-  key_item.type = siBuffer;
-  key_item.data = const_cast<unsigned char*>(
-      reinterpret_cast<const unsigned char*>(key.data()));
-  key_item.len = key.size();
-
-  const CK_ATTRIBUTE_TYPE cka_mode = mode == ENCRYPT ? CKA_ENCRYPT
-                                                     : CKA_DECRYPT;
-
-  crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
-  crypto::ScopedPK11SymKey aead_key(
-      PK11_ImportSymKey(slot.get(), CKM_AES_GCM, PK11_OriginUnwrap, cka_mode,
-                        &key_item, nullptr));
-
-  CK_GCM_PARAMS gcm_params;
-  gcm_params.pIv = const_cast<unsigned char*>(
-      reinterpret_cast<const unsigned char*>(nonce.data()));
-  gcm_params.ulIvLen = nonce.size();
-
-  gcm_params.pAAD = nullptr;
-  gcm_params.ulAADLen = 0;
-
-  gcm_params.ulTagBits = kAuthenticationTagBytes * 8;
-
-  SECItem param;
-  param.type = siBuffer;
-  param.data = reinterpret_cast<unsigned char*>(&gcm_params);
-  param.len = sizeof(gcm_params);
-
-  base::CheckedNumeric<size_t> maximum_output_length(input.size());
-  if (mode == ENCRYPT)
-    maximum_output_length += kAuthenticationTagBytes;
-
-  // WriteInto requires the buffer to finish with a NULL-byte.
-  maximum_output_length += 1;
-
-  unsigned int output_length = 0;
-  unsigned char* raw_input = const_cast<unsigned char*>(
-      reinterpret_cast<const unsigned char*>(input.data()));
-  unsigned char* raw_output = reinterpret_cast<unsigned char*>(
-      base::WriteInto(output, maximum_output_length.ValueOrDie()));
-
-  if (mode == ENCRYPT) {
-    if (PK11_Encrypt(aead_key.get(), CKM_AES_GCM, &param, raw_output,
-                     &output_length, output->size(), raw_input,
-                     input.size()) != SECSuccess) {
-      return false;
-    }
-  } else {
-    if (PK11_Decrypt(aead_key.get(), CKM_AES_GCM, &param, raw_output,
-                     &output_length, output->size(), raw_input,
-                     input.size()) != SECSuccess) {
-      return false;
-    }
-  }
-
-  base::CheckedNumeric<size_t> expected_output_length(input.size());
-  if (mode == ENCRYPT)
-    expected_output_length += kAuthenticationTagBytes;
-  else
-    expected_output_length -= kAuthenticationTagBytes;
-
-  DCHECK_EQ(expected_output_length.ValueOrDie(), output_length);
-
-  output->resize(output_length);
-  return true;
-}
-
-}  // namespace gcm
diff --git a/components/gcm_driver/crypto/p256_key_util_nss.cc b/components/gcm_driver/crypto/p256_key_util_nss.cc
deleted file mode 100644
index 260efc8..0000000
--- a/components/gcm_driver/crypto/p256_key_util_nss.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/gcm_driver/crypto/p256_key_util.h"
-
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "crypto/ec_private_key.h"
-#include "crypto/scoped_nss_types.h"
-
-namespace gcm {
-
-namespace {
-
-// A P-256 field element consists of 32 bytes.
-const size_t kFieldBytes = 32;
-
-}  // namespace
-
-bool ComputeSharedP256Secret(const base::StringPiece& private_key,
-                             const base::StringPiece& public_key_x509,
-                             const base::StringPiece& peer_public_key,
-                             std::string* out_shared_secret) {
-  DCHECK(out_shared_secret);
-
-  scoped_ptr<crypto::ECPrivateKey> local_key_pair(
-      crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
-          "" /* no password */,
-          std::vector<uint8_t>(
-              private_key.data(), private_key.data() + private_key.size()),
-          std::vector<uint8_t>(
-              public_key_x509.data(),
-              public_key_x509.data() + public_key_x509.size())));
-
-  if (!local_key_pair) {
-    DLOG(ERROR) << "Unable to create the local key pair.";
-    return false;
-  }
-
-  SECKEYPublicKey public_key_peer;
-  memset(&public_key_peer, 0, sizeof(public_key_peer));
-
-  public_key_peer.keyType = ecKey;
-  // Both sides of a ECDH key exchange need to use the same EC params.
-  public_key_peer.u.ec.DEREncodedParams.len =
-      local_key_pair->public_key()->u.ec.DEREncodedParams.len;
-  public_key_peer.u.ec.DEREncodedParams.data =
-      local_key_pair->public_key()->u.ec.DEREncodedParams.data;
-
-  public_key_peer.u.ec.publicValue.type = siBuffer;
-  public_key_peer.u.ec.publicValue.data =
-      reinterpret_cast<uint8_t*>(const_cast<char*>(peer_public_key.data()));
-  public_key_peer.u.ec.publicValue.len = peer_public_key.size();
-
-  // The NSS function performing ECDH key exchange is PK11_PubDeriveWithKDF.
-  // As this function is used for SSL/TLS's ECDH key exchanges it has many
-  // arguments, most of which are not required. Key derivation function CKD_NULL
-  // is used because the return value of |CalculateSharedKey| is the actual ECDH
-  // shared key, not any derived keys from it.
-  crypto::ScopedPK11SymKey premaster_secret(
-      PK11_PubDeriveWithKDF(
-          local_key_pair->key(),
-          &public_key_peer,
-          PR_FALSE /* isSender */,
-          nullptr /* randomA */,
-          nullptr /* randomB */,
-          CKM_ECDH1_DERIVE,
-          CKM_GENERIC_SECRET_KEY_GEN,
-          CKA_DERIVE,
-          0 /* keySize */,
-          CKD_NULL /* kdf */,
-          nullptr /* sharedData */,
-          nullptr /* wincx */));
-
-  if (!premaster_secret) {
-    DLOG(ERROR) << "Unable to derive the ECDH shared key.";
-    return false;
-  }
-
-  if (PK11_ExtractKeyValue(premaster_secret.get()) != SECSuccess) {
-    DLOG(ERROR) << "Unable to extract the raw ECDH shared secret.";
-    return false;
-  }
-
-  SECItem* key_data = PK11_GetKeyData(premaster_secret.get());
-  if (!key_data || !key_data->data || key_data->len != kFieldBytes) {
-    DLOG(ERROR) << "The raw ECDH shared secret is invalid.";
-    return false;
-  }
-
-  out_shared_secret->assign(
-      reinterpret_cast<char*>(key_data->data), key_data->len);
-  return true;
-}
-
-}  // namespace gcm
diff --git a/components/ntp_snippets/ntp_snippets_service_unittest.cc b/components/ntp_snippets/ntp_snippets_service_unittest.cc
index 02be166..9eab18d 100644
--- a/components/ntp_snippets/ntp_snippets_service_unittest.cc
+++ b/components/ntp_snippets/ntp_snippets_service_unittest.cc
@@ -13,10 +13,14 @@
 #include "base/time/time.h"
 #include "components/ntp_snippets/ntp_snippet.h"
 #include "components/ntp_snippets/ntp_snippets_fetcher.h"
+#include "components/ntp_snippets/ntp_snippets_scheduler.h"
 #include "components/prefs/testing_pref_service.h"
 #include "net/url_request/url_request_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using testing::_;
+
 namespace ntp_snippets {
 
 namespace {
@@ -100,6 +104,16 @@
   }
 }
 
+class MockScheduler : public NTPSnippetsScheduler {
+ public:
+  MOCK_METHOD4(Schedule,
+               bool(base::TimeDelta period_wifi_charging,
+                    base::TimeDelta period_wifi,
+                    base::TimeDelta period_fallback,
+                    base::Time reschedule_time));
+  MOCK_METHOD0(Unschedule, bool());
+};
+
 }  // namespace
 
 class NTPSnippetsServiceTest : public testing::Test {
@@ -114,24 +128,32 @@
     CreateSnippetsService();
   }
 
-  void CreateSnippetsService() {
+  virtual void CreateSnippetsService() {
+    CreateSnippetsServiceEnabled(true);
+  }
+
+  void CreateSnippetsServiceEnabled(bool enabled) {
+    scheduler_.reset(new MockScheduler);
     scoped_refptr<base::SingleThreadTaskRunner> task_runner(
         base::ThreadTaskRunnerHandle::Get());
     scoped_refptr<net::TestURLRequestContextGetter> request_context_getter =
         new net::TestURLRequestContextGetter(task_runner.get());
 
     service_.reset(new NTPSnippetsService(
-        pref_service_.get(), nullptr, task_runner, std::string("fr"), nullptr,
+        pref_service_.get(), nullptr, task_runner, std::string("fr"),
+        scheduler_.get(),
         make_scoped_ptr(new NTPSnippetsFetcher(
             task_runner, std::move(request_context_getter), true)),
         base::Bind(&ParseJson, true)));
-    service_->Init(true);
+    if (enabled)
+      EXPECT_CALL(*scheduler_, Schedule(_, _, _, _));
+    else
+      EXPECT_CALL(*scheduler_, Unschedule());
+    service_->Init(enabled);
   }
 
  protected:
-  NTPSnippetsService* service() {
-    return service_.get();
-  }
+  NTPSnippetsService* service() { return service_.get(); }
 
   void LoadFromJSONString(const std::string& json) {
     service_->OnSnippetsDownloaded(json);
@@ -145,10 +167,26 @@
   base::MessageLoop message_loop_;
   scoped_ptr<TestingPrefServiceSimple> pref_service_;
   scoped_ptr<NTPSnippetsService> service_;
+  scoped_ptr<MockScheduler> scheduler_;
 
   DISALLOW_COPY_AND_ASSIGN(NTPSnippetsServiceTest);
 };
 
+class NTPSnippetsServiceDisabledTest : public NTPSnippetsServiceTest {
+ public:
+  void CreateSnippetsService() override {
+    CreateSnippetsServiceEnabled(false);
+  }
+};
+
+TEST_F(NTPSnippetsServiceTest, Schedule) {
+  // CreateSnippetsServiceEnabled checks that Schedule is called.
+}
+
+TEST_F(NTPSnippetsServiceDisabledTest, Unschedule) {
+  // CreateSnippetsServiceEnabled checks that Unschedule is called.
+}
+
 TEST_F(NTPSnippetsServiceTest, Loop) {
   std::string json_str(
       "{ \"recos\": [ "
diff --git a/components/password_manager/sync/browser/password_manager_setting_migrator_service_unittest.cc b/components/password_manager/sync/browser/password_manager_setting_migrator_service_unittest.cc
index ce644d4..c912032 100644
--- a/components/password_manager/sync/browser/password_manager_setting_migrator_service_unittest.cc
+++ b/components/password_manager/sync/browser/password_manager_setting_migrator_service_unittest.cc
@@ -264,19 +264,8 @@
   }
 }
 
-// TODO(crbug.com/604721): original CL never compiled this file with gyp and
-// thus the test was never run on iOS and is now failing. Disabled until the
-// bug is fixed to unblock conversion to gn.
-#if !defined(OS_IOS)
-#define MAYBE_ReconcileWhenWhenBothPrefsTypesArrivesFromSync \
-  ReconcileWhenWhenBothPrefsTypesArrivesFromSync
-#else
-#define MAYBE_ReconcileWhenWhenBothPrefsTypesArrivesFromSync \
-  DISABLED_ReconcileWhenWhenBothPrefsTypesArrivesFromSync
-#endif
-
 TEST_F(PasswordManagerSettingMigratorServiceTest,
-       MAYBE_ReconcileWhenWhenBothPrefsTypesArrivesFromSync) {
+       ReconcileWhenWhenBothPrefsTypesArrivesFromSync) {
   const struct {
     BooleanPrefState new_pref_local_value;
     BooleanPrefState old_pref_local_value;
diff --git a/components/quirks/quirks_manager.cc b/components/quirks/quirks_manager.cc
index 4875ee4..db97631 100644
--- a/components/quirks/quirks_manager.cc
+++ b/components/quirks/quirks_manager.cc
@@ -126,9 +126,9 @@
     return;
 
   waiting_for_login_ = false;
-  if (!QuirksEnabled()) {
-    VLOG(1) << "Quirks Client disabled by device policy.";
-    return;
+  if (!clients_.empty() && !QuirksEnabled()) {
+    VLOG(2) << clients_.size() << " client(s) deleted.";
+    clients_.clear();
   }
 
   for (const scoped_ptr<QuirksClient>& client : clients_)
@@ -252,9 +252,16 @@
 }
 
 bool QuirksManager::QuirksEnabled() {
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-             switches::kEnableQuirksClient) &&
-         delegate_->DevicePolicyEnabled();
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableQuirksClient)) {
+    VLOG(2) << "Quirks Client disabled by command line flag.";
+    return false;
+  }
+  if (!delegate_->DevicePolicyEnabled()) {
+    VLOG(2) << "Quirks Client disabled by device policy.";
+    return false;
+  }
+  return true;
 }
 
 void QuirksManager::SetLastServerCheck(int64_t product_id,
diff --git a/components/quirks/switches.cc b/components/quirks/switches.cc
index fd61a5d..c0a4622a 100644
--- a/components/quirks/switches.cc
+++ b/components/quirks/switches.cc
@@ -7,8 +7,8 @@
 namespace quirks {
 namespace switches {
 
-// Enable Quirks Client for handling display calibration information.
-const char kEnableQuirksClient[] = "enable-quirks-client";
+// Disable Quirks Client for handling display calibration information.
+const char kDisableQuirksClient[] = "disable-quirks-client";
 
 }  // namespace switches
 }  // namespace quirks
diff --git a/components/quirks/switches.h b/components/quirks/switches.h
index e359dcf..2c14926 100644
--- a/components/quirks/switches.h
+++ b/components/quirks/switches.h
@@ -12,7 +12,7 @@
 
 // All switches in alphabetical order. The switches should be documented
 // alongside the definition of their values in the .cc file.
-QUIRKS_EXPORT extern const char kEnableQuirksClient[];
+QUIRKS_EXPORT extern const char kDisableQuirksClient[];
 
 }  // namespace switches
 }  // namespace quirks
diff --git a/components/test_runner/layout_test_runtime_flags.cc b/components/test_runner/layout_test_runtime_flags.cc
index 7f2410c..63e3310 100644
--- a/components/test_runner/layout_test_runtime_flags.cc
+++ b/components/test_runner/layout_test_runtime_flags.cc
@@ -27,6 +27,7 @@
   set_policy_delegate_is_permissive(false);
   set_policy_delegate_should_notify_done(false);
   set_wait_until_done(false);
+  set_wait_until_external_url_load(false);
 
   set_dump_selection_rect(false);
   set_dump_drag_image(false);
@@ -42,6 +43,21 @@
   set_displaying_insecure_content_allowed(false);
   set_running_insecure_content_allowed(false);
 
+  set_dump_editting_callbacks(false);
+  set_dump_frame_load_callbacks(false);
+  set_dump_ping_loader_callbacks(false);
+  set_dump_user_gesture_in_frame_load_callbacks(false);
+  set_dump_resource_load_callbacks(false);
+  set_dump_resource_priorities(false);
+  set_dump_resource_response_mime_types(false);
+  set_dump_navigation_policy(false);
+  set_intercept_post_message(false);
+
+  set_dump_title_changes(false);
+  set_dump_icon_changes(false);
+
+  set_stay_on_page_after_handling_before_unload(false);
+
   // No need to report the initial state - only the future delta is important.
   tracked_dictionary().ResetChangeTracking();
 }
diff --git a/components/test_runner/layout_test_runtime_flags.h b/components/test_runner/layout_test_runtime_flags.h
index c772ba8..0a4355b 100644
--- a/components/test_runner/layout_test_runtime_flags.h
+++ b/components/test_runner/layout_test_runtime_flags.h
@@ -78,6 +78,10 @@
   // If true, don't dump output until notifyDone is called.
   DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(wait_until_done)
 
+  // If true, ends the test when a URL is loaded externally via
+  // WebFrameClient::loadURLExternally().
+  DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(wait_until_external_url_load)
+
   // Causes navigation actions just printout the intended navigation instead
   // of taking you to the page. This is used for cases like mailto, where you
   // don't actually want to open the mail program.
@@ -111,6 +115,49 @@
   DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(
       dump_web_content_settings_client_callbacks)
 
+  // If true, the test_shell will write a descriptive line for each editing
+  // command.
+  DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_editting_callbacks)
+
+  // If true, the test_shell will output a descriptive line for each frame
+  // load callback.
+  DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_frame_load_callbacks)
+
+  // If true, the test_shell will output a descriptive line for each
+  // PingLoader dispatched.
+  DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_ping_loader_callbacks)
+
+  // If true, the test_shell will output a line of the user gesture status
+  // text for some frame load callbacks.
+  DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(
+      dump_user_gesture_in_frame_load_callbacks)
+
+  // If true, the test_shell will output a descriptive line for each resource
+  // load callback.
+  DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_resource_load_callbacks)
+  DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_resource_priorities)
+
+  // If true, the test_shell will output the MIME type for each resource that
+  // was loaded.
+  DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_resource_response_mime_types)
+
+  // If true, content_shell will dump the default navigation policy passed to
+  // WebFrameClient::decidePolicyForNavigation.
+  DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_navigation_policy)
+
+  // Bound variable to set whether postMessages should be intercepted or not
+  DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(intercept_post_message)
+
+  // If true, output a message when the page title is changed.
+  DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_title_changes)
+
+  // If true, the test_shell will print out the icon change notifications.
+  DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_icon_changes)
+
+  // Desired return value of WebFrameClient::runModalBeforeUnloadDialog.
+  DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(
+      stay_on_page_after_handling_before_unload)
+
 #undef DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG
 #undef DEFINE_STRING_LAYOUT_TEST_RUNTIME_FLAG
 
diff --git a/components/test_runner/test_runner.cc b/components/test_runner/test_runner.cc
index 34af6df2..5fd5a1b3 100644
--- a/components/test_runner/test_runner.cc
+++ b/components/test_runner/test_runner.cc
@@ -1492,13 +1492,15 @@
 
 bool TestRunnerBindings::InterceptPostMessage() {
   if (runner_)
-    return runner_->intercept_post_message_;
+    return runner_->shouldInterceptPostMessage();
   return false;
 }
 
 void TestRunnerBindings::SetInterceptPostMessage(bool value) {
-  if (runner_)
-    runner_->intercept_post_message_ = value;
+  if (runner_) {
+    runner_->layout_test_runtime_flags_.set_intercept_post_message(value);
+    runner_->OnLayoutTestRuntimeFlagsChanged();
+  }
 }
 
 void TestRunnerBindings::ForceNextWebGLContextCreationToFail() {
@@ -1571,7 +1573,6 @@
       close_remaining_windows_(false),
       work_queue_(this),
       web_history_item_count_(0),
-      intercept_post_message_(false),
       test_interfaces_(interfaces),
       delegate_(nullptr),
       web_view_(nullptr),
@@ -1624,7 +1625,6 @@
   mock_screen_orientation_client_->ResetData();
   drag_image_.reset();
   views_with_scheduled_animations_.clear();
-  wait_until_external_url_load_ = false;
 
   WebSecurityPolicy::resetOriginAccessWhitelists();
 #if defined(__linux__) || defined(ANDROID)
@@ -1647,26 +1647,15 @@
     ResetDeviceLight();
   }
 
-  dump_editting_callbacks_ = false;
-  dump_icon_changes_ = false;
   dump_as_audio_ = false;
-  dump_frame_load_callbacks_ = false;
-  dump_ping_loader_callbacks_ = false;
-  dump_user_gesture_in_frame_load_callbacks_ = false;
-  dump_title_changes_ = false;
   dump_create_view_ = false;
   can_open_windows_ = false;
-  dump_resource_load_callbacks_ = false;
-  dump_resource_response_mime_types_ = false;
   dump_window_status_changes_ = false;
   dump_spell_check_callbacks_ = false;
   dump_back_forward_list_ = false;
-  dump_navigation_policy_ = false;
   test_repaint_ = false;
   sweep_horizontally_ = false;
   midi_accessor_result_ = true;
-  should_stay_on_page_after_handling_before_unload_ = false;
-  should_dump_resource_priorities_ = false;
   has_custom_text_output_ = false;
   custom_text_output_.clear();
 
@@ -1675,7 +1664,6 @@
   platform_name_ = "chromium";
   tooltip_text_ = std::string();
   web_history_item_count_ = 0;
-  intercept_post_message_ = false;
 
   SetUseMockTheme(true);
 
@@ -1765,7 +1753,7 @@
 }
 
 bool TestRunner::shouldDumpEditingCallbacks() const {
-  return dump_editting_callbacks_;
+  return layout_test_runtime_flags_.dump_editting_callbacks();
 }
 
 void TestRunner::setShouldDumpAsText(bool value) {
@@ -1797,7 +1785,7 @@
 }
 
 bool TestRunner::shouldStayOnPageAfterHandlingBeforeUnload() const {
-  return should_stay_on_page_after_handling_before_unload_;
+  return layout_test_runtime_flags_.stay_on_page_after_handling_before_unload();
 }
 
 
@@ -1867,15 +1855,18 @@
 }
 
 bool TestRunner::shouldDumpFrameLoadCallbacks() const {
-  return test_is_running_ && dump_frame_load_callbacks_;
+  return test_is_running_ &&
+         layout_test_runtime_flags_.dump_frame_load_callbacks();
 }
 
 void TestRunner::setShouldDumpFrameLoadCallbacks(bool value) {
-  dump_frame_load_callbacks_ = value;
+  layout_test_runtime_flags_.set_dump_frame_load_callbacks(value);
+  OnLayoutTestRuntimeFlagsChanged();
 }
 
 bool TestRunner::shouldDumpPingLoaderCallbacks() const {
-  return test_is_running_ && dump_ping_loader_callbacks_;
+  return test_is_running_ &&
+         layout_test_runtime_flags_.dump_ping_loader_callbacks();
 }
 
 void TestRunner::setShouldEnableViewSource(bool value) {
@@ -1883,15 +1874,16 @@
 }
 
 bool TestRunner::shouldDumpUserGestureInFrameLoadCallbacks() const {
-  return test_is_running_ && dump_user_gesture_in_frame_load_callbacks_;
+  return test_is_running_ &&
+         layout_test_runtime_flags_.dump_user_gesture_in_frame_load_callbacks();
 }
 
 bool TestRunner::shouldDumpTitleChanges() const {
-  return dump_title_changes_;
+  return layout_test_runtime_flags_.dump_title_changes();
 }
 
 bool TestRunner::shouldDumpIconChanges() const {
-  return dump_icon_changes_;
+  return layout_test_runtime_flags_.dump_icon_changes();
 }
 
 bool TestRunner::shouldDumpCreateView() const {
@@ -1903,11 +1895,13 @@
 }
 
 bool TestRunner::shouldDumpResourceLoadCallbacks() const {
-  return test_is_running_ && dump_resource_load_callbacks_;
+  return test_is_running_ &&
+         layout_test_runtime_flags_.dump_resource_load_callbacks();
 }
 
 bool TestRunner::shouldDumpResourceResponseMIMETypes() const {
-  return test_is_running_ && dump_resource_response_mime_types_;
+  return test_is_running_ &&
+         layout_test_runtime_flags_.dump_resource_response_mime_types();
 }
 
 WebContentSettingsClient* TestRunner::GetWebContentSettings() const {
@@ -1936,7 +1930,7 @@
 }
 
 bool TestRunner::shouldWaitUntilExternalURLLoad() const {
-  return wait_until_external_url_load_;
+  return layout_test_runtime_flags_.wait_until_external_url_load();
 }
 
 const std::set<std::string>* TestRunner::httpHeadersToClear() const {
@@ -1980,11 +1974,11 @@
 }
 
 bool TestRunner::shouldInterceptPostMessage() const {
-  return intercept_post_message_;
+  return layout_test_runtime_flags_.intercept_post_message();
 }
 
 bool TestRunner::shouldDumpResourcePriorities() const {
-  return should_dump_resource_priorities_;
+  return layout_test_runtime_flags_.dump_resource_priorities();
 }
 
 bool TestRunner::RequestPointerLock() {
@@ -2027,7 +2021,7 @@
 }
 
 bool TestRunner::shouldDumpNavigationPolicy() const {
-  return dump_navigation_policy_;
+  return layout_test_runtime_flags_.dump_navigation_policy();
 }
 
 bool TestRunner::midiAccessorResult() {
@@ -2655,7 +2649,8 @@
 }
 
 void TestRunner::DumpEditingCallbacks() {
-  dump_editting_callbacks_ = true;
+  layout_test_runtime_flags_.set_dump_editting_callbacks(true);
+  OnLayoutTestRuntimeFlagsChanged();
 }
 
 void TestRunner::DumpAsMarkup() {
@@ -2692,7 +2687,8 @@
 }
 
 void TestRunner::DumpIconChanges() {
-  dump_icon_changes_ = true;
+  layout_test_runtime_flags_.set_dump_icon_changes(true);
+  OnLayoutTestRuntimeFlagsChanged();
 }
 
 void TestRunner::SetAudioData(const gin::ArrayBufferView& view) {
@@ -2703,19 +2699,24 @@
 }
 
 void TestRunner::DumpFrameLoadCallbacks() {
-  dump_frame_load_callbacks_ = true;
+  layout_test_runtime_flags_.set_dump_frame_load_callbacks(true);
+  OnLayoutTestRuntimeFlagsChanged();
 }
 
 void TestRunner::DumpPingLoaderCallbacks() {
-  dump_ping_loader_callbacks_ = true;
+  layout_test_runtime_flags_.set_dump_ping_loader_callbacks(true);
+  OnLayoutTestRuntimeFlagsChanged();
 }
 
 void TestRunner::DumpUserGestureInFrameLoadCallbacks() {
-  dump_user_gesture_in_frame_load_callbacks_ = true;
+  layout_test_runtime_flags_.set_dump_user_gesture_in_frame_load_callbacks(
+      true);
+  OnLayoutTestRuntimeFlagsChanged();
 }
 
 void TestRunner::DumpTitleChanges() {
-  dump_title_changes_ = true;
+  layout_test_runtime_flags_.set_dump_title_changes(true);
+  OnLayoutTestRuntimeFlagsChanged();
 }
 
 void TestRunner::DumpCreateView() {
@@ -2727,11 +2728,13 @@
 }
 
 void TestRunner::DumpResourceLoadCallbacks() {
-  dump_resource_load_callbacks_ = true;
+  layout_test_runtime_flags_.set_dump_resource_load_callbacks(true);
+  OnLayoutTestRuntimeFlagsChanged();
 }
 
 void TestRunner::DumpResourceResponseMIMETypes() {
-  dump_resource_response_mime_types_ = true;
+  layout_test_runtime_flags_.set_dump_resource_response_mime_types(true);
+  OnLayoutTestRuntimeFlagsChanged();
 }
 
 void TestRunner::SetImagesAllowed(bool allowed) {
@@ -2803,7 +2806,9 @@
 }
 
 void TestRunner::SetShouldStayOnPageAfterHandlingBeforeUnload(bool value) {
-  should_stay_on_page_after_handling_before_unload_ = value;
+  layout_test_runtime_flags_.set_stay_on_page_after_handling_before_unload(
+      value);
+  OnLayoutTestRuntimeFlagsChanged();
 }
 
 void TestRunner::SetWillSendRequestClearHeader(const std::string& header) {
@@ -2812,7 +2817,8 @@
 }
 
 void TestRunner::DumpResourceRequestPriorities() {
-  should_dump_resource_priorities_ = true;
+  layout_test_runtime_flags_.set_dump_resource_priorities(true);
+  OnLayoutTestRuntimeFlagsChanged();
 }
 
 void TestRunner::SetUseMockTheme(bool use) {
@@ -2826,7 +2832,8 @@
 }
 
 void TestRunner::WaitUntilExternalURLLoad() {
-  wait_until_external_url_load_ = true;
+  layout_test_runtime_flags_.set_wait_until_external_url_load(true);
+  OnLayoutTestRuntimeFlagsChanged();
 }
 
 void TestRunner::DumpDragImage() {
@@ -2836,7 +2843,8 @@
 }
 
 void TestRunner::DumpNavigationPolicy() {
-  dump_navigation_policy_ = true;
+  layout_test_runtime_flags_.set_dump_navigation_policy(true);
+  OnLayoutTestRuntimeFlagsChanged();
 }
 
 void TestRunner::DumpPageImportanceSignals() {
diff --git a/components/test_runner/test_runner.h b/components/test_runner/test_runner.h
index 2ab35da..8ea7370 100644
--- a/components/test_runner/test_runner.h
+++ b/components/test_runner/test_runner.h
@@ -686,10 +686,6 @@
   // setCloseRemainingWindowsWhenComplete().
   bool close_remaining_windows_;
 
-  // If true, ends the test when a URL is loaded externally via
-  // WebFrameClient::loadURLExternally().
-  bool wait_until_external_url_load_;
-
   WorkQueue work_queue_;
 
   // Bound variable to return the name of this platform (chromium).
@@ -701,37 +697,12 @@
   // Bound variable counting the number of top URLs visited.
   int web_history_item_count_;
 
-  // Bound variable to set whether postMessages should be intercepted or not
-  bool intercept_post_message_;
-
-  // If true, the test_shell will write a descriptive line for each editing
-  // command.
-  bool dump_editting_callbacks_;
-
   // Flags controlling what content gets dumped as a layout text result.
   LayoutTestRuntimeFlags layout_test_runtime_flags_;
 
-  // If true, the test_shell will print out the icon change notifications.
-  bool dump_icon_changes_;
-
   // If true, the test_shell will output a base64 encoded WAVE file.
   bool dump_as_audio_;
 
-  // If true, the test_shell will output a descriptive line for each frame
-  // load callback.
-  bool dump_frame_load_callbacks_;
-
-  // If true, the test_shell will output a descriptive line for each
-  // PingLoader dispatched.
-  bool dump_ping_loader_callbacks_;
-
-  // If true, the test_shell will output a line of the user gesture status
-  // text for some frame load callbacks.
-  bool dump_user_gesture_in_frame_load_callbacks_;
-
-  // If true, output a message when the page title is changed.
-  bool dump_title_changes_;
-
   // If true, output a descriptive line each time WebViewClient::createView
   // is invoked.
   bool dump_create_view_;
@@ -741,14 +712,6 @@
   // setCanOpenWindows().
   bool can_open_windows_;
 
-  // If true, the test_shell will output a descriptive line for each resource
-  // load callback.
-  bool dump_resource_load_callbacks_;
-
-  // If true, the test_shell will output the MIME type for each resource that
-  // was loaded.
-  bool dump_resource_response_mime_types_;
-
   // If true, the test_shell will dump all changes to window.status.
   bool dump_window_status_changes_;
 
@@ -760,10 +723,6 @@
   // well.
   bool dump_back_forward_list_;
 
-  // If true, content_shell will dump the default navigation policy passed to
-  // WebFrameClient::decidePolicyForNavigation.
-  bool dump_navigation_policy_;
-
   // If true, pixel dump will be produced as a series of 1px-tall, view-wide
   // individual paints over the height of the view.
   bool test_repaint_;
@@ -775,10 +734,6 @@
   // If false, MockWebMIDIAccessor fails on startSession() for testing.
   bool midi_accessor_result_;
 
-  bool should_stay_on_page_after_handling_before_unload_;
-
-  bool should_dump_resource_priorities_;
-
   bool has_custom_text_output_;
   std::string custom_text_output_;
 
diff --git a/components/variations/variations_seed_store_unittest.cc b/components/variations/variations_seed_store_unittest.cc
index 577e3f8c..c687932 100644
--- a/components/variations/variations_seed_store_unittest.cc
+++ b/components/variations/variations_seed_store_unittest.cc
@@ -329,15 +329,10 @@
             seed_store.VerifySeedSignature(seed_data, seed_data));
 
   // Using a different signature (e.g. the base64 seed data) should fail.
-#if defined(USE_OPENSSL)
   // OpenSSL doesn't distinguish signature decode failure from the
   // signature not matching.
   EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_INVALID_SEED,
             seed_store.VerifySeedSignature(seed_data, base64_seed_data));
-#else
-  EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_INVALID_SIGNATURE,
-            seed_store.VerifySeedSignature(seed_data, base64_seed_data));
-#endif
 
   // Using a different seed should not match the signature.
   seed_data[0] = 'x';
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index d04fac6b..d36ad98 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -176,7 +176,7 @@
 #include "ui/gfx/x/x11_types.h"  // nogncheck
 #endif
 
-#if defined(USE_NSS_CERTS) || !defined(USE_OPENSSL)
+#if defined(USE_NSS_CERTS)
 #include "crypto/nss_util.h"
 #endif
 
@@ -495,7 +495,7 @@
   net::EnsureWinsockInit();
 #endif
 
-#if defined(USE_NSS_CERTS) || !defined(USE_OPENSSL)
+#if defined(USE_NSS_CERTS)
   // We want to be sure to init NSPR on the main thread.
   crypto::EnsureNSPRInit();
 #endif
diff --git a/content/browser/media/webrtc/webrtc_browsertest.cc b/content/browser/media/webrtc/webrtc_browsertest.cc
index 7dd174f..9036deea 100644
--- a/content/browser/media/webrtc/webrtc_browsertest.cc
+++ b/content/browser/media/webrtc/webrtc_browsertest.cc
@@ -96,9 +96,9 @@
 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
                        CanSetupVideoCallWith4To3AspectRatio) {
   const std::string javascript =
-      "callAndExpectResolution({video: {mandatory: { minWidth: 960,"
-      "maxWidth: 960, minAspectRatio: 1.333, maxAspectRatio: 1.333}}}, 960,"
-      " 720);";
+      "callAndExpectResolution({video: {mandatory: { minWidth: 320,"
+      "maxWidth: 320, minAspectRatio: 1.333, maxAspectRatio: 1.333}}}, 320,"
+      " 240);";
   MakeTypicalPeerConnectionCall(javascript);
 }
 
diff --git a/content/browser/renderer_host/input/mouse_wheel_event_queue.cc b/content/browser/renderer_host/input/mouse_wheel_event_queue.cc
index 38405d8..2c7774bd 100644
--- a/content/browser/renderer_host/input/mouse_wheel_event_queue.cc
+++ b/content/browser/renderer_host/input/mouse_wheel_event_queue.cc
@@ -83,6 +83,7 @@
   // If event wasn't consumed then generate a gesture scroll for it.
   if (send_gestures_ && ack_result != INPUT_EVENT_ACK_STATE_CONSUMED &&
       event_sent_for_gesture_ack_->event.canScroll &&
+      event_sent_for_gesture_ack_->event.resendingPluginId == -1 &&
       (scrolling_device_ == blink::WebGestureDeviceUninitialized ||
        scrolling_device_ == blink::WebGestureDeviceTouchpad)) {
     WebGestureEvent scroll_update;
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 1b899725..4ca26b60 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -614,8 +614,12 @@
 void ServiceWorkerVersion::Doom() {
   DCHECK(!HasControllee());
   SetStatus(REDUNDANT);
-  if (running_status() == STARTING || running_status() == RUNNING)
-    embedded_worker_->Stop();
+  if (running_status() == STARTING || running_status() == RUNNING) {
+    if (embedded_worker()->devtools_attached())
+      stop_when_devtools_detached_ = true;
+    else
+      embedded_worker_->Stop();
+  }
   if (!context_)
     return;
   std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
@@ -625,6 +629,12 @@
 
 void ServiceWorkerVersion::SetDevToolsAttached(bool attached) {
   embedded_worker()->set_devtools_attached(attached);
+  if (stop_when_devtools_detached_ && !attached) {
+    DCHECK_EQ(REDUNDANT, status());
+    if (running_status() == STARTING || running_status() == RUNNING)
+      embedded_worker_->Stop();
+    return;
+  }
   if (attached) {
     // TODO(falken): Canceling the timeouts when debugging could cause
     // heisenbugs; we should instead run them as normal show an educational
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index 214cd58..af006d8 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -669,6 +669,8 @@
   std::unique_ptr<Metrics> metrics_;
   const bool should_exclude_from_uma_ = false;
 
+  bool stop_when_devtools_detached_ = false;
+
   base::WeakPtrFactory<ServiceWorkerVersion> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersion);
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index ba2787d..44eaf6d9 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -198,6 +198,11 @@
   WebRuntimeFeatures::enableMediaDocumentDownloadButton(
       base::FeatureList::IsEnabled(features::kMediaDocumentDownloadButton));
 
+  if (base::FeatureList::IsEnabled(features::kPointerEvents)) {
+      WebRuntimeFeatures::enableFeatureFromString(
+        std::string("PointerEvent"), true);
+  }
+
   // Enable explicitly enabled features, and then disable explicitly disabled
   // ones.
   if (command_line.HasSwitch(switches::kEnableBlinkFeatures)) {
diff --git a/content/content_shell.gypi b/content/content_shell.gypi
index cb15a5f..7d024c3 100644
--- a/content/content_shell.gypi
+++ b/content/content_shell.gypi
@@ -269,6 +269,7 @@
         ['use_x11 == 1', {
           'dependencies': [
             '../ui/events/devices/events_devices.gyp:events_devices',
+            '../ui/events/devices/x11/events_devices_x11.gyp:events_devices_x11',
             '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
           ],
         }],
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index d904a830..e999affe 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -58,6 +58,10 @@
     "OptimizeForSmallResource",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Partial support for pointer event feature.
+const base::Feature kPointerEvents{"PointerEvent",
+                                   base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Throttle Blink's rendering pipeline based on frame visibility.
 const base::Feature kRenderingPipelineThrottling{
     "RenderingPipelineThrottling", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 14205702..88f9d378 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -25,6 +25,7 @@
 CONTENT_EXPORT extern const base::Feature kMediaDocumentDownloadButton;
 CONTENT_EXPORT extern const base::Feature kNonValidatingReloadOnRefreshContent;
 CONTENT_EXPORT extern const base::Feature kOptimizeIPCForSmallResource;
+CONTENT_EXPORT extern const base::Feature kPointerEvents;
 CONTENT_EXPORT extern const base::Feature kRenderingPipelineThrottling;
 CONTENT_EXPORT extern const base::Feature kScrollAnchoring;
 CONTENT_EXPORT extern const base::Feature kStaleWhileRevalidate;
diff --git a/content/renderer/media/rtc_video_encoder.cc b/content/renderer/media/rtc_video_encoder.cc
index ae67c980..2a2891c 100644
--- a/content/renderer/media/rtc_video_encoder.cc
+++ b/content/renderer/media/rtc_video_encoder.cc
@@ -15,6 +15,7 @@
 #include "base/numerics/safe_conversions.h"
 #include "base/rand_util.h"
 #include "base/single_thread_task_runner.h"
+#include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/thread_task_runner_handle.h"
 #include "media/base/bind_to_current_loop.h"
@@ -91,20 +92,17 @@
 // This private class of RTCVideoEncoder does the actual work of communicating
 // with a media::VideoEncodeAccelerator for handling video encoding.  It can
 // be created on any thread, but should subsequently be posted to (and Destroy()
-// called on) a single thread.  Callbacks to RTCVideoEncoder are posted to the
-// thread on which the instance was constructed.
+// called on) a single thread.
 //
 // This class separates state related to the thread that RTCVideoEncoder
-// operates on (presently the libjingle worker thread) from the thread that
-// |gpu_factories_| provides for accelerator operations (presently the media
-// thread).  The RTCVideoEncoder class can be deleted directly by WebRTC, while
-// RTCVideoEncoder::Impl stays around long enough to properly shut down the VEA.
+// operates on from the thread that |gpu_factories_| provides for accelerator
+// operations (presently the media thread).
 class RTCVideoEncoder::Impl
     : public media::VideoEncodeAccelerator::Client,
       public base::RefCountedThreadSafe<RTCVideoEncoder::Impl> {
  public:
-  Impl(const base::WeakPtr<RTCVideoEncoder>& weak_encoder,
-       media::GpuVideoAcceleratorFactories* gpu_factories);
+  Impl(media::GpuVideoAcceleratorFactories* gpu_factories,
+       webrtc::VideoCodecType video_codec_type);
 
   // Create the VEA and call Initialize() on it.  Called once per instantiation,
   // and then the instance is bound forevermore to whichever thread made the
@@ -132,9 +130,18 @@
   // Request encoding parameter change for the underlying encoder.
   void RequestEncodingParametersChange(uint32_t bitrate, uint32_t framerate);
 
+  void RegisterEncodeCompleteCallback(base::WaitableEvent* async_waiter,
+                                      int32_t* async_retval,
+                                      webrtc::EncodedImageCallback* callback);
+
   // Destroy this Impl's encoder.  The destructor is not explicitly called, as
   // Impl is a base::RefCountedThreadSafe.
-  void Destroy();
+  void Destroy(base::WaitableEvent* async_waiter);
+
+  // Return the status of Impl. One of WEBRTC_VIDEO_CODEC_XXX value.
+  int32_t GetStatus() const;
+
+  webrtc::VideoCodecType video_codec_type() { return video_codec_type_; }
 
   // media::VideoEncodeAccelerator::Client implementation.
   void RequireBitstreamBuffers(unsigned int input_count,
@@ -180,15 +187,17 @@
   // requirements.
   bool RequiresSizeChange(const scoped_refptr<media::VideoFrame>& frame) const;
 
+  // Return an encoded output buffer to WebRTC.
+  void ReturnEncodedImage(const webrtc::EncodedImage& image,
+                          int32_t bitstream_buffer_id,
+                          uint16_t picture_id);
+
+  void SetStatus(int32_t status);
+
+  // This is attached to |gpu_task_runner_|, not the thread class is constructed
+  // on.
   base::ThreadChecker thread_checker_;
 
-  // Weak pointer to the parent RTCVideoEncoder, for posting back VEA::Client
-  // notifications.
-  const base::WeakPtr<RTCVideoEncoder> weak_encoder_;
-
-  // The message loop on which to post callbacks to |weak_encoder_|.
-  const scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner_;
-
   // Factory for creating VEAs, shared memory buffers, etc.
   media::GpuVideoAcceleratorFactories* gpu_factories_;
 
@@ -228,19 +237,36 @@
   // 15 bits running index of the VP8 frames. See VP8 RTP spec for details.
   uint16_t picture_id_;
 
+  // webrtc::VideoEncoder encode complete callback.
+  webrtc::EncodedImageCallback* encoded_image_callback_;
+
+  // The video codec type, as reported to WebRTC.
+  const webrtc::VideoCodecType video_codec_type_;
+
+  // Protect |status_|. |status_| is read or written on |gpu_task_runner_| in
+  // Impl. It can be read in RTCVideoEncoder on other threads.
+  mutable base::Lock status_lock_;
+
+  // We cannot immediately return error conditions to the WebRTC user of this
+  // class, as there is no error callback in the webrtc::VideoEncoder interface.
+  // Instead, we cache an error status here and return it the next time an
+  // interface entry point is called. This is protected by |status_lock_|.
+  int32_t status_;
+
   DISALLOW_COPY_AND_ASSIGN(Impl);
 };
 
-RTCVideoEncoder::Impl::Impl(const base::WeakPtr<RTCVideoEncoder>& weak_encoder,
-                            media::GpuVideoAcceleratorFactories* gpu_factories)
-    : weak_encoder_(weak_encoder),
-      encoder_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      gpu_factories_(gpu_factories),
+RTCVideoEncoder::Impl::Impl(media::GpuVideoAcceleratorFactories* gpu_factories,
+                            webrtc::VideoCodecType video_codec_type)
+    : gpu_factories_(gpu_factories),
       async_waiter_(NULL),
       async_retval_(NULL),
       input_next_frame_(NULL),
       input_next_frame_keyframe_(false),
-      output_buffers_free_count_(0) {
+      output_buffers_free_count_(0),
+      encoded_image_callback_(nullptr),
+      video_codec_type_(video_codec_type),
+      status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED) {
   thread_checker_.DetachFromThread();
   // Picture ID should start on a random number.
   picture_id_ = static_cast<uint16_t>(base::RandInt(0, 0x7FFF));
@@ -255,6 +281,7 @@
   DVLOG(3) << "Impl::CreateAndInitializeVEA()";
   DCHECK(thread_checker_.CalledOnValidThread());
 
+  SetStatus(WEBRTC_VIDEO_CODEC_UNINITIALIZED);
   RegisterAsyncWaiter(async_waiter, async_retval);
 
   // Check for overflow converting bitrate (kilobits/sec) to bits/sec.
@@ -274,6 +301,8 @@
                       media::VideoEncodeAccelerator::kInvalidArgumentError);
     return;
   }
+  // RequireBitstreamBuffers or NotifyError will be called and the waiter will
+  // be signaled.
 }
 
 void RTCVideoEncoder::Impl::Enqueue(const webrtc::VideoFrame* input_frame,
@@ -285,6 +314,12 @@
   DCHECK(!input_next_frame_);
 
   RegisterAsyncWaiter(async_waiter, async_retval);
+  int32_t retval = GetStatus();
+  if (retval != WEBRTC_VIDEO_CODEC_OK) {
+    SignalAsyncWaiter(retval);
+    return;
+  }
+
   // If there are no free input and output buffers, drop the frame to avoid a
   // deadlock. If there is a free input buffer, EncodeOneFrame will run and
   // unblock Encode(). If there are no free input buffers but there is a free
@@ -344,10 +379,24 @@
     video_encoder_->RequestEncodingParametersChange(bitrate * 1000, framerate);
 }
 
-void RTCVideoEncoder::Impl::Destroy() {
+void RTCVideoEncoder::Impl::Destroy(base::WaitableEvent* async_waiter) {
   DVLOG(3) << "Impl::Destroy()";
   DCHECK(thread_checker_.CalledOnValidThread());
-  video_encoder_.reset();
+  if (video_encoder_) {
+    video_encoder_.reset();
+    SetStatus(WEBRTC_VIDEO_CODEC_UNINITIALIZED);
+  }
+  async_waiter->Signal();
+}
+
+int32_t RTCVideoEncoder::Impl::GetStatus() const {
+  base::AutoLock lock(status_lock_);
+  return status_;
+}
+
+void RTCVideoEncoder::Impl::SetStatus(int32_t status) {
+  base::AutoLock lock(status_lock_);
+  status_ = status;
 }
 
 void RTCVideoEncoder::Impl::RequireBitstreamBuffers(
@@ -394,6 +443,8 @@
         i, output_buffers_[i]->handle(), output_buffers_[i]->mapped_size()));
     output_buffers_free_count_++;
   }
+  DCHECK_EQ(GetStatus(), WEBRTC_VIDEO_CODEC_UNINITIALIZED);
+  SetStatus(WEBRTC_VIDEO_CODEC_OK);
   SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK);
 }
 
@@ -429,21 +480,18 @@
   const uint32_t rtp_timestamp =
       static_cast<uint32_t>(capture_time_us * 90 / 1000);
 
-  std::unique_ptr<webrtc::EncodedImage> image(new webrtc::EncodedImage(
+  webrtc::EncodedImage image(
       reinterpret_cast<uint8_t*>(output_buffer->memory()), payload_size,
-      output_buffer->mapped_size()));
-  image->_encodedWidth = input_visible_size_.width();
-  image->_encodedHeight = input_visible_size_.height();
-  image->_timeStamp = rtp_timestamp;
-  image->capture_time_ms_ = capture_time_ms;
-  image->_frameType =
+      output_buffer->mapped_size());
+  image._encodedWidth = input_visible_size_.width();
+  image._encodedHeight = input_visible_size_.height();
+  image._timeStamp = rtp_timestamp;
+  image.capture_time_ms_ = capture_time_ms;
+  image._frameType =
       (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta);
-  image->_completeFrame = true;
+  image._completeFrame = true;
 
-  encoder_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&RTCVideoEncoder::ReturnEncodedImage, weak_encoder_,
-                 base::Passed(&image), bitstream_buffer_id, picture_id_));
+  ReturnEncodedImage(image, bitstream_buffer_id, picture_id_);
   // Picture ID must wrap after reaching the maximum.
   picture_id_ = (picture_id_ + 1) & 0x7FFF;
 }
@@ -462,13 +510,9 @@
 
   video_encoder_.reset();
 
-  if (async_waiter_) {
+  SetStatus(retval);
+  if (async_waiter_)
     SignalAsyncWaiter(retval);
-  } else {
-    encoder_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&RTCVideoEncoder::NotifyError, weak_encoder_, retval));
-  }
 }
 
 RTCVideoEncoder::Impl::~Impl() { DCHECK(!video_encoder_); }
@@ -599,23 +643,87 @@
           frame->visible_rect() != gfx::Rect(input_visible_size_));
 }
 
+void RTCVideoEncoder::Impl::RegisterEncodeCompleteCallback(
+    base::WaitableEvent* async_waiter,
+    int32_t* async_retval,
+    webrtc::EncodedImageCallback* callback) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DVLOG(3) << "RegisterEncodeCompleteCallback()";
+  RegisterAsyncWaiter(async_waiter, async_retval);
+  int32_t retval = GetStatus();
+  if (retval == WEBRTC_VIDEO_CODEC_OK)
+    encoded_image_callback_ = callback;
+  SignalAsyncWaiter(retval);
+}
+
+void RTCVideoEncoder::Impl::ReturnEncodedImage(
+    const webrtc::EncodedImage& image,
+    int32_t bitstream_buffer_id,
+    uint16_t picture_id) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DVLOG(3) << "ReturnEncodedImage(): "
+           << "bitstream_buffer_id=" << bitstream_buffer_id
+           << ", picture_id=" << picture_id;
+
+  if (!encoded_image_callback_)
+    return;
+
+  webrtc::RTPFragmentationHeader header;
+  memset(&header, 0, sizeof(header));
+  switch (video_codec_type_) {
+    case webrtc::kVideoCodecVP8:
+      // Generate a header describing a single fragment.
+      header.VerifyAndAllocateFragmentationHeader(1);
+      header.fragmentationOffset[0] = 0;
+      header.fragmentationLength[0] = image._length;
+      header.fragmentationPlType[0] = 0;
+      header.fragmentationTimeDiff[0] = 0;
+      break;
+    case webrtc::kVideoCodecH264:
+      if (!GetRTPFragmentationHeaderH264(&header, image._buffer,
+                                         image._length)) {
+        DLOG(ERROR) << "Failed to get RTP fragmentation header for H264";
+        NotifyError(
+            (media::VideoEncodeAccelerator::Error)WEBRTC_VIDEO_CODEC_ERROR);
+        return;
+      }
+      break;
+    default:
+      NOTREACHED() << "Invalid video codec type";
+      return;
+  }
+
+  webrtc::CodecSpecificInfo info;
+  memset(&info, 0, sizeof(info));
+  info.codecType = video_codec_type_;
+  if (video_codec_type_ == webrtc::kVideoCodecVP8) {
+    info.codecSpecific.VP8.pictureId = picture_id;
+    info.codecSpecific.VP8.tl0PicIdx = -1;
+    info.codecSpecific.VP8.keyIdx = -1;
+  }
+
+  const int32_t retval =
+      encoded_image_callback_->Encoded(image, &info, &header);
+  if (retval < 0) {
+    DVLOG(2) << "ReturnEncodedImage(): encoded_image_callback_ returned "
+             << retval;
+  }
+
+  UseOutputBitstreamBufferId(bitstream_buffer_id);
+}
+
 RTCVideoEncoder::RTCVideoEncoder(
     webrtc::VideoCodecType type,
     media::GpuVideoAcceleratorFactories* gpu_factories)
-    : video_codec_type_(type),
-      gpu_factories_(gpu_factories),
+    : gpu_factories_(gpu_factories),
       gpu_task_runner_(gpu_factories->GetTaskRunner()),
-      encoded_image_callback_(NULL),
-      impl_status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED),
-      weak_factory_(this) {
+      impl_(new Impl(gpu_factories_, type)) {
   DVLOG(1) << "RTCVideoEncoder(): codec type=" << type;
 }
 
 RTCVideoEncoder::~RTCVideoEncoder() {
   DVLOG(3) << "~RTCVideoEncoder";
-  DCHECK(thread_checker_.CalledOnValidThread());
   Release();
-  DCHECK(!impl_.get());
 }
 
 int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings,
@@ -625,14 +733,10 @@
            << ", width=" << codec_settings->width
            << ", height=" << codec_settings->height
            << ", startBitrate=" << codec_settings->startBitrate;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(!impl_.get());
 
-  const media::VideoCodecProfile profile =
-      WebRTCVideoCodecToVideoCodecProfile(video_codec_type_, codec_settings);
+  const media::VideoCodecProfile profile = WebRTCVideoCodecToVideoCodecProfile(
+      impl_->video_codec_type(), codec_settings);
 
-  weak_factory_.InvalidateWeakPtrs();
-  impl_ = new Impl(weak_factory_.GetWeakPtr(), gpu_factories_);
   base::WaitableEvent initialization_waiter(true, false);
   int32_t initialization_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
   gpu_task_runner_->PostTask(
@@ -656,10 +760,6 @@
     const webrtc::CodecSpecificInfo* codec_specific_info,
     const std::vector<webrtc::FrameType>* frame_types) {
   DVLOG(3) << "Encode()";
-  if (!impl_.get()) {
-    DVLOG(3) << "Encode(): returning impl_status_=" << impl_status_;
-    return impl_status_;
-  }
 
   const bool want_key_frame = frame_types && frame_types->size() &&
                               frame_types->front() == webrtc::kVideoFrameKey;
@@ -683,27 +783,24 @@
 int32_t RTCVideoEncoder::RegisterEncodeCompleteCallback(
     webrtc::EncodedImageCallback* callback) {
   DVLOG(3) << "RegisterEncodeCompleteCallback()";
-  DCHECK(thread_checker_.CalledOnValidThread());
-  if (!impl_.get()) {
-    DVLOG(3) << "RegisterEncodeCompleteCallback(): returning " << impl_status_;
-    return impl_status_;
-  }
-
-  encoded_image_callback_ = callback;
-  return WEBRTC_VIDEO_CODEC_OK;
+  base::WaitableEvent register_waiter(true, false);
+  int32_t register_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
+  gpu_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&RTCVideoEncoder::Impl::RegisterEncodeCompleteCallback, impl_,
+                 &register_waiter, &register_retval, callback));
+  register_waiter.Wait();
+  return register_retval;
 }
 
 int32_t RTCVideoEncoder::Release() {
   DVLOG(3) << "Release()";
-  DCHECK(thread_checker_.CalledOnValidThread());
 
-  if (impl_.get()) {
-    gpu_task_runner_->PostTask(FROM_HERE,
-                           base::Bind(&RTCVideoEncoder::Impl::Destroy, impl_));
-    impl_ = NULL;
-    weak_factory_.InvalidateWeakPtrs();
-    impl_status_ = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
-  }
+  base::WaitableEvent release_waiter(true, false);
+  gpu_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&RTCVideoEncoder::Impl::Destroy, impl_, &release_waiter));
+  release_waiter.Wait();
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
@@ -718,9 +815,10 @@
 int32_t RTCVideoEncoder::SetRates(uint32_t new_bit_rate, uint32_t frame_rate) {
   DVLOG(3) << "SetRates(): new_bit_rate=" << new_bit_rate
            << ", frame_rate=" << frame_rate;
-  if (!impl_.get()) {
-    DVLOG(3) << "SetRates(): returning " << impl_status_;
-    return impl_status_;
+  const int32_t retval = impl_->GetStatus();
+  if (retval != WEBRTC_VIDEO_CODEC_OK) {
+    DVLOG(3) << "SetRates(): returning " << retval;
+    return retval;
   }
 
   gpu_task_runner_->PostTask(
@@ -732,76 +830,6 @@
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
-void RTCVideoEncoder::ReturnEncodedImage(
-    std::unique_ptr<webrtc::EncodedImage> image,
-    int32_t bitstream_buffer_id,
-    uint16_t picture_id) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DVLOG(3) << "ReturnEncodedImage(): "
-           << "bitstream_buffer_id=" << bitstream_buffer_id
-           << ", picture_id=" << picture_id;
-
-  if (!encoded_image_callback_)
-    return;
-
-  webrtc::RTPFragmentationHeader header;
-  memset(&header, 0, sizeof(header));
-  switch (video_codec_type_) {
-    case webrtc::kVideoCodecVP8:
-      // Generate a header describing a single fragment.
-      header.VerifyAndAllocateFragmentationHeader(1);
-      header.fragmentationOffset[0] = 0;
-      header.fragmentationLength[0] = image->_length;
-      header.fragmentationPlType[0] = 0;
-      header.fragmentationTimeDiff[0] = 0;
-      break;
-    case webrtc::kVideoCodecH264:
-      if (!GetRTPFragmentationHeaderH264(
-          &header, image->_buffer, image->_length)) {
-        DLOG(ERROR) << "Failed to get RTP fragmentation header for H264";
-        NotifyError(WEBRTC_VIDEO_CODEC_ERROR);
-        return;
-      }
-      break;
-    default:
-      NOTREACHED() << "Invalid video codec type";
-      return;
-  }
-
-  webrtc::CodecSpecificInfo info;
-  memset(&info, 0, sizeof(info));
-  info.codecType = video_codec_type_;
-  if (video_codec_type_ == webrtc::kVideoCodecVP8) {
-    info.codecSpecific.VP8.pictureId = picture_id;
-    info.codecSpecific.VP8.tl0PicIdx = -1;
-    info.codecSpecific.VP8.keyIdx = -1;
-  }
-
-  int32_t retval = encoded_image_callback_->Encoded(*image, &info, &header);
-  if (retval < 0) {
-    DVLOG(2) << "ReturnEncodedImage(): encoded_image_callback_ returned "
-             << retval;
-  }
-
-  // The call through webrtc::EncodedImageCallback is synchronous, so we can
-  // immediately recycle the output buffer back to the Impl.
-  gpu_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&RTCVideoEncoder::Impl::UseOutputBitstreamBufferId,
-                 impl_,
-                 bitstream_buffer_id));
-}
-
-void RTCVideoEncoder::NotifyError(int32_t error) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DVLOG(1) << "NotifyError(): error=" << error;
-
-  impl_status_ = error;
-  gpu_task_runner_->PostTask(FROM_HERE,
-                         base::Bind(&RTCVideoEncoder::Impl::Destroy, impl_));
-  impl_ = NULL;
-}
-
 void RTCVideoEncoder::RecordInitEncodeUMA(
     int32_t init_retval, media::VideoCodecProfile profile) {
   UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess",
diff --git a/content/renderer/media/rtc_video_encoder.h b/content/renderer/media/rtc_video_encoder.h
index d0cd43a..d8c5413e 100644
--- a/content/renderer/media/rtc_video_encoder.h
+++ b/content/renderer/media/rtc_video_encoder.h
@@ -32,12 +32,8 @@
 // trampolined to a private RTCVideoEncoder::Impl instance.  The Impl class runs
 // on the worker thread queried from the |gpu_factories_|, which is presently
 // the media thread.  RTCVideoEncoder is sychronized by webrtc::VideoSender.
-// webrtc::VideoEncoder methods do not run concurrently. RTCVideoEncoder is run
-// and destroyed on the thread it is constructed on, which is presently the
-// libjingle worker thread. Encode is run on ViECaptureThread. SetRates and
-// SetChannelParameters are run on ProcessThread or the libjingle worker thread.
-// Callbacks from the Impl due to its VEA::Client notifications are posted back
-// to RTCVideoEncoder on the libjingle worker thread.
+// webrtc::VideoEncoder methods do not run concurrently. RtcVideoEncoder needs
+// to synchronize RegisterEncodeCompleteCallback and encode complete callback.
 class CONTENT_EXPORT RTCVideoEncoder
     : NON_EXPORTED_BASE(public webrtc::VideoEncoder) {
  public:
@@ -64,44 +60,18 @@
   class Impl;
   friend class RTCVideoEncoder::Impl;
 
-  // Return an encoded output buffer to WebRTC.
-  void ReturnEncodedImage(std::unique_ptr<webrtc::EncodedImage> image,
-                          int32_t bitstream_buffer_id,
-                          uint16_t picture_id);
-
-  void NotifyError(int32_t error);
-
   void RecordInitEncodeUMA(int32_t init_retval,
                            media::VideoCodecProfile profile);
 
-  base::ThreadChecker thread_checker_;
-
-  // The video codec type, as reported to WebRTC.
-  const webrtc::VideoCodecType video_codec_type_;
-
   // Factory for creating VEAs, shared memory buffers, etc.
   media::GpuVideoAcceleratorFactories* gpu_factories_;
 
   // Task runner that the video accelerator runs on.
   const scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_;
 
-  // webrtc::VideoEncoder encode complete callback.
-  webrtc::EncodedImageCallback* encoded_image_callback_;
-
   // The RTCVideoEncoder::Impl that does all the work.
   scoped_refptr<Impl> impl_;
 
-  // We cannot immediately return error conditions to the WebRTC user of this
-  // class, as there is no error callback in the webrtc::VideoEncoder interface.
-  // Instead, we cache an error status here and return it the next time an
-  // interface entry point is called.
-  int32_t impl_status_;
-
-  // Weak pointer factory for posting back VEA::Client notifications to
-  // RTCVideoEncoder.
-  // NOTE: Weak pointers must be invalidated before all other member variables.
-  base::WeakPtrFactory<RTCVideoEncoder> weak_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(RTCVideoEncoder);
 };
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 5fadcf68..4f0d7c6 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -1126,7 +1126,7 @@
 
 void RenderFrameImpl::InitializeBlameContext(RenderFrameImpl* parent_frame) {
   DCHECK(!blame_context_);
-  blame_context_ = new FrameBlameContext(this, parent_frame);
+  blame_context_ = base::WrapUnique(new FrameBlameContext(this, parent_frame));
   blame_context_->Initialize();
 }
 
@@ -2557,7 +2557,7 @@
 
 blink::BlameContext* RenderFrameImpl::frameBlameContext() {
   DCHECK(blame_context_);
-  return blame_context_;
+  return blame_context_.get();
 }
 
 blink::WebServiceWorkerProvider*
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index eaadfa8..57c67a1 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -1220,7 +1220,7 @@
   std::unique_ptr<ExternalPopupMenu> external_popup_menu_;
 #endif
 
-  FrameBlameContext* blame_context_;  // Not owned.
+  std::unique_ptr<FrameBlameContext> blame_context_;
 
   base::WeakPtrFactory<RenderFrameImpl> weak_factory_;
 
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn
index b141202..8e59d0d 100644
--- a/content/shell/BUILD.gn
+++ b/content/shell/BUILD.gn
@@ -288,7 +288,7 @@
       "//tools/xdisplaycheck",
     ]
 
-    deps += [ "//ui/events/devices" ]
+    deps += [ "//ui/events/devices/x11" ]
   }
 
   if (is_android) {
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index ed2db4eb..9e23c65a 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -868,7 +868,7 @@
         [ "../browser/compositor/software_output_device_ozone_unittest.cc" ]
   }
 
-  if (is_mac && use_openssl) {
+  if (is_mac) {
     deps += [ "//third_party/boringssl" ]
   }
 
diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn
index ac48f7a..2b86893 100644
--- a/crypto/BUILD.gn
+++ b/crypto/BUILD.gn
@@ -19,27 +19,21 @@
     "crypto_export.h",
     "cssm_init.cc",
     "cssm_init.h",
-    "curve25519-donna.c",
     "curve25519.h",
-    "curve25519_nss.cc",
     "curve25519_openssl.cc",
     "ec_private_key.h",
-    "ec_private_key_nss.cc",
     "ec_private_key_openssl.cc",
     "ec_signature_creator.cc",
     "ec_signature_creator.h",
     "ec_signature_creator_impl.h",
-    "ec_signature_creator_nss.cc",
     "ec_signature_creator_openssl.cc",
     "encryptor.cc",
     "encryptor.h",
-    "encryptor_nss.cc",
     "encryptor_openssl.cc",
     "hkdf.cc",
     "hkdf.h",
     "hmac.cc",
     "hmac.h",
-    "hmac_nss.cc",
     "hmac_openssl.cc",
     "mac_security_services_lock.cc",
     "mac_security_services_lock.h",
@@ -66,33 +60,22 @@
     "random.cc",
     "random.h",
     "rsa_private_key.h",
-    "rsa_private_key_nss.cc",
     "rsa_private_key_openssl.cc",
     "scoped_capi_types.h",
     "scoped_nss_types.h",
     "secure_hash.h",
-    "secure_hash_default.cc",
     "secure_hash_openssl.cc",
     "secure_util.cc",
     "secure_util.h",
     "sha2.cc",
     "sha2.h",
     "signature_creator.h",
-    "signature_creator_nss.cc",
     "signature_creator_openssl.cc",
     "signature_verifier.h",
-    "signature_verifier_nss.cc",
     "signature_verifier_openssl.cc",
     "symmetric_key.h",
-    "symmetric_key_nss.cc",
     "symmetric_key_openssl.cc",
-    "third_party/nss/chromium-blapi.h",
-    "third_party/nss/chromium-blapit.h",
-    "third_party/nss/chromium-nss.h",
     "third_party/nss/chromium-sha256.h",
-    "third_party/nss/pk11akey.cc",
-    "third_party/nss/rsawrapr.c",
-    "third_party/nss/secsign.cc",
     "third_party/nss/sha512.cc",
   ]
 
@@ -130,53 +113,8 @@
     ]
   }
 
-  if (use_openssl) {
-    # Remove NSS files when using OpenSSL
-    sources -= [
-      "curve25519-donna.c",
-      "curve25519_nss.cc",
-      "ec_private_key_nss.cc",
-      "ec_signature_creator_nss.cc",
-      "encryptor_nss.cc",
-      "hmac_nss.cc",
-      "rsa_private_key_nss.cc",
-      "secure_hash_default.cc",
-      "signature_creator_nss.cc",
-      "signature_verifier_nss.cc",
-      "symmetric_key_nss.cc",
-      "third_party/nss/chromium-blapi.h",
-      "third_party/nss/chromium-blapit.h",
-      "third_party/nss/chromium-nss.h",
-      "third_party/nss/pk11akey.cc",
-      "third_party/nss/rsawrapr.c",
-      "third_party/nss/secsign.cc",
-    ]
-  } else {
-    # Remove OpenSSL when using NSS.
-    sources -= [
-      "aead_openssl.cc",
-      "aead_openssl.h",
-      "auto_cbb.h",
-      "curve25519_openssl.cc",
-      "ec_private_key_openssl.cc",
-      "ec_signature_creator_openssl.cc",
-      "encryptor_openssl.cc",
-      "hmac_openssl.cc",
-      "openssl_bio_string.cc",
-      "openssl_bio_string.h",
-      "openssl_util.cc",
-      "openssl_util.h",
-      "rsa_private_key_openssl.cc",
-      "secure_hash_openssl.cc",
-      "signature_creator_openssl.cc",
-      "signature_verifier_openssl.cc",
-      "symmetric_key_openssl.cc",
-    ]
-  }
-
-  # Some files are built when NSS is used at all, either for the internal crypto
-  # library or the platform certificate library.
-  if (use_openssl && !use_nss_certs) {
+  # Some files are built when NSS is used for the platform certificate library.
+  if (!use_nss_certs) {
     sources -= [
       "nss_key_util.cc",
       "nss_key_util.h",
@@ -248,19 +186,14 @@
     "symmetric_key_unittest.cc",
   ]
 
-  # Some files are built when NSS is used at all, either for the internal crypto
-  # library or the platform certificate library.
-  if (use_openssl && !use_nss_certs) {
+  # Some files are built when NSS is used for the platform certificate library.
+  if (!use_nss_certs) {
     sources -= [
       "nss_key_util_unittest.cc",
       "nss_util_unittest.cc",
     ]
   }
 
-  if (!use_openssl) {
-    sources -= [ "openssl_bio_string_unittest.cc" ]
-  }
-
   configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
 
   deps = [
@@ -308,7 +241,7 @@
 }
 
 config("platform_config") {
-  if ((!use_openssl || use_nss_certs) && is_clang) {
+  if (use_nss_certs && is_clang) {
     # There is a broken header guard in /usr/include/nss/secmod.h:
     # https://bugzilla.mozilla.org/show_bug.cgi?id=884072
     cflags = [ "-Wno-header-guard" ]
@@ -319,40 +252,14 @@
 # according to the state of the crypto flags. A target just wanting to depend
 # on the current SSL library should just depend on this.
 group("platform") {
-  if (use_openssl) {
-    public_deps = [
-      "//third_party/boringssl",
-    ]
-  } else {
-    public_deps = [
-      "//net/third_party/nss/ssl:libssl",
-    ]
-  }
+  public_deps = [
+    "//third_party/boringssl",
+  ]
 
-  # Link in NSS if it is used for either the internal crypto library
-  # (!use_openssl) or platform certificate library (use_nss_certs).
-  if (!use_openssl || use_nss_certs) {
-    if (is_linux) {
-      # On Linux, we use the system NSS (excepting SSL where we always use our
-      # own).
-      public_configs = [ ":platform_config" ]
-      if (!use_openssl) {
-        # If using a bundled copy of NSS's SSL library, ensure the bundled SSL
-        # header search path comes before the system one so our versions are
-        # used. The libssl target will add the search path we want, but
-        # according to GN's ordering rules, public_configs' search path will get
-        # applied before ones inherited from our dependencies.  Therefore, we
-        # need to explicitly list our custom libssl's config here before the
-        # system one.
-        public_configs += [ "//net/third_party/nss/ssl:ssl_config" ]
-      }
-      public_configs += [ "//third_party/nss:system_nss_no_ssl_config" ]
-    } else {
-      # Non-Linux platforms use the hermetic NSS from the tree.
-      public_deps += [
-        "//third_party/nss:nspr",
-        "//third_party/nss:nss",
-      ]
-    }
+  # Link in NSS if it is used for the platform certificate library
+  # (use_nss_certs).
+  if (use_nss_certs) {
+    public_configs = [ ":platform_config" ]
+    public_configs += [ "//third_party/nss:system_nss_no_ssl_config" ]
   }
 }
diff --git a/crypto/aead_openssl.cc b/crypto/aead_openssl.cc
index 7249421..8ad05dc 100644
--- a/crypto/aead_openssl.cc
+++ b/crypto/aead_openssl.cc
@@ -4,8 +4,6 @@
 
 #include "crypto/aead_openssl.h"
 
-#if defined(USE_OPENSSL)
-
 #include <openssl/aes.h>
 #include <openssl/evp.h>
 #include <stddef.h>
@@ -123,5 +121,3 @@
 }
 
 }  // namespace
-
-#endif
diff --git a/crypto/aead_openssl_unittest.cc b/crypto/aead_openssl_unittest.cc
index 446bca2..395e15a 100644
--- a/crypto/aead_openssl_unittest.cc
+++ b/crypto/aead_openssl_unittest.cc
@@ -10,8 +10,6 @@
 
 namespace {
 
-#if defined(USE_OPENSSL)
-
 TEST(AeadTest, SealOpen) {
   crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256);
   std::string key(aead.KeyLength(), 0);
@@ -49,6 +47,4 @@
   EXPECT_EQ(0U, decrypted.size());
 }
 
-#endif
-
 }  // namespace
diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp
index 21bd6c5..9edbe356 100644
--- a/crypto/crypto.gyp
+++ b/crypto/crypto.gyp
@@ -17,10 +17,17 @@
       'dependencies': [
         '../base/base.gyp:base',
         '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+        '../third_party/boringssl/boringssl.gyp:boringssl',
       ],
       'defines': [
         'CRYPTO_IMPLEMENTATION',
       ],
+      'sources!': [
+        'third_party/nss/chromium-nss.h',
+        'third_party/nss/chromium-prtypes.h',
+        'third_party/nss/chromium-sha256.h',
+        'third_party/nss/sha512.cc',
+      ],
       'conditions': [
         [ 'os_posix == 1 and OS != "mac" and OS != "ios" and OS != "android"', {
           'dependencies': [
@@ -70,16 +77,6 @@
             'mac_security_services_lock.h',
           ],
         }],
-        [ 'use_openssl == 0 and (OS == "mac" or OS == "ios" or OS == "win")', {
-          'dependencies': [
-            '../third_party/nss/nss.gyp:nspr',
-            '../third_party/nss/nss.gyp:nss',
-          ],
-          'export_dependent_settings': [
-            '../third_party/nss/nss.gyp:nspr',
-            '../third_party/nss/nss.gyp:nss',
-          ],
-        }],
         [ 'OS != "win"', {
           'sources!': [
             'capi_util.h',
@@ -91,58 +88,8 @@
             4267,  # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
           ],
         }],
-        [ 'use_openssl==1', {
-            'dependencies': [
-              '../third_party/boringssl/boringssl.gyp:boringssl',
-            ],
-            # TODO(joth): Use a glob to match exclude patterns once the
-            #             OpenSSL file set is complete.
-            'sources!': [
-              'curve25519-donna.c',
-              'curve25519_nss.cc',
-              'ec_private_key_nss.cc',
-              'ec_signature_creator_nss.cc',
-              'encryptor_nss.cc',
-              'hmac_nss.cc',
-              'rsa_private_key_nss.cc',
-              'secure_hash_default.cc',
-              'signature_creator_nss.cc',
-              'signature_verifier_nss.cc',
-              'symmetric_key_nss.cc',
-              'third_party/nss/chromium-blapi.h',
-              'third_party/nss/chromium-blapit.h',
-              'third_party/nss/chromium-nss.h',
-              'third_party/nss/chromium-prtypes.h',
-              'third_party/nss/chromium-sha256.h',
-              'third_party/nss/pk11akey.cc',
-              'third_party/nss/rsawrapr.c',
-              'third_party/nss/secsign.cc',
-              'third_party/nss/sha512.cc',
-            ],
-          }, {
-            'sources!': [
-              'aead_openssl.cc',
-              'aead_openssl.h',
-              'auto_cbb.h',
-              'curve25519_openssl.cc',
-              'ec_private_key_openssl.cc',
-              'ec_signature_creator_openssl.cc',
-              'encryptor_openssl.cc',
-              'hmac_openssl.cc',
-              'openssl_bio_string.cc',
-              'openssl_bio_string.h',
-              'openssl_util.cc',
-              'openssl_util.h',
-              'rsa_private_key_openssl.cc',
-              'secure_hash_openssl.cc',
-              'signature_creator_openssl.cc',
-              'signature_verifier_openssl.cc',
-              'symmetric_key_openssl.cc',
-            ],
-        },],
-        [ 'use_openssl==1 and use_nss_certs==0', {
-            # Some files are built when NSS is used at all, either for the
-            # internal crypto library or the platform certificate library.
+        [ 'use_nss_certs==0', {
+            # Some files are built when NSS is used for the platform certificate library.
             'sources!': [
               'nss_key_util.cc',
               'nss_key_util.h',
@@ -188,6 +135,7 @@
         '../base/base.gyp:test_support_base',
         '../testing/gmock.gyp:gmock',
         '../testing/gtest.gyp:gtest',
+        '../third_party/boringssl/boringssl.gyp:boringssl',
       ],
       'conditions': [
         [ 'use_nss_certs == 1', {
@@ -195,32 +143,17 @@
             '../build/linux/system.gyp:ssl',
           ],
         }],
-        [ 'use_openssl == 1 and use_nss_certs == 0', {
-          # Some files are built when NSS is used at all, either for the
-          # internal crypto library or the platform certificate library.
+        [ 'use_nss_certs == 0', {
+          # Some files are built when NSS is used for the platform certificate library.
           'sources!': [
             'nss_key_util_unittest.cc',
             'nss_util_unittest.cc',
           ],
         }],
-        [ 'use_openssl == 0 and (OS == "mac" or OS == "ios" or OS == "win")', {
-          'dependencies': [
-            '../third_party/nss/nss.gyp:nspr',
-          ],
-        }],
         [ 'OS == "win"', {
           # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
           'msvs_disabled_warnings': [4267, ],
         }],
-        [ 'use_openssl==1', {
-          'dependencies': [
-            '../third_party/boringssl/boringssl.gyp:boringssl',
-          ],
-        }, {
-          'sources!': [
-            'openssl_bio_string_unittest.cc',
-          ],
-        }],
       ],
     },
   ],
@@ -229,9 +162,7 @@
       'targets': [
         {
           'target_name': 'crypto_nacl_win64',
-          # We do not want nacl_helper to depend on NSS because this would
-          # require including a 64-bit copy of NSS. Thus, use the native APIs
-          # for the helper.
+          # We use the native APIs for the helper.
           'type': '<(component)',
           'dependencies': [
             '../base/base.gyp:base_win64',
diff --git a/crypto/crypto.gypi b/crypto/crypto.gypi
index a7135cf6..748f4a9 100644
--- a/crypto/crypto.gypi
+++ b/crypto/crypto.gypi
@@ -15,8 +15,6 @@
         'secure_util.h',
         'symmetric_key.h',
         'symmetric_key_win.cc',
-        'third_party/nss/chromium-blapi.h',
-        'third_party/nss/chromium-blapit.h',
         'third_party/nss/chromium-prtypes.h',
         'third_party/nss/chromium-sha256.h',
         'third_party/nss/sha512.cc',
@@ -38,25 +36,19 @@
       'crypto_export.h',
       'cssm_init.cc',
       'cssm_init.h',
-      'curve25519-donna.c',
       'curve25519.h',
-      'curve25519_nss.cc',
       'curve25519_openssl.cc',
       'ec_private_key.h',
-      'ec_private_key_nss.cc',
       'ec_private_key_openssl.cc',
       'ec_signature_creator.cc',
       'ec_signature_creator.h',
       'ec_signature_creator_impl.h',
-      'ec_signature_creator_nss.cc',
       'ec_signature_creator_openssl.cc',
       'encryptor.cc',
       'encryptor.h',
-      'encryptor_nss.cc',
       'encryptor_openssl.cc',
       'hkdf.cc',
       'hkdf.h',
-      'hmac_nss.cc',
       'hmac_openssl.cc',
       'mac_security_services_lock.cc',
       'mac_security_services_lock.h',
@@ -81,27 +73,18 @@
       'random.h',
       'random.cc',
       'rsa_private_key.h',
-      'rsa_private_key_nss.cc',
       'rsa_private_key_openssl.cc',
       'scoped_capi_types.h',
       'scoped_nss_types.h',
       'secure_hash.h',
-      'secure_hash_default.cc',
       'secure_hash_openssl.cc',
       'sha2.cc',
       'sha2.h',
       'signature_creator.h',
-      'signature_creator_nss.cc',
       'signature_creator_openssl.cc',
       'signature_verifier.h',
-      'signature_verifier_nss.cc',
       'signature_verifier_openssl.cc',
-      'symmetric_key_nss.cc',
       'symmetric_key_openssl.cc',
-      'third_party/nss/chromium-nss.h',
-      'third_party/nss/pk11akey.cc',
-      'third_party/nss/rsawrapr.c',
-      'third_party/nss/secsign.cc',
     ],
     'nacl_win64_sources': [
       '<@(hmac_win64_related_sources)',
diff --git a/crypto/curve25519-donna.c b/crypto/curve25519-donna.c
deleted file mode 100644
index f141ac0..0000000
--- a/crypto/curve25519-donna.c
+++ /dev/null
@@ -1,592 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/*
- * curve25519-donna: Curve25519 elliptic curve, public key function
- *
- * http://code.google.com/p/curve25519-donna/
- *
- * Adam Langley <agl@imperialviolet.org>
- *
- * Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to>
- *
- * More information about curve25519 can be found here
- *   http://cr.yp.to/ecdh.html
- *
- * djb's sample implementation of curve25519 is written in a special assembly
- * language called qhasm and uses the floating point registers.
- *
- * This is, almost, a clean room reimplementation from the curve25519 paper. It
- * uses many of the tricks described therein. Only the crecip function is taken
- * from the sample implementation.
- */
-
-#include <string.h>
-#include <stdint.h>
-
-typedef uint8_t u8;
-typedef int32_t s32;
-typedef int64_t limb;
-
-/* Field element representation:
- *
- * Field elements are written as an array of signed, 64-bit limbs, least
- * significant first. The value of the field element is:
- *   x[0] + 2^26·x[1] + x^51·x[2] + 2^102·x[3] + ...
- *
- * i.e. the limbs are 26, 25, 26, 25, ... bits wide.
- */
-
-/* Sum two numbers: output += in */
-static void fsum(limb *output, const limb *in) {
-  unsigned i;
-  for (i = 0; i < 10; i += 2) {
-    output[0+i] = (output[0+i] + in[0+i]);
-    output[1+i] = (output[1+i] + in[1+i]);
-  }
-}
-
-/* Find the difference of two numbers: output = in - output
- * (note the order of the arguments!)
- */
-static void fdifference(limb *output, const limb *in) {
-  unsigned i;
-  for (i = 0; i < 10; ++i) {
-    output[i] = (in[i] - output[i]);
-  }
-}
-
-/* Multiply a number my a scalar: output = in * scalar */
-static void fscalar_product(limb *output, const limb *in, const limb scalar) {
-  unsigned i;
-  for (i = 0; i < 10; ++i) {
-    output[i] = in[i] * scalar;
-  }
-}
-
-/* Multiply two numbers: output = in2 * in
- *
- * output must be distinct to both inputs. The inputs are reduced coefficient
- * form, the output is not.
- */
-static void fproduct(limb *output, const limb *in2, const limb *in) {
-  output[0] =       ((limb) ((s32) in2[0])) * ((s32) in[0]);
-  output[1] =       ((limb) ((s32) in2[0])) * ((s32) in[1]) +
-                    ((limb) ((s32) in2[1])) * ((s32) in[0]);
-  output[2] =  2 *  ((limb) ((s32) in2[1])) * ((s32) in[1]) +
-                    ((limb) ((s32) in2[0])) * ((s32) in[2]) +
-                    ((limb) ((s32) in2[2])) * ((s32) in[0]);
-  output[3] =       ((limb) ((s32) in2[1])) * ((s32) in[2]) +
-                    ((limb) ((s32) in2[2])) * ((s32) in[1]) +
-                    ((limb) ((s32) in2[0])) * ((s32) in[3]) +
-                    ((limb) ((s32) in2[3])) * ((s32) in[0]);
-  output[4] =       ((limb) ((s32) in2[2])) * ((s32) in[2]) +
-               2 * (((limb) ((s32) in2[1])) * ((s32) in[3]) +
-                    ((limb) ((s32) in2[3])) * ((s32) in[1])) +
-                    ((limb) ((s32) in2[0])) * ((s32) in[4]) +
-                    ((limb) ((s32) in2[4])) * ((s32) in[0]);
-  output[5] =       ((limb) ((s32) in2[2])) * ((s32) in[3]) +
-                    ((limb) ((s32) in2[3])) * ((s32) in[2]) +
-                    ((limb) ((s32) in2[1])) * ((s32) in[4]) +
-                    ((limb) ((s32) in2[4])) * ((s32) in[1]) +
-                    ((limb) ((s32) in2[0])) * ((s32) in[5]) +
-                    ((limb) ((s32) in2[5])) * ((s32) in[0]);
-  output[6] =  2 * (((limb) ((s32) in2[3])) * ((s32) in[3]) +
-                    ((limb) ((s32) in2[1])) * ((s32) in[5]) +
-                    ((limb) ((s32) in2[5])) * ((s32) in[1])) +
-                    ((limb) ((s32) in2[2])) * ((s32) in[4]) +
-                    ((limb) ((s32) in2[4])) * ((s32) in[2]) +
-                    ((limb) ((s32) in2[0])) * ((s32) in[6]) +
-                    ((limb) ((s32) in2[6])) * ((s32) in[0]);
-  output[7] =       ((limb) ((s32) in2[3])) * ((s32) in[4]) +
-                    ((limb) ((s32) in2[4])) * ((s32) in[3]) +
-                    ((limb) ((s32) in2[2])) * ((s32) in[5]) +
-                    ((limb) ((s32) in2[5])) * ((s32) in[2]) +
-                    ((limb) ((s32) in2[1])) * ((s32) in[6]) +
-                    ((limb) ((s32) in2[6])) * ((s32) in[1]) +
-                    ((limb) ((s32) in2[0])) * ((s32) in[7]) +
-                    ((limb) ((s32) in2[7])) * ((s32) in[0]);
-  output[8] =       ((limb) ((s32) in2[4])) * ((s32) in[4]) +
-               2 * (((limb) ((s32) in2[3])) * ((s32) in[5]) +
-                    ((limb) ((s32) in2[5])) * ((s32) in[3]) +
-                    ((limb) ((s32) in2[1])) * ((s32) in[7]) +
-                    ((limb) ((s32) in2[7])) * ((s32) in[1])) +
-                    ((limb) ((s32) in2[2])) * ((s32) in[6]) +
-                    ((limb) ((s32) in2[6])) * ((s32) in[2]) +
-                    ((limb) ((s32) in2[0])) * ((s32) in[8]) +
-                    ((limb) ((s32) in2[8])) * ((s32) in[0]);
-  output[9] =       ((limb) ((s32) in2[4])) * ((s32) in[5]) +
-                    ((limb) ((s32) in2[5])) * ((s32) in[4]) +
-                    ((limb) ((s32) in2[3])) * ((s32) in[6]) +
-                    ((limb) ((s32) in2[6])) * ((s32) in[3]) +
-                    ((limb) ((s32) in2[2])) * ((s32) in[7]) +
-                    ((limb) ((s32) in2[7])) * ((s32) in[2]) +
-                    ((limb) ((s32) in2[1])) * ((s32) in[8]) +
-                    ((limb) ((s32) in2[8])) * ((s32) in[1]) +
-                    ((limb) ((s32) in2[0])) * ((s32) in[9]) +
-                    ((limb) ((s32) in2[9])) * ((s32) in[0]);
-  output[10] = 2 * (((limb) ((s32) in2[5])) * ((s32) in[5]) +
-                    ((limb) ((s32) in2[3])) * ((s32) in[7]) +
-                    ((limb) ((s32) in2[7])) * ((s32) in[3]) +
-                    ((limb) ((s32) in2[1])) * ((s32) in[9]) +
-                    ((limb) ((s32) in2[9])) * ((s32) in[1])) +
-                    ((limb) ((s32) in2[4])) * ((s32) in[6]) +
-                    ((limb) ((s32) in2[6])) * ((s32) in[4]) +
-                    ((limb) ((s32) in2[2])) * ((s32) in[8]) +
-                    ((limb) ((s32) in2[8])) * ((s32) in[2]);
-  output[11] =      ((limb) ((s32) in2[5])) * ((s32) in[6]) +
-                    ((limb) ((s32) in2[6])) * ((s32) in[5]) +
-                    ((limb) ((s32) in2[4])) * ((s32) in[7]) +
-                    ((limb) ((s32) in2[7])) * ((s32) in[4]) +
-                    ((limb) ((s32) in2[3])) * ((s32) in[8]) +
-                    ((limb) ((s32) in2[8])) * ((s32) in[3]) +
-                    ((limb) ((s32) in2[2])) * ((s32) in[9]) +
-                    ((limb) ((s32) in2[9])) * ((s32) in[2]);
-  output[12] =      ((limb) ((s32) in2[6])) * ((s32) in[6]) +
-               2 * (((limb) ((s32) in2[5])) * ((s32) in[7]) +
-                    ((limb) ((s32) in2[7])) * ((s32) in[5]) +
-                    ((limb) ((s32) in2[3])) * ((s32) in[9]) +
-                    ((limb) ((s32) in2[9])) * ((s32) in[3])) +
-                    ((limb) ((s32) in2[4])) * ((s32) in[8]) +
-                    ((limb) ((s32) in2[8])) * ((s32) in[4]);
-  output[13] =      ((limb) ((s32) in2[6])) * ((s32) in[7]) +
-                    ((limb) ((s32) in2[7])) * ((s32) in[6]) +
-                    ((limb) ((s32) in2[5])) * ((s32) in[8]) +
-                    ((limb) ((s32) in2[8])) * ((s32) in[5]) +
-                    ((limb) ((s32) in2[4])) * ((s32) in[9]) +
-                    ((limb) ((s32) in2[9])) * ((s32) in[4]);
-  output[14] = 2 * (((limb) ((s32) in2[7])) * ((s32) in[7]) +
-                    ((limb) ((s32) in2[5])) * ((s32) in[9]) +
-                    ((limb) ((s32) in2[9])) * ((s32) in[5])) +
-                    ((limb) ((s32) in2[6])) * ((s32) in[8]) +
-                    ((limb) ((s32) in2[8])) * ((s32) in[6]);
-  output[15] =      ((limb) ((s32) in2[7])) * ((s32) in[8]) +
-                    ((limb) ((s32) in2[8])) * ((s32) in[7]) +
-                    ((limb) ((s32) in2[6])) * ((s32) in[9]) +
-                    ((limb) ((s32) in2[9])) * ((s32) in[6]);
-  output[16] =      ((limb) ((s32) in2[8])) * ((s32) in[8]) +
-               2 * (((limb) ((s32) in2[7])) * ((s32) in[9]) +
-                    ((limb) ((s32) in2[9])) * ((s32) in[7]));
-  output[17] =      ((limb) ((s32) in2[8])) * ((s32) in[9]) +
-                    ((limb) ((s32) in2[9])) * ((s32) in[8]);
-  output[18] = 2 *  ((limb) ((s32) in2[9])) * ((s32) in[9]);
-}
-
-/* Reduce a long form to a short form by taking the input mod 2^255 - 19. */
-static void freduce_degree(limb *output) {
-  /* Each of these shifts and adds ends up multiplying the value by 19. */
-  output[8] += output[18] << 4;
-  output[8] += output[18] << 1;
-  output[8] += output[18];
-  output[7] += output[17] << 4;
-  output[7] += output[17] << 1;
-  output[7] += output[17];
-  output[6] += output[16] << 4;
-  output[6] += output[16] << 1;
-  output[6] += output[16];
-  output[5] += output[15] << 4;
-  output[5] += output[15] << 1;
-  output[5] += output[15];
-  output[4] += output[14] << 4;
-  output[4] += output[14] << 1;
-  output[4] += output[14];
-  output[3] += output[13] << 4;
-  output[3] += output[13] << 1;
-  output[3] += output[13];
-  output[2] += output[12] << 4;
-  output[2] += output[12] << 1;
-  output[2] += output[12];
-  output[1] += output[11] << 4;
-  output[1] += output[11] << 1;
-  output[1] += output[11];
-  output[0] += output[10] << 4;
-  output[0] += output[10] << 1;
-  output[0] += output[10];
-}
-
-/* Reduce all coefficients of the short form input so that |x| < 2^26.
- *
- * On entry: |output[i]| < 2^62
- */
-static void freduce_coefficients(limb *output) {
-  unsigned i;
-  do {
-    output[10] = 0;
-
-    for (i = 0; i < 10; i += 2) {
-      limb over = output[i] / 0x4000000l;
-      output[i+1] += over;
-      output[i] -= over * 0x4000000l;
-
-      over = output[i+1] / 0x2000000;
-      output[i+2] += over;
-      output[i+1] -= over * 0x2000000;
-    }
-    output[0] += 19 * output[10];
-  } while (output[10]);
-}
-
-/* A helpful wrapper around fproduct: output = in * in2.
- *
- * output must be distinct to both inputs. The output is reduced degree and
- * reduced coefficient.
- */
-static void
-fmul(limb *output, const limb *in, const limb *in2) {
-  limb t[19];
-  fproduct(t, in, in2);
-  freduce_degree(t);
-  freduce_coefficients(t);
-  memcpy(output, t, sizeof(limb) * 10);
-}
-
-static void fsquare_inner(limb *output, const limb *in) {
-  output[0] =       ((limb) ((s32) in[0])) * ((s32) in[0]);
-  output[1] =  2 *  ((limb) ((s32) in[0])) * ((s32) in[1]);
-  output[2] =  2 * (((limb) ((s32) in[1])) * ((s32) in[1]) +
-                    ((limb) ((s32) in[0])) * ((s32) in[2]));
-  output[3] =  2 * (((limb) ((s32) in[1])) * ((s32) in[2]) +
-                    ((limb) ((s32) in[0])) * ((s32) in[3]));
-  output[4] =       ((limb) ((s32) in[2])) * ((s32) in[2]) +
-               4 *  ((limb) ((s32) in[1])) * ((s32) in[3]) +
-               2 *  ((limb) ((s32) in[0])) * ((s32) in[4]);
-  output[5] =  2 * (((limb) ((s32) in[2])) * ((s32) in[3]) +
-                    ((limb) ((s32) in[1])) * ((s32) in[4]) +
-                    ((limb) ((s32) in[0])) * ((s32) in[5]));
-  output[6] =  2 * (((limb) ((s32) in[3])) * ((s32) in[3]) +
-                    ((limb) ((s32) in[2])) * ((s32) in[4]) +
-                    ((limb) ((s32) in[0])) * ((s32) in[6]) +
-               2 *  ((limb) ((s32) in[1])) * ((s32) in[5]));
-  output[7] =  2 * (((limb) ((s32) in[3])) * ((s32) in[4]) +
-                    ((limb) ((s32) in[2])) * ((s32) in[5]) +
-                    ((limb) ((s32) in[1])) * ((s32) in[6]) +
-                    ((limb) ((s32) in[0])) * ((s32) in[7]));
-  output[8] =       ((limb) ((s32) in[4])) * ((s32) in[4]) +
-               2 * (((limb) ((s32) in[2])) * ((s32) in[6]) +
-                    ((limb) ((s32) in[0])) * ((s32) in[8]) +
-               2 * (((limb) ((s32) in[1])) * ((s32) in[7]) +
-                    ((limb) ((s32) in[3])) * ((s32) in[5])));
-  output[9] =  2 * (((limb) ((s32) in[4])) * ((s32) in[5]) +
-                    ((limb) ((s32) in[3])) * ((s32) in[6]) +
-                    ((limb) ((s32) in[2])) * ((s32) in[7]) +
-                    ((limb) ((s32) in[1])) * ((s32) in[8]) +
-                    ((limb) ((s32) in[0])) * ((s32) in[9]));
-  output[10] = 2 * (((limb) ((s32) in[5])) * ((s32) in[5]) +
-                    ((limb) ((s32) in[4])) * ((s32) in[6]) +
-                    ((limb) ((s32) in[2])) * ((s32) in[8]) +
-               2 * (((limb) ((s32) in[3])) * ((s32) in[7]) +
-                    ((limb) ((s32) in[1])) * ((s32) in[9])));
-  output[11] = 2 * (((limb) ((s32) in[5])) * ((s32) in[6]) +
-                    ((limb) ((s32) in[4])) * ((s32) in[7]) +
-                    ((limb) ((s32) in[3])) * ((s32) in[8]) +
-                    ((limb) ((s32) in[2])) * ((s32) in[9]));
-  output[12] =      ((limb) ((s32) in[6])) * ((s32) in[6]) +
-               2 * (((limb) ((s32) in[4])) * ((s32) in[8]) +
-               2 * (((limb) ((s32) in[5])) * ((s32) in[7]) +
-                    ((limb) ((s32) in[3])) * ((s32) in[9])));
-  output[13] = 2 * (((limb) ((s32) in[6])) * ((s32) in[7]) +
-                    ((limb) ((s32) in[5])) * ((s32) in[8]) +
-                    ((limb) ((s32) in[4])) * ((s32) in[9]));
-  output[14] = 2 * (((limb) ((s32) in[7])) * ((s32) in[7]) +
-                    ((limb) ((s32) in[6])) * ((s32) in[8]) +
-               2 *  ((limb) ((s32) in[5])) * ((s32) in[9]));
-  output[15] = 2 * (((limb) ((s32) in[7])) * ((s32) in[8]) +
-                    ((limb) ((s32) in[6])) * ((s32) in[9]));
-  output[16] =      ((limb) ((s32) in[8])) * ((s32) in[8]) +
-               4 *  ((limb) ((s32) in[7])) * ((s32) in[9]);
-  output[17] = 2 *  ((limb) ((s32) in[8])) * ((s32) in[9]);
-  output[18] = 2 *  ((limb) ((s32) in[9])) * ((s32) in[9]);
-}
-
-static void
-fsquare(limb *output, const limb *in) {
-  limb t[19];
-  fsquare_inner(t, in);
-  freduce_degree(t);
-  freduce_coefficients(t);
-  memcpy(output, t, sizeof(limb) * 10);
-}
-
-/* Take a little-endian, 32-byte number and expand it into polynomial form */
-static void
-fexpand(limb *output, const u8 *input) {
-#define F(n,start,shift,mask) \
-  output[n] = ((((limb) input[start + 0]) | \
-                ((limb) input[start + 1]) << 8 | \
-                ((limb) input[start + 2]) << 16 | \
-                ((limb) input[start + 3]) << 24) >> shift) & mask;
-  F(0, 0, 0, 0x3ffffff);
-  F(1, 3, 2, 0x1ffffff);
-  F(2, 6, 3, 0x3ffffff);
-  F(3, 9, 5, 0x1ffffff);
-  F(4, 12, 6, 0x3ffffff);
-  F(5, 16, 0, 0x1ffffff);
-  F(6, 19, 1, 0x3ffffff);
-  F(7, 22, 3, 0x1ffffff);
-  F(8, 25, 4, 0x3ffffff);
-  F(9, 28, 6, 0x1ffffff);
-#undef F
-}
-
-/* Take a fully reduced polynomial form number and contract it into a
- * little-endian, 32-byte array
- */
-static void
-fcontract(u8 *output, limb *input) {
-  int i;
-
-  do {
-    for (i = 0; i < 9; ++i) {
-      if ((i & 1) == 1) {
-        while (input[i] < 0) {
-          input[i] += 0x2000000;
-          input[i + 1]--;
-        }
-      } else {
-        while (input[i] < 0) {
-          input[i] += 0x4000000;
-          input[i + 1]--;
-        }
-      }
-    }
-    while (input[9] < 0) {
-      input[9] += 0x2000000;
-      input[0] -= 19;
-    }
-  } while (input[0] < 0);
-
-  input[1] <<= 2;
-  input[2] <<= 3;
-  input[3] <<= 5;
-  input[4] <<= 6;
-  input[6] <<= 1;
-  input[7] <<= 3;
-  input[8] <<= 4;
-  input[9] <<= 6;
-#define F(i, s) \
-  output[s+0] |=  input[i] & 0xff; \
-  output[s+1]  = (input[i] >> 8) & 0xff; \
-  output[s+2]  = (input[i] >> 16) & 0xff; \
-  output[s+3]  = (input[i] >> 24) & 0xff;
-  output[0] = 0;
-  output[16] = 0;
-  F(0,0);
-  F(1,3);
-  F(2,6);
-  F(3,9);
-  F(4,12);
-  F(5,16);
-  F(6,19);
-  F(7,22);
-  F(8,25);
-  F(9,28);
-#undef F
-}
-
-/* Input: Q, Q', Q-Q'
- * Output: 2Q, Q+Q'
- *
- *   x2 z3: long form
- *   x3 z3: long form
- *   x z: short form, destroyed
- *   xprime zprime: short form, destroyed
- *   qmqp: short form, preserved
- */
-static void fmonty(limb *x2, limb *z2,  /* output 2Q */
-                   limb *x3, limb *z3,  /* output Q + Q' */
-                   limb *x, limb *z,    /* input Q */
-                   limb *xprime, limb *zprime,  /* input Q' */
-                   const limb *qmqp /* input Q - Q' */) {
-  limb origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19],
-        zzprime[19], zzzprime[19], xxxprime[19];
-
-  memcpy(origx, x, 10 * sizeof(limb));
-  fsum(x, z);
-  fdifference(z, origx);  // does x - z
-
-  memcpy(origxprime, xprime, sizeof(limb) * 10);
-  fsum(xprime, zprime);
-  fdifference(zprime, origxprime);
-  fproduct(xxprime, xprime, z);
-  fproduct(zzprime, x, zprime);
-  freduce_degree(xxprime);
-  freduce_coefficients(xxprime);
-  freduce_degree(zzprime);
-  freduce_coefficients(zzprime);
-  memcpy(origxprime, xxprime, sizeof(limb) * 10);
-  fsum(xxprime, zzprime);
-  fdifference(zzprime, origxprime);
-  fsquare(xxxprime, xxprime);
-  fsquare(zzzprime, zzprime);
-  fproduct(zzprime, zzzprime, qmqp);
-  freduce_degree(zzprime);
-  freduce_coefficients(zzprime);
-  memcpy(x3, xxxprime, sizeof(limb) * 10);
-  memcpy(z3, zzprime, sizeof(limb) * 10);
-
-  fsquare(xx, x);
-  fsquare(zz, z);
-  fproduct(x2, xx, zz);
-  freduce_degree(x2);
-  freduce_coefficients(x2);
-  fdifference(zz, xx);  // does zz = xx - zz
-  memset(zzz + 10, 0, sizeof(limb) * 9);
-  fscalar_product(zzz, zz, 121665);
-  freduce_degree(zzz);
-  freduce_coefficients(zzz);
-  fsum(zzz, xx);
-  fproduct(z2, zz, zzz);
-  freduce_degree(z2);
-  freduce_coefficients(z2);
-}
-
-/* Calculates nQ where Q is the x-coordinate of a point on the curve
- *
- *   resultx/resultz: the x coordinate of the resulting curve point (short form)
- *   n: a little endian, 32-byte number
- *   q: a point of the curve (short form)
- */
-static void
-cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) {
-  limb a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0};
-  limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t;
-  limb e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1};
-  limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h;
-
-  unsigned i, j;
-
-  memcpy(nqpqx, q, sizeof(limb) * 10);
-
-  for (i = 0; i < 32; ++i) {
-    u8 byte = n[31 - i];
-    for (j = 0; j < 8; ++j) {
-      if (byte & 0x80) {
-        fmonty(nqpqx2, nqpqz2,
-               nqx2, nqz2,
-               nqpqx, nqpqz,
-               nqx, nqz,
-               q);
-      } else {
-        fmonty(nqx2, nqz2,
-               nqpqx2, nqpqz2,
-               nqx, nqz,
-               nqpqx, nqpqz,
-               q);
-      }
-
-      t = nqx;
-      nqx = nqx2;
-      nqx2 = t;
-      t = nqz;
-      nqz = nqz2;
-      nqz2 = t;
-      t = nqpqx;
-      nqpqx = nqpqx2;
-      nqpqx2 = t;
-      t = nqpqz;
-      nqpqz = nqpqz2;
-      nqpqz2 = t;
-
-      byte <<= 1;
-    }
-  }
-
-  memcpy(resultx, nqx, sizeof(limb) * 10);
-  memcpy(resultz, nqz, sizeof(limb) * 10);
-}
-
-// -----------------------------------------------------------------------------
-// Shamelessly copied from djb's code
-// -----------------------------------------------------------------------------
-static void
-crecip(limb *out, const limb *z) {
-  limb z2[10];
-  limb z9[10];
-  limb z11[10];
-  limb z2_5_0[10];
-  limb z2_10_0[10];
-  limb z2_20_0[10];
-  limb z2_50_0[10];
-  limb z2_100_0[10];
-  limb t0[10];
-  limb t1[10];
-  int i;
-
-  /* 2 */ fsquare(z2,z);
-  /* 4 */ fsquare(t1,z2);
-  /* 8 */ fsquare(t0,t1);
-  /* 9 */ fmul(z9,t0,z);
-  /* 11 */ fmul(z11,z9,z2);
-  /* 22 */ fsquare(t0,z11);
-  /* 2^5 - 2^0 = 31 */ fmul(z2_5_0,t0,z9);
-
-  /* 2^6 - 2^1 */ fsquare(t0,z2_5_0);
-  /* 2^7 - 2^2 */ fsquare(t1,t0);
-  /* 2^8 - 2^3 */ fsquare(t0,t1);
-  /* 2^9 - 2^4 */ fsquare(t1,t0);
-  /* 2^10 - 2^5 */ fsquare(t0,t1);
-  /* 2^10 - 2^0 */ fmul(z2_10_0,t0,z2_5_0);
-
-  /* 2^11 - 2^1 */ fsquare(t0,z2_10_0);
-  /* 2^12 - 2^2 */ fsquare(t1,t0);
-  /* 2^20 - 2^10 */
-  for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
-  /* 2^20 - 2^0 */ fmul(z2_20_0,t1,z2_10_0);
-
-  /* 2^21 - 2^1 */ fsquare(t0,z2_20_0);
-  /* 2^22 - 2^2 */ fsquare(t1,t0);
-  /* 2^40 - 2^20 */
-  for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
-  /* 2^40 - 2^0 */ fmul(t0,t1,z2_20_0);
-
-  /* 2^41 - 2^1 */ fsquare(t1,t0);
-  /* 2^42 - 2^2 */ fsquare(t0,t1);
-  /* 2^50 - 2^10 */
-  for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); }
-  /* 2^50 - 2^0 */ fmul(z2_50_0,t0,z2_10_0);
-
-  /* 2^51 - 2^1 */ fsquare(t0,z2_50_0);
-  /* 2^52 - 2^2 */ fsquare(t1,t0);
-  /* 2^100 - 2^50 */
-  for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
-  /* 2^100 - 2^0 */ fmul(z2_100_0,t1,z2_50_0);
-
-  /* 2^101 - 2^1 */ fsquare(t1,z2_100_0);
-  /* 2^102 - 2^2 */ fsquare(t0,t1);
-  /* 2^200 - 2^100 */
-  for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); }
-  /* 2^200 - 2^0 */ fmul(t1,t0,z2_100_0);
-
-  /* 2^201 - 2^1 */ fsquare(t0,t1);
-  /* 2^202 - 2^2 */ fsquare(t1,t0);
-  /* 2^250 - 2^50 */
-  for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
-  /* 2^250 - 2^0 */ fmul(t0,t1,z2_50_0);
-
-  /* 2^251 - 2^1 */ fsquare(t1,t0);
-  /* 2^252 - 2^2 */ fsquare(t0,t1);
-  /* 2^253 - 2^3 */ fsquare(t1,t0);
-  /* 2^254 - 2^4 */ fsquare(t0,t1);
-  /* 2^255 - 2^5 */ fsquare(t1,t0);
-  /* 2^255 - 21 */ fmul(out,t1,z11);
-}
-
-int
-curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) {
-  limb bp[10], x[10], z[10], zmone[10];
-  uint8_t e[32];
-  int i;
-
-  for (i = 0; i < 32; ++i) e[i] = secret[i];
-  e[0] &= 248;
-  e[31] &= 127;
-  e[31] |= 64;
-
-  fexpand(bp, basepoint);
-  cmult(x, z, e, bp);
-  crecip(zmone, z);
-  fmul(z, x, zmone);
-  fcontract(mypublic, z);
-  return 0;
-}
diff --git a/crypto/curve25519_nss.cc b/crypto/curve25519_nss.cc
deleted file mode 100644
index 88bf94c..0000000
--- a/crypto/curve25519_nss.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "crypto/curve25519.h"
-
-#include <stdint.h>
-
-#include "crypto/secure_util.h"
-
-// Curve25519 is specified in terms of byte strings, not numbers, so all
-// implementations take and return the same sequence of bits. So the byte
-// order is implicitly specified as in, say, SHA1.
-//
-// Prototype for |curve25519_donna| function in
-// third_party/curve25519-donna/curve25519-donna.c
-extern "C" int curve25519_donna(uint8_t*, const uint8_t*, const uint8_t*);
-
-namespace crypto {
-
-namespace curve25519 {
-
-bool ScalarMult(const uint8_t* private_key,
-                const uint8_t* peer_public_key,
-                uint8_t* shared_key) {
-  curve25519_donna(shared_key, private_key, peer_public_key);
-
-  // The all-zero output results when the input is a point of small order.
-  static const uint8_t kZeros[32] = {0};
-  return !SecureMemEqual(shared_key, kZeros, 32);
-}
-
-// kBasePoint is the base point (generator) of the elliptic curve group.
-// It is little-endian version of '9' followed by 31 zeros.
-// See "Computing public keys" section of http://cr.yp.to/ecdh.html.
-static const uint8_t kBasePoint[32] = {9};
-
-void ScalarBaseMult(const uint8_t* private_key, uint8_t* public_key) {
-  curve25519_donna(public_key, private_key, kBasePoint);
-}
-
-}  // namespace curve25519
-
-}  // namespace crypto
diff --git a/crypto/ec_private_key.h b/crypto/ec_private_key.h
index 1ee4aca..6ebe21d 100644
--- a/crypto/ec_private_key.h
+++ b/crypto/ec_private_key.h
@@ -15,16 +15,8 @@
 #include "build/build_config.h"
 #include "crypto/crypto_export.h"
 
-#if defined(USE_OPENSSL)
 // Forward declaration for openssl/*.h
 typedef struct evp_pkey_st EVP_PKEY;
-#else
-// Forward declaration.
-typedef struct CERTSubjectPublicKeyInfoStr CERTSubjectPublicKeyInfo;
-typedef struct PK11SlotInfoStr PK11SlotInfo;
-typedef struct SECKEYPrivateKeyStr SECKEYPrivateKey;
-typedef struct SECKEYPublicKeyStr SECKEYPublicKey;
-#endif
 
 namespace crypto {
 
@@ -51,32 +43,10 @@
       const std::vector<uint8_t>& encrypted_private_key_info,
       const std::vector<uint8_t>& subject_public_key_info);
 
-#if !defined(USE_OPENSSL)
-  // Imports the key pair into |slot| and returns in |public_key| and |key|.
-  // Shortcut for code that needs to keep a reference directly to NSS types
-  // without having to create a ECPrivateKey object and make a copy of them.
-  // TODO(mattm): move this function to some NSS util file.
-  static bool ImportFromEncryptedPrivateKeyInfo(
-      PK11SlotInfo* slot,
-      const std::string& password,
-      const uint8_t* encrypted_private_key_info,
-      size_t encrypted_private_key_info_len,
-      CERTSubjectPublicKeyInfo* decoded_spki,
-      bool permanent,
-      bool sensitive,
-      SECKEYPrivateKey** key,
-      SECKEYPublicKey** public_key);
-#endif
-
   // Returns a copy of the object.
   ECPrivateKey* Copy() const;
 
-#if defined(USE_OPENSSL)
   EVP_PKEY* key() { return key_; }
-#else
-  SECKEYPrivateKey* key() { return key_; }
-  SECKEYPublicKey* public_key() { return public_key_; }
-#endif
 
   // Exports the private key as an ASN.1-encoded PKCS #8 EncryptedPrivateKeyInfo
   // block and the public key as an X.509 SubjectPublicKeyInfo block.
@@ -101,12 +71,7 @@
   // Constructor is private. Use one of the Create*() methods above instead.
   ECPrivateKey();
 
-#if defined(USE_OPENSSL)
   EVP_PKEY* key_;
-#else
-  SECKEYPrivateKey* key_;
-  SECKEYPublicKey* public_key_;
-#endif
 
   DISALLOW_COPY_AND_ASSIGN(ECPrivateKey);
 };
diff --git a/crypto/ec_private_key_nss.cc b/crypto/ec_private_key_nss.cc
deleted file mode 100644
index 8ca8f25ec..0000000
--- a/crypto/ec_private_key_nss.cc
+++ /dev/null
@@ -1,326 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "crypto/ec_private_key.h"
-
-extern "C" {
-// Work around NSS missing SEC_BEGIN_PROTOS in secmodt.h.  This must come before
-// other NSS headers.
-#include <secmodt.h>
-}
-
-#include <cryptohi.h>
-#include <keyhi.h>
-#include <pk11pub.h>
-#include <secmod.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/logging.h"
-#include "crypto/nss_util.h"
-#include "crypto/nss_util_internal.h"
-#include "crypto/scoped_nss_types.h"
-#include "crypto/third_party/nss/chromium-nss.h"
-
-namespace {
-
-static bool AppendAttribute(SECKEYPrivateKey* key,
-                            CK_ATTRIBUTE_TYPE type,
-                            std::vector<uint8_t>* output) {
-  SECItem item;
-  SECStatus rv;
-  rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item);
-  if (rv != SECSuccess) {
-    DLOG(ERROR) << "PK11_ReadRawAttribute: " << PORT_GetError();
-    return false;
-  }
-
-  output->insert(output->end(), item.data, item.data + item.len);
-  SECITEM_FreeItem(&item, PR_FALSE);
-  return true;
-}
-
-}  // namespace
-
-namespace crypto {
-
-ECPrivateKey::~ECPrivateKey() {
-  if (key_)
-    SECKEY_DestroyPrivateKey(key_);
-  if (public_key_)
-    SECKEY_DestroyPublicKey(public_key_);
-}
-
-// static
-ECPrivateKey* ECPrivateKey::Create() {
-  EnsureNSSInit();
-
-  ScopedPK11Slot slot(PK11_GetInternalSlot());
-  if (!slot)
-    return nullptr;
-
-  std::unique_ptr<ECPrivateKey> result(new ECPrivateKey);
-
-  SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1);
-  if (!oid_data) {
-    DLOG(ERROR) << "SECOID_FindOIDByTag: " << PORT_GetError();
-    return nullptr;
-  }
-
-  // SECKEYECParams is a SECItem containing the DER encoded ASN.1 ECParameters
-  // value.  For a named curve, that is just the OBJECT IDENTIFIER of the curve.
-  // In addition to the oid data, the encoding requires one byte for the ASN.1
-  // tag and one byte for the length (assuming the length is <= 127).
-  CHECK_LE(oid_data->oid.len, 127U);
-  std::vector<unsigned char> parameters_buf(2 + oid_data->oid.len);
-  SECKEYECParams ec_parameters = {
-    siDEROID, &parameters_buf[0],
-    static_cast<unsigned>(parameters_buf.size())
-  };
-
-  ec_parameters.data[0] = SEC_ASN1_OBJECT_ID;
-  ec_parameters.data[1] = static_cast<unsigned char>(oid_data->oid.len);
-  memcpy(ec_parameters.data + 2, oid_data->oid.data, oid_data->oid.len);
-
-  result->key_ = PK11_GenerateKeyPair(slot.get(),
-                                      CKM_EC_KEY_PAIR_GEN,
-                                      &ec_parameters,
-                                      &result->public_key_,
-                                      PR_FALSE /* not permanent */,
-                                      PR_FALSE /* not sensitive */,
-                                      NULL);
-  if (!result->key_) {
-    DLOG(ERROR) << "PK11_GenerateKeyPair: " << PORT_GetError();
-    return nullptr;
-  }
-  CHECK_EQ(ecKey, SECKEY_GetPublicKeyType(result->public_key_));
-
-  return result.release();
-}
-
-// static
-ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
-    const std::string& password,
-    const std::vector<uint8_t>& encrypted_private_key_info,
-    const std::vector<uint8_t>& subject_public_key_info) {
-  EnsureNSSInit();
-
-  ScopedPK11Slot slot(PK11_GetInternalSlot());
-  if (!slot)
-    return nullptr;
-
-  std::unique_ptr<ECPrivateKey> result(new ECPrivateKey);
-
-  SECItem encoded_spki = {
-    siBuffer,
-    const_cast<unsigned char*>(&subject_public_key_info[0]),
-    static_cast<unsigned>(subject_public_key_info.size())
-  };
-  CERTSubjectPublicKeyInfo* decoded_spki = SECKEY_DecodeDERSubjectPublicKeyInfo(
-      &encoded_spki);
-  if (!decoded_spki) {
-    DLOG(ERROR) << "SECKEY_DecodeDERSubjectPublicKeyInfo: " << PORT_GetError();
-    return nullptr;
-  }
-
-  bool success = ImportFromEncryptedPrivateKeyInfo(
-      slot.get(),
-      password,
-      &encrypted_private_key_info[0],
-      encrypted_private_key_info.size(),
-      decoded_spki,
-      false /* not permanent */,
-      false /* not sensitive */,
-      &result->key_,
-      &result->public_key_);
-
-  SECKEY_DestroySubjectPublicKeyInfo(decoded_spki);
-
-  if (success) {
-    CHECK_EQ(ecKey, SECKEY_GetPublicKeyType(result->public_key_));
-    return result.release();
-  }
-
-  return nullptr;
-}
-
-// static
-bool ECPrivateKey::ImportFromEncryptedPrivateKeyInfo(
-    PK11SlotInfo* slot,
-    const std::string& password,
-    const uint8_t* encrypted_private_key_info,
-    size_t encrypted_private_key_info_len,
-    CERTSubjectPublicKeyInfo* decoded_spki,
-    bool permanent,
-    bool sensitive,
-    SECKEYPrivateKey** key,
-    SECKEYPublicKey** public_key) {
-  if (!slot)
-    return false;
-
-  *public_key = SECKEY_ExtractPublicKey(decoded_spki);
-
-  if (!*public_key) {
-    DLOG(ERROR) << "SECKEY_ExtractPublicKey: " << PORT_GetError();
-    return false;
-  }
-
-  if (SECKEY_GetPublicKeyType(*public_key) != ecKey) {
-    DLOG(ERROR) << "The public key is not an EC key";
-    SECKEY_DestroyPublicKey(*public_key);
-    *public_key = NULL;
-    return false;
-  }
-
-  SECItem encoded_epki = {
-    siBuffer,
-    const_cast<unsigned char*>(encrypted_private_key_info),
-    static_cast<unsigned>(encrypted_private_key_info_len)
-  };
-  SECKEYEncryptedPrivateKeyInfo epki;
-  memset(&epki, 0, sizeof(epki));
-
-  ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-
-  SECStatus rv = SEC_QuickDERDecodeItem(
-      arena.get(),
-      &epki,
-      SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate),
-      &encoded_epki);
-  if (rv != SECSuccess) {
-    DLOG(ERROR) << "SEC_QuickDERDecodeItem: " << PORT_GetError();
-    SECKEY_DestroyPublicKey(*public_key);
-    *public_key = NULL;
-    return false;
-  }
-
-  SECItem password_item = {
-    siBuffer,
-    reinterpret_cast<unsigned char*>(const_cast<char*>(password.data())),
-    static_cast<unsigned>(password.size())
-  };
-
-  rv = ImportEncryptedECPrivateKeyInfoAndReturnKey(
-      slot,
-      &epki,
-      &password_item,
-      NULL,  // nickname
-      &(*public_key)->u.ec.publicValue,
-      permanent,
-      sensitive,
-      key,
-      NULL);  // wincx
-  if (rv != SECSuccess) {
-    DLOG(ERROR) << "ImportEncryptedECPrivateKeyInfoAndReturnKey: "
-                << PORT_GetError();
-    SECKEY_DestroyPublicKey(*public_key);
-    *public_key = NULL;
-    return false;
-  }
-
-  return true;
-}
-
-ECPrivateKey* ECPrivateKey::Copy() const {
-  std::unique_ptr<ECPrivateKey> copy(new ECPrivateKey);
-  if (key_) {
-    copy->key_ = SECKEY_CopyPrivateKey(key_);
-    if (!copy->key_)
-      return NULL;
-  }
-  if (public_key_) {
-    copy->public_key_ = SECKEY_CopyPublicKey(public_key_);
-    if (!copy->public_key_)
-      return NULL;
-  }
-  return copy.release();
-}
-
-bool ECPrivateKey::ExportEncryptedPrivateKey(const std::string& password,
-                                             int iterations,
-                                             std::vector<uint8_t>* output) {
-  // We export as an EncryptedPrivateKeyInfo bundle instead of a plain PKCS #8
-  // PrivateKeyInfo because PK11_ImportDERPrivateKeyInfoAndReturnKey doesn't
-  // support EC keys.
-  // https://bugzilla.mozilla.org/show_bug.cgi?id=327773
-  SECItem password_item = {
-    siBuffer,
-    reinterpret_cast<unsigned char*>(const_cast<char*>(password.data())),
-    static_cast<unsigned>(password.size())
-  };
-
-  SECKEYEncryptedPrivateKeyInfo* encrypted = PK11_ExportEncryptedPrivKeyInfo(
-      NULL,  // Slot, optional.
-      SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC,
-      &password_item,
-      key_,
-      iterations,
-      NULL);  // wincx.
-
-  if (!encrypted) {
-    DLOG(ERROR) << "PK11_ExportEncryptedPrivKeyInfo: " << PORT_GetError();
-    return false;
-  }
-
-  ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-  SECItem der_key = {siBuffer, NULL, 0};
-  SECItem* encoded_item = SEC_ASN1EncodeItem(
-      arena.get(),
-      &der_key,
-      encrypted,
-      SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate));
-  SECKEY_DestroyEncryptedPrivateKeyInfo(encrypted, PR_TRUE);
-  if (!encoded_item) {
-    DLOG(ERROR) << "SEC_ASN1EncodeItem: " << PORT_GetError();
-    return false;
-  }
-
-  output->assign(der_key.data, der_key.data + der_key.len);
-
-  return true;
-}
-
-bool ECPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) {
-  ScopedSECItem der_pubkey(
-      SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_));
-  if (!der_pubkey.get()) {
-    return false;
-  }
-
-  output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len);
-  return true;
-}
-
-bool ECPrivateKey::ExportRawPublicKey(std::string* output) {
-  // public_key_->u.ec.publicValue is an ANSI X9.62 public key which, for
-  // a P-256 key, is 0x04 (meaning uncompressed) followed by the x and y field
-  // elements as 32-byte, big-endian numbers.
-  static const unsigned int kExpectedKeyLength = 65;
-
-  CHECK_EQ(ecKey, SECKEY_GetPublicKeyType(public_key_));
-  const unsigned char* const data = public_key_->u.ec.publicValue.data;
-  const unsigned int len = public_key_->u.ec.publicValue.len;
-  if (len != kExpectedKeyLength || data[0] != 0x04)
-    return false;
-
-  output->assign(reinterpret_cast<const char*>(data + 1),
-                 kExpectedKeyLength - 1);
-  return true;
-}
-
-bool ECPrivateKey::ExportValueForTesting(std::vector<uint8_t>* output) {
-  // This serialization format is purely for testing equality, so just
-  // concatenate the raw private key (always 32 bytes for P-256) with the
-  // parameters.
-  output->clear();
-  return AppendAttribute(key_, CKA_VALUE, output) &&
-         output->size() == 32 &&
-         AppendAttribute(key_, CKA_EC_PARAMS, output);
-}
-
-ECPrivateKey::ECPrivateKey() : key_(NULL), public_key_(NULL) {}
-
-}  // namespace crypto
diff --git a/crypto/ec_private_key_unittest.cc b/crypto/ec_private_key_unittest.cc
index 0fa8c8c..00bd77c 100644
--- a/crypto/ec_private_key_unittest.cc
+++ b/crypto/ec_private_key_unittest.cc
@@ -223,7 +223,6 @@
 // The Android code writes out Channel IDs differently from the NSS
 // implementation; the empty password is converted to "\0\0". The OpenSSL port
 // should support either.
-#if defined(USE_OPENSSL)
 TEST(ECPrivateKeyUnitTest, LoadOldOpenSSLKeyTest) {
   static const uint8_t kOpenSSLKey[] = {
       0x30, 0x82, 0x01, 0xa1, 0x30, 0x1b, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86,
@@ -303,4 +302,3 @@
 
   EXPECT_TRUE(keypair_openssl.get());
 }
-#endif  // defined(USE_OPENSSL)
diff --git a/crypto/ec_signature_creator_nss.cc b/crypto/ec_signature_creator_nss.cc
deleted file mode 100644
index 7c8cc7d..0000000
--- a/crypto/ec_signature_creator_nss.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "crypto/ec_signature_creator_impl.h"
-
-#include <cryptohi.h>
-#include <pk11pub.h>
-#include <secerr.h>
-#include <sechash.h>
-#if defined(OS_POSIX)
-#include <stddef.h>
-#include <stdint.h>
-#include <unistd.h>
-#endif
-
-#include "base/logging.h"
-#include "crypto/ec_private_key.h"
-#include "crypto/nss_util.h"
-#include "crypto/scoped_nss_types.h"
-
-namespace crypto {
-
-namespace {
-
-SECStatus SignData(SECItem* result,
-                   SECItem* input,
-                   SECKEYPrivateKey* key,
-                   HASH_HashType hash_type) {
-  if (key->keyType != ecKey) {
-    DLOG(FATAL) << "Should be using an EC key.";
-    PORT_SetError(SEC_ERROR_INVALID_ARGS);
-    return SECFailure;
-  }
-
-  // Hash the input.
-  std::vector<uint8_t> hash_data(HASH_ResultLen(hash_type));
-  SECStatus rv = HASH_HashBuf(
-      hash_type, &hash_data[0], input->data, input->len);
-  if (rv != SECSuccess)
-    return rv;
-  SECItem hash = {siBuffer, &hash_data[0],
-                  static_cast<unsigned int>(hash_data.size())};
-
-  // Compute signature of hash.
-  int signature_len = PK11_SignatureLen(key);
-  std::vector<uint8_t> signature_data(signature_len);
-  SECItem sig = {siBuffer, &signature_data[0],
-                 static_cast<unsigned int>(signature_len)};
-  rv = PK11_Sign(key, &sig, &hash);
-  if (rv != SECSuccess)
-    return rv;
-
-  // DER encode the signature.
-  return DSAU_EncodeDerSigWithLen(result, &sig, sig.len);
-}
-
-}  // namespace
-
-ECSignatureCreatorImpl::ECSignatureCreatorImpl(ECPrivateKey* key)
-    : key_(key) {
-  EnsureNSSInit();
-}
-
-ECSignatureCreatorImpl::~ECSignatureCreatorImpl() {}
-
-bool ECSignatureCreatorImpl::Sign(const uint8_t* data,
-                                  int data_len,
-                                  std::vector<uint8_t>* signature) {
-  // Data to be signed
-  SECItem secret;
-  secret.type = siBuffer;
-  secret.len = data_len;
-  secret.data = const_cast<unsigned char*>(data);
-
-  // SECItem to receive the output buffer.
-  SECItem result;
-  result.type = siBuffer;
-  result.len = 0;
-  result.data = NULL;
-
-  // Sign the secret data and save it to |result|.
-  SECStatus rv =
-      SignData(&result, &secret, key_->key(), HASH_AlgSHA256);
-  if (rv != SECSuccess) {
-    DLOG(ERROR) << "DerSignData: " << PORT_GetError();
-    return false;
-  }
-
-  // Copy the signed data into the output vector.
-  signature->assign(result.data, result.data + result.len);
-  SECITEM_FreeItem(&result, PR_FALSE /* only free |result.data| */);
-  return true;
-}
-
-bool ECSignatureCreatorImpl::DecodeSignature(
-    const std::vector<uint8_t>& der_sig,
-    std::vector<uint8_t>* out_raw_sig) {
-  SECItem der_sig_item;
-  der_sig_item.type = siBuffer;
-  der_sig_item.len = der_sig.size();
-  der_sig_item.data = const_cast<uint8_t*>(&der_sig[0]);
-
-  size_t signature_len = SECKEY_SignatureLen(key_->public_key());
-  if (signature_len == 0)
-    return false;
-
-  SECItem* raw_sig = DSAU_DecodeDerSigToLen(&der_sig_item, signature_len);
-  if (!raw_sig)
-    return false;
-  out_raw_sig->assign(raw_sig->data, raw_sig->data + raw_sig->len);
-  SECITEM_FreeItem(raw_sig, PR_TRUE /* free SECItem structure itself. */);
-  return true;
-}
-
-}  // namespace crypto
diff --git a/crypto/encryptor.h b/crypto/encryptor.h
index f1a478a..f5a1031 100644
--- a/crypto/encryptor.h
+++ b/crypto/encryptor.h
@@ -15,10 +15,6 @@
 #include "build/build_config.h"
 #include "crypto/crypto_export.h"
 
-#if !defined(USE_OPENSSL)
-#include "crypto/scoped_nss_types.h"
-#endif
-
 namespace crypto {
 
 class SymmetricKey;
@@ -115,7 +111,6 @@
   Mode mode_;
   std::unique_ptr<Counter> counter_;
 
-#if defined(USE_OPENSSL)
   bool Crypt(bool do_encrypt,  // Pass true to encrypt, false to decrypt.
              const base::StringPiece& input,
              std::string* output);
@@ -123,15 +118,6 @@
                 const base::StringPiece& input,
                 std::string* output);
   std::string iv_;
-#else
-  bool Crypt(PK11Context* context,
-             const base::StringPiece& input,
-             std::string* output);
-  bool CryptCTR(PK11Context* context,
-                const base::StringPiece& input,
-                std::string* output);
-  ScopedSECItem param_;
-#endif
 };
 
 }  // namespace crypto
diff --git a/crypto/encryptor_nss.cc b/crypto/encryptor_nss.cc
deleted file mode 100644
index eca1377..0000000
--- a/crypto/encryptor_nss.cc
+++ /dev/null
@@ -1,203 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "crypto/encryptor.h"
-
-#include <cryptohi.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <vector>
-
-#include "base/logging.h"
-#include "crypto/nss_util.h"
-#include "crypto/symmetric_key.h"
-
-namespace crypto {
-
-namespace {
-
-inline CK_MECHANISM_TYPE GetMechanism(Encryptor::Mode mode) {
-  switch (mode) {
-    case Encryptor::CBC:
-      return CKM_AES_CBC_PAD;
-    case Encryptor::CTR:
-      // AES-CTR encryption uses ECB encryptor as a building block since
-      // NSS doesn't support CTR encryption mode.
-      return CKM_AES_ECB;
-    default:
-      NOTREACHED() << "Unsupported mode of operation";
-      break;
-  }
-  return static_cast<CK_MECHANISM_TYPE>(-1);
-}
-
-}  // namespace
-
-Encryptor::Encryptor()
-    : key_(NULL),
-      mode_(CBC) {
-  EnsureNSSInit();
-}
-
-Encryptor::~Encryptor() {
-}
-
-bool Encryptor::Init(SymmetricKey* key,
-                     Mode mode,
-                     const base::StringPiece& iv) {
-  DCHECK(key);
-  DCHECK(CBC == mode || CTR == mode) << "Unsupported mode of operation";
-
-  key_ = key;
-  mode_ = mode;
-
-  if (mode == CBC && iv.size() != AES_BLOCK_SIZE)
-    return false;
-
-  switch (mode) {
-    case CBC:
-      SECItem iv_item;
-      iv_item.type = siBuffer;
-      iv_item.data = reinterpret_cast<unsigned char*>(
-          const_cast<char *>(iv.data()));
-      iv_item.len = iv.size();
-
-      param_.reset(PK11_ParamFromIV(GetMechanism(mode), &iv_item));
-      break;
-    case CTR:
-      param_.reset(PK11_ParamFromIV(GetMechanism(mode), NULL));
-      break;
-  }
-
-  return param_ != NULL;
-}
-
-bool Encryptor::Encrypt(const base::StringPiece& plaintext,
-                        std::string* ciphertext) {
-  CHECK(!plaintext.empty() || (mode_ == CBC));
-  ScopedPK11Context context(PK11_CreateContextBySymKey(GetMechanism(mode_),
-                                                       CKA_ENCRYPT,
-                                                       key_->key(),
-                                                       param_.get()));
-  if (!context.get())
-    return false;
-
-  return (mode_ == CTR) ?
-      CryptCTR(context.get(), plaintext, ciphertext) :
-      Crypt(context.get(), plaintext, ciphertext);
-}
-
-bool Encryptor::Decrypt(const base::StringPiece& ciphertext,
-                        std::string* plaintext) {
-  CHECK(!ciphertext.empty());
-  ScopedPK11Context context(PK11_CreateContextBySymKey(
-      GetMechanism(mode_), (mode_ == CTR ? CKA_ENCRYPT : CKA_DECRYPT),
-      key_->key(), param_.get()));
-  if (!context.get())
-    return false;
-
-  if (mode_ == CTR)
-    return CryptCTR(context.get(), ciphertext, plaintext);
-
-  if (ciphertext.size() % AES_BLOCK_SIZE != 0) {
-    // Decryption will fail if the input is not a multiple of the block size.
-    // PK11_CipherOp has a bug where it will do an invalid memory access before
-    // the start of the input, so avoid calling it. (NSS bug 922780).
-    plaintext->clear();
-    return false;
-  }
-
-  return Crypt(context.get(), ciphertext, plaintext);
-}
-
-bool Encryptor::Crypt(PK11Context* context,
-                      const base::StringPiece& input,
-                      std::string* output) {
-  size_t output_len = input.size() + AES_BLOCK_SIZE;
-  CHECK_GT(output_len, input.size());
-
-  output->resize(output_len);
-  uint8_t* output_data =
-      reinterpret_cast<uint8_t*>(const_cast<char*>(output->data()));
-
-  int input_len = input.size();
-  uint8_t* input_data =
-      reinterpret_cast<uint8_t*>(const_cast<char*>(input.data()));
-
-  int op_len;
-  SECStatus rv = PK11_CipherOp(context,
-                               output_data,
-                               &op_len,
-                               output_len,
-                               input_data,
-                               input_len);
-
-  if (SECSuccess != rv) {
-    output->clear();
-    return false;
-  }
-
-  unsigned int digest_len;
-  rv = PK11_DigestFinal(context,
-                        output_data + op_len,
-                        &digest_len,
-                        output_len - op_len);
-  if (SECSuccess != rv) {
-    output->clear();
-    return false;
-  }
-
-  output->resize(op_len + digest_len);
-  return true;
-}
-
-bool Encryptor::CryptCTR(PK11Context* context,
-                         const base::StringPiece& input,
-                         std::string* output) {
-  if (!counter_.get()) {
-    LOG(ERROR) << "Counter value not set in CTR mode.";
-    return false;
-  }
-
-  size_t output_len = ((input.size() + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE) *
-      AES_BLOCK_SIZE;
-  CHECK_GE(output_len, input.size());
-  output->resize(output_len);
-  uint8_t* output_data =
-      reinterpret_cast<uint8_t*>(const_cast<char*>(output->data()));
-
-  size_t mask_len;
-  bool ret = GenerateCounterMask(input.size(), output_data, &mask_len);
-  if (!ret)
-    return false;
-
-  CHECK_EQ(mask_len, output_len);
-  int op_len;
-  SECStatus rv = PK11_CipherOp(context,
-                               output_data,
-                               &op_len,
-                               output_len,
-                               output_data,
-                               mask_len);
-  if (SECSuccess != rv)
-    return false;
-  CHECK_EQ(static_cast<int>(mask_len), op_len);
-
-  unsigned int digest_len;
-  rv = PK11_DigestFinal(context,
-                        NULL,
-                        &digest_len,
-                        0);
-  if (SECSuccess != rv)
-    return false;
-  CHECK(!digest_len);
-
-  // Use |output_data| to mask |input|.
-  MaskMessage(reinterpret_cast<uint8_t*>(const_cast<char*>(input.data())),
-              input.length(), output_data, output_data);
-  output->resize(input.length());
-  return true;
-}
-
-}  // namespace crypto
diff --git a/crypto/hmac_nss.cc b/crypto/hmac_nss.cc
deleted file mode 100644
index 2547860..0000000
--- a/crypto/hmac_nss.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "crypto/hmac.h"
-
-#include <nss.h>
-#include <pk11pub.h>
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/logging.h"
-#include "crypto/nss_util.h"
-#include "crypto/scoped_nss_types.h"
-
-namespace crypto {
-
-struct HMACPlatformData {
-  CK_MECHANISM_TYPE mechanism_;
-  ScopedPK11Slot slot_;
-  ScopedPK11SymKey sym_key_;
-};
-
-HMAC::HMAC(HashAlgorithm hash_alg)
-    : hash_alg_(hash_alg), plat_(new HMACPlatformData()) {
-  // Only SHA-1 and SHA-256 hash algorithms are supported.
-  switch (hash_alg_) {
-    case SHA1:
-      plat_->mechanism_ = CKM_SHA_1_HMAC;
-      break;
-    case SHA256:
-      plat_->mechanism_ = CKM_SHA256_HMAC;
-      break;
-    default:
-      NOTREACHED() << "Unsupported hash algorithm";
-      break;
-  }
-}
-
-HMAC::~HMAC() {
-}
-
-bool HMAC::Init(const unsigned char *key, size_t key_length) {
-  EnsureNSSInit();
-
-  if (plat_->slot_.get()) {
-    // Init must not be called more than twice on the same HMAC object.
-    NOTREACHED();
-    return false;
-  }
-
-  plat_->slot_.reset(PK11_GetInternalSlot());
-  if (!plat_->slot_.get()) {
-    NOTREACHED();
-    return false;
-  }
-
-  SECItem key_item;
-  key_item.type = siBuffer;
-  key_item.data = const_cast<unsigned char*>(key);  // NSS API isn't const.
-  key_item.len = key_length;
-
-  plat_->sym_key_.reset(PK11_ImportSymKey(plat_->slot_.get(),
-                                          plat_->mechanism_,
-                                          PK11_OriginUnwrap,
-                                          CKA_SIGN,
-                                          &key_item,
-                                          NULL));
-  if (!plat_->sym_key_.get()) {
-    NOTREACHED();
-    return false;
-  }
-
-  return true;
-}
-
-bool HMAC::Sign(const base::StringPiece& data,
-                unsigned char* digest,
-                size_t digest_length) const {
-  if (!plat_->sym_key_.get()) {
-    // Init has not been called before Sign.
-    NOTREACHED();
-    return false;
-  }
-
-  SECItem param = { siBuffer, NULL, 0 };
-  ScopedPK11Context context(PK11_CreateContextBySymKey(plat_->mechanism_,
-                                                       CKA_SIGN,
-                                                       plat_->sym_key_.get(),
-                                                       &param));
-  if (!context.get()) {
-    NOTREACHED();
-    return false;
-  }
-
-  if (PK11_DigestBegin(context.get()) != SECSuccess) {
-    NOTREACHED();
-    return false;
-  }
-
-  if (PK11_DigestOp(context.get(),
-                    reinterpret_cast<const unsigned char*>(data.data()),
-                    data.length()) != SECSuccess) {
-    NOTREACHED();
-    return false;
-  }
-
-  unsigned int len = 0;
-  if (PK11_DigestFinal(context.get(),
-                       digest, &len, digest_length) != SECSuccess) {
-    NOTREACHED();
-    return false;
-  }
-
-  return true;
-}
-
-}  // namespace crypto
diff --git a/crypto/rsa_private_key.h b/crypto/rsa_private_key.h
index 5a6dc8cf0..0304a8c 100644
--- a/crypto/rsa_private_key.h
+++ b/crypto/rsa_private_key.h
@@ -15,15 +15,8 @@
 #include "build/build_config.h"
 #include "crypto/crypto_export.h"
 
-#if defined(USE_OPENSSL)
 // Forward declaration for openssl/*.h
 typedef struct evp_pkey_st EVP_PKEY;
-#else
-// Forward declaration.
-typedef struct PK11SlotInfoStr PK11SlotInfo;
-typedef struct SECKEYPrivateKeyStr SECKEYPrivateKey;
-typedef struct SECKEYPublicKeyStr SECKEYPublicKey;
-#endif
 
 namespace crypto {
 
@@ -43,23 +36,12 @@
   static RSAPrivateKey* CreateFromPrivateKeyInfo(
       const std::vector<uint8_t>& input);
 
-#if defined(USE_OPENSSL)
   // Create a new instance from an existing EVP_PKEY, taking a
   // reference to it. |key| must be an RSA key. Returns NULL on
   // failure.
   static RSAPrivateKey* CreateFromKey(EVP_PKEY* key);
-#else
-  // Create a new instance by referencing an existing private key
-  // structure.  Does not import the key.
-  static RSAPrivateKey* CreateFromKey(SECKEYPrivateKey* key);
-#endif
 
-#if defined(USE_OPENSSL)
   EVP_PKEY* key() { return key_; }
-#else
-  SECKEYPrivateKey* key() { return key_; }
-  SECKEYPublicKey* public_key() { return public_key_; }
-#endif
 
   // Creates a copy of the object.
   RSAPrivateKey* Copy() const;
@@ -74,12 +56,7 @@
   // Constructor is private. Use one of the Create*() methods above instead.
   RSAPrivateKey();
 
-#if defined(USE_OPENSSL)
   EVP_PKEY* key_;
-#else
-  SECKEYPrivateKey* key_;
-  SECKEYPublicKey* public_key_;
-#endif
 
   DISALLOW_COPY_AND_ASSIGN(RSAPrivateKey);
 };
diff --git a/crypto/rsa_private_key_nss.cc b/crypto/rsa_private_key_nss.cc
deleted file mode 100644
index 2538a723..0000000
--- a/crypto/rsa_private_key_nss.cc
+++ /dev/null
@@ -1,633 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "crypto/rsa_private_key.h"
-
-#include <cryptohi.h>
-#include <keyhi.h>
-#include <pk11pub.h>
-#include <stdint.h>
-
-#include <list>
-#include <memory>
-
-#include "base/debug/leak_annotations.h"
-#include "base/logging.h"
-#include "base/strings/string_util.h"
-#include "crypto/nss_key_util.h"
-#include "crypto/nss_util.h"
-#include "crypto/scoped_nss_types.h"
-
-// Helper for error handling during key import.
-#define READ_ASSERT(truth) \
-  if (!(truth)) { \
-    NOTREACHED(); \
-    return false; \
-  }
-
-// TODO(rafaelw): Consider using NSS's ASN.1 encoder.
-namespace {
-
-static bool ReadAttribute(SECKEYPrivateKey* key,
-                          CK_ATTRIBUTE_TYPE type,
-                          std::vector<uint8_t>* output) {
-  SECItem item;
-  SECStatus rv;
-  rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item);
-  if (rv != SECSuccess) {
-    NOTREACHED();
-    return false;
-  }
-
-  output->assign(item.data, item.data + item.len);
-  SECITEM_FreeItem(&item, PR_FALSE);
-  return true;
-}
-
-// Used internally by RSAPrivateKey for serializing and deserializing
-// PKCS #8 PrivateKeyInfo and PublicKeyInfo.
-class PrivateKeyInfoCodec {
- public:
-  // ASN.1 encoding of the AlgorithmIdentifier from PKCS #8.
-  static const uint8_t kRsaAlgorithmIdentifier[];
-
-  // ASN.1 tags for some types we use.
-  static const uint8_t kBitStringTag = 0x03;
-  static const uint8_t kIntegerTag = 0x02;
-  static const uint8_t kOctetStringTag = 0x04;
-  static const uint8_t kSequenceTag = 0x30;
-
-  // |big_endian| here specifies the byte-significance of the integer components
-  // that will be parsed & serialized (modulus(), etc...) during Import(),
-  // Export() and ExportPublicKeyInfo() -- not the ASN.1 DER encoding of the
-  // PrivateKeyInfo/PublicKeyInfo (which is always big-endian).
-  explicit PrivateKeyInfoCodec(bool big_endian);
-
-  ~PrivateKeyInfoCodec();
-
-  // Exports the contents of the integer components to the ASN.1 DER encoding
-  // of the PrivateKeyInfo structure to |output|.
-  bool Export(std::vector<uint8_t>* output);
-
-  // Exports the contents of the integer components to the ASN.1 DER encoding
-  // of the PublicKeyInfo structure to |output|.
-  bool ExportPublicKeyInfo(std::vector<uint8_t>* output);
-
-  // Exports the contents of the integer components to the ASN.1 DER encoding
-  // of the RSAPublicKey structure to |output|.
-  bool ExportPublicKey(std::vector<uint8_t>* output);
-
-  // Parses the ASN.1 DER encoding of the PrivateKeyInfo structure in |input|
-  // and populates the integer components with |big_endian_| byte-significance.
-  // IMPORTANT NOTE: This is currently *not* security-approved for importing
-  // keys from unstrusted sources.
-  bool Import(const std::vector<uint8_t>& input);
-
-  // Accessors to the contents of the integer components of the PrivateKeyInfo
-  // structure.
-  std::vector<uint8_t>* modulus() { return &modulus_; }
-  std::vector<uint8_t>* public_exponent() { return &public_exponent_; }
-  std::vector<uint8_t>* private_exponent() { return &private_exponent_; }
-  std::vector<uint8_t>* prime1() { return &prime1_; }
-  std::vector<uint8_t>* prime2() { return &prime2_; }
-  std::vector<uint8_t>* exponent1() { return &exponent1_; }
-  std::vector<uint8_t>* exponent2() { return &exponent2_; }
-  std::vector<uint8_t>* coefficient() { return &coefficient_; }
-
- private:
-  // Utility wrappers for PrependIntegerImpl that use the class's |big_endian_|
-  // value.
-  void PrependInteger(const std::vector<uint8_t>& in, std::list<uint8_t>* out);
-  void PrependInteger(uint8_t* val, int num_bytes, std::list<uint8_t>* data);
-
-  // Prepends the integer stored in |val| - |val + num_bytes| with |big_endian|
-  // byte-significance into |data| as an ASN.1 integer.
-  void PrependIntegerImpl(uint8_t* val,
-                          int num_bytes,
-                          std::list<uint8_t>* data,
-                          bool big_endian);
-
-  // Utility wrappers for ReadIntegerImpl that use the class's |big_endian_|
-  // value.
-  bool ReadInteger(uint8_t** pos, uint8_t* end, std::vector<uint8_t>* out);
-  bool ReadIntegerWithExpectedSize(uint8_t** pos,
-                                   uint8_t* end,
-                                   size_t expected_size,
-                                   std::vector<uint8_t>* out);
-
-  // Reads an ASN.1 integer from |pos|, and stores the result into |out| with
-  // |big_endian| byte-significance.
-  bool ReadIntegerImpl(uint8_t** pos,
-                       uint8_t* end,
-                       std::vector<uint8_t>* out,
-                       bool big_endian);
-
-  // Prepends the integer stored in |val|, starting a index |start|, for
-  // |num_bytes| bytes onto |data|.
-  void PrependBytes(uint8_t* val,
-                    int start,
-                    int num_bytes,
-                    std::list<uint8_t>* data);
-
-  // Helper to prepend an ASN.1 length field.
-  void PrependLength(size_t size, std::list<uint8_t>* data);
-
-  // Helper to prepend an ASN.1 type header.
-  void PrependTypeHeaderAndLength(uint8_t type,
-                                  uint32_t length,
-                                  std::list<uint8_t>* output);
-
-  // Helper to prepend an ASN.1 bit string
-  void PrependBitString(uint8_t* val,
-                        int num_bytes,
-                        std::list<uint8_t>* output);
-
-  // Read an ASN.1 length field. This also checks that the length does not
-  // extend beyond |end|.
-  bool ReadLength(uint8_t** pos, uint8_t* end, uint32_t* result);
-
-  // Read an ASN.1 type header and its length.
-  bool ReadTypeHeaderAndLength(uint8_t** pos,
-                               uint8_t* end,
-                               uint8_t expected_tag,
-                               uint32_t* length);
-
-  // Read an ASN.1 sequence declaration. This consumes the type header and
-  // length field, but not the contents of the sequence.
-  bool ReadSequence(uint8_t** pos, uint8_t* end);
-
-  // Read the RSA AlgorithmIdentifier.
-  bool ReadAlgorithmIdentifier(uint8_t** pos, uint8_t* end);
-
-  // Read one of the two version fields in PrivateKeyInfo.
-  bool ReadVersion(uint8_t** pos, uint8_t* end);
-
-  // The byte-significance of the stored components (modulus, etc..).
-  bool big_endian_;
-
-  // Component integers of the PrivateKeyInfo
-  std::vector<uint8_t> modulus_;
-  std::vector<uint8_t> public_exponent_;
-  std::vector<uint8_t> private_exponent_;
-  std::vector<uint8_t> prime1_;
-  std::vector<uint8_t> prime2_;
-  std::vector<uint8_t> exponent1_;
-  std::vector<uint8_t> exponent2_;
-  std::vector<uint8_t> coefficient_;
-
-  DISALLOW_COPY_AND_ASSIGN(PrivateKeyInfoCodec);
-};
-
-const uint8_t PrivateKeyInfoCodec::kRsaAlgorithmIdentifier[] = {
-    0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
-    0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00};
-
-PrivateKeyInfoCodec::PrivateKeyInfoCodec(bool big_endian)
-    : big_endian_(big_endian) {}
-
-PrivateKeyInfoCodec::~PrivateKeyInfoCodec() {}
-
-bool PrivateKeyInfoCodec::Export(std::vector<uint8_t>* output) {
-  std::list<uint8_t> content;
-
-  // Version (always zero)
-  uint8_t version = 0;
-
-  PrependInteger(coefficient_, &content);
-  PrependInteger(exponent2_, &content);
-  PrependInteger(exponent1_, &content);
-  PrependInteger(prime2_, &content);
-  PrependInteger(prime1_, &content);
-  PrependInteger(private_exponent_, &content);
-  PrependInteger(public_exponent_, &content);
-  PrependInteger(modulus_, &content);
-  PrependInteger(&version, 1, &content);
-  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
-  PrependTypeHeaderAndLength(kOctetStringTag, content.size(), &content);
-
-  // RSA algorithm OID
-  for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
-    content.push_front(kRsaAlgorithmIdentifier[i - 1]);
-
-  PrependInteger(&version, 1, &content);
-  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
-
-  // Copy everying into the output.
-  output->reserve(content.size());
-  output->assign(content.begin(), content.end());
-
-  return true;
-}
-
-bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector<uint8_t>* output) {
-  // Create a sequence with the modulus (n) and public exponent (e).
-  std::vector<uint8_t> bit_string;
-  if (!ExportPublicKey(&bit_string))
-    return false;
-
-  // Add the sequence as the contents of a bit string.
-  std::list<uint8_t> content;
-  PrependBitString(&bit_string[0], static_cast<int>(bit_string.size()),
-                   &content);
-
-  // Add the RSA algorithm OID.
-  for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
-    content.push_front(kRsaAlgorithmIdentifier[i - 1]);
-
-  // Finally, wrap everything in a sequence.
-  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
-
-  // Copy everything into the output.
-  output->reserve(content.size());
-  output->assign(content.begin(), content.end());
-
-  return true;
-}
-
-bool PrivateKeyInfoCodec::ExportPublicKey(std::vector<uint8_t>* output) {
-  // Create a sequence with the modulus (n) and public exponent (e).
-  std::list<uint8_t> content;
-  PrependInteger(&public_exponent_[0],
-                 static_cast<int>(public_exponent_.size()),
-                 &content);
-  PrependInteger(&modulus_[0],  static_cast<int>(modulus_.size()), &content);
-  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
-
-  // Copy everything into the output.
-  output->reserve(content.size());
-  output->assign(content.begin(), content.end());
-
-  return true;
-}
-
-bool PrivateKeyInfoCodec::Import(const std::vector<uint8_t>& input) {
-  if (input.empty()) {
-    return false;
-  }
-
-  // Parse the private key info up to the public key values, ignoring
-  // the subsequent private key values.
-  uint8_t* src = const_cast<uint8_t*>(&input.front());
-  uint8_t* end = src + input.size();
-  if (!ReadSequence(&src, end) ||
-      !ReadVersion(&src, end) ||
-      !ReadAlgorithmIdentifier(&src, end) ||
-      !ReadTypeHeaderAndLength(&src, end, kOctetStringTag, NULL) ||
-      !ReadSequence(&src, end) ||
-      !ReadVersion(&src, end) ||
-      !ReadInteger(&src, end, &modulus_))
-    return false;
-
-  int mod_size = modulus_.size();
-  READ_ASSERT(mod_size % 2 == 0);
-  int primes_size = mod_size / 2;
-
-  if (!ReadIntegerWithExpectedSize(&src, end, 4, &public_exponent_) ||
-      !ReadIntegerWithExpectedSize(&src, end, mod_size, &private_exponent_) ||
-      !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime1_) ||
-      !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime2_) ||
-      !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent1_) ||
-      !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent2_) ||
-      !ReadIntegerWithExpectedSize(&src, end, primes_size, &coefficient_))
-    return false;
-
-  READ_ASSERT(src == end);
-
-
-  return true;
-}
-
-void PrivateKeyInfoCodec::PrependInteger(const std::vector<uint8_t>& in,
-                                         std::list<uint8_t>* out) {
-  uint8_t* ptr = const_cast<uint8_t*>(&in.front());
-  PrependIntegerImpl(ptr, in.size(), out, big_endian_);
-}
-
-// Helper to prepend an ASN.1 integer.
-void PrivateKeyInfoCodec::PrependInteger(uint8_t* val,
-                                         int num_bytes,
-                                         std::list<uint8_t>* data) {
-  PrependIntegerImpl(val, num_bytes, data, big_endian_);
-}
-
-void PrivateKeyInfoCodec::PrependIntegerImpl(uint8_t* val,
-                                             int num_bytes,
-                                             std::list<uint8_t>* data,
-                                             bool big_endian) {
- // Reverse input if little-endian.
- std::vector<uint8_t> tmp;
- if (!big_endian) {
-   tmp.assign(val, val + num_bytes);
-   std::reverse(tmp.begin(), tmp.end());
-   val = &tmp.front();
- }
-
-  // ASN.1 integers are unpadded byte arrays, so skip any null padding bytes
-  // from the most-significant end of the integer.
-  int start = 0;
-  while (start < (num_bytes - 1) && val[start] == 0x00) {
-    start++;
-    num_bytes--;
-  }
-  PrependBytes(val, start, num_bytes, data);
-
-  // ASN.1 integers are signed. To encode a positive integer whose sign bit
-  // (the most significant bit) would otherwise be set and make the number
-  // negative, ASN.1 requires a leading null byte to force the integer to be
-  // positive.
-  uint8_t front = data->front();
-  if ((front & 0x80) != 0) {
-    data->push_front(0x00);
-    num_bytes++;
-  }
-
-  PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data);
-}
-
-bool PrivateKeyInfoCodec::ReadInteger(uint8_t** pos,
-                                      uint8_t* end,
-                                      std::vector<uint8_t>* out) {
-  return ReadIntegerImpl(pos, end, out, big_endian_);
-}
-
-bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(
-    uint8_t** pos,
-    uint8_t* end,
-    size_t expected_size,
-    std::vector<uint8_t>* out) {
-  std::vector<uint8_t> temp;
-  if (!ReadIntegerImpl(pos, end, &temp, true))  // Big-Endian
-    return false;
-
-  int pad = expected_size - temp.size();
-  int index = 0;
-  if (out->size() == expected_size + 1) {
-    READ_ASSERT(out->front() == 0x00);
-    pad++;
-    index++;
-  } else {
-    READ_ASSERT(out->size() <= expected_size);
-  }
-
-  out->insert(out->end(), pad, 0x00);
-  out->insert(out->end(), temp.begin(), temp.end());
-
-  // Reverse output if little-endian.
-  if (!big_endian_)
-    std::reverse(out->begin(), out->end());
-  return true;
-}
-
-bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8_t** pos,
-                                          uint8_t* end,
-                                          std::vector<uint8_t>* out,
-                                          bool big_endian) {
-  uint32_t length = 0;
-  if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length) || !length)
-    return false;
-
-  // The first byte can be zero to force positiveness. We can ignore this.
-  if (**pos == 0x00) {
-    ++(*pos);
-    --length;
-  }
-
-  if (length)
-    out->insert(out->end(), *pos, (*pos) + length);
-
-  (*pos) += length;
-
-  // Reverse output if little-endian.
-  if (!big_endian)
-    std::reverse(out->begin(), out->end());
-  return true;
-}
-
-void PrivateKeyInfoCodec::PrependBytes(uint8_t* val,
-                                       int start,
-                                       int num_bytes,
-                                       std::list<uint8_t>* data) {
-  while (num_bytes > 0) {
-    --num_bytes;
-    data->push_front(val[start + num_bytes]);
-  }
-}
-
-void PrivateKeyInfoCodec::PrependLength(size_t size, std::list<uint8_t>* data) {
-  // The high bit is used to indicate whether additional octets are needed to
-  // represent the length.
-  if (size < 0x80) {
-    data->push_front(static_cast<uint8_t>(size));
-  } else {
-    uint8_t num_bytes = 0;
-    while (size > 0) {
-      data->push_front(static_cast<uint8_t>(size & 0xFF));
-      size >>= 8;
-      num_bytes++;
-    }
-    CHECK_LE(num_bytes, 4);
-    data->push_front(0x80 | num_bytes);
-  }
-}
-
-void PrivateKeyInfoCodec::PrependTypeHeaderAndLength(
-    uint8_t type,
-    uint32_t length,
-    std::list<uint8_t>* output) {
-  PrependLength(length, output);
-  output->push_front(type);
-}
-
-void PrivateKeyInfoCodec::PrependBitString(uint8_t* val,
-                                           int num_bytes,
-                                           std::list<uint8_t>* output) {
-  // Start with the data.
-  PrependBytes(val, 0, num_bytes, output);
-  // Zero unused bits.
-  output->push_front(0);
-  // Add the length.
-  PrependLength(num_bytes + 1, output);
-  // Finally, add the bit string tag.
-  output->push_front((uint8_t)kBitStringTag);
-}
-
-bool PrivateKeyInfoCodec::ReadLength(uint8_t** pos,
-                                     uint8_t* end,
-                                     uint32_t* result) {
-  READ_ASSERT(*pos < end);
-  int length = 0;
-
-  // If the MSB is not set, the length is just the byte itself.
-  if (!(**pos & 0x80)) {
-    length = **pos;
-    (*pos)++;
-  } else {
-    // Otherwise, the lower 7 indicate the length of the length.
-    int length_of_length = **pos & 0x7F;
-    READ_ASSERT(length_of_length <= 4);
-    (*pos)++;
-    READ_ASSERT(*pos + length_of_length < end);
-
-    length = 0;
-    for (int i = 0; i < length_of_length; ++i) {
-      length <<= 8;
-      length |= **pos;
-      (*pos)++;
-    }
-  }
-
-  READ_ASSERT(*pos + length <= end);
-  if (result) *result = length;
-  return true;
-}
-
-bool PrivateKeyInfoCodec::ReadTypeHeaderAndLength(uint8_t** pos,
-                                                  uint8_t* end,
-                                                  uint8_t expected_tag,
-                                                  uint32_t* length) {
-  READ_ASSERT(*pos < end);
-  READ_ASSERT(**pos == expected_tag);
-  (*pos)++;
-
-  return ReadLength(pos, end, length);
-}
-
-bool PrivateKeyInfoCodec::ReadSequence(uint8_t** pos, uint8_t* end) {
-  return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL);
-}
-
-bool PrivateKeyInfoCodec::ReadAlgorithmIdentifier(uint8_t** pos, uint8_t* end) {
-  READ_ASSERT(*pos + sizeof(kRsaAlgorithmIdentifier) < end);
-  READ_ASSERT(memcmp(*pos, kRsaAlgorithmIdentifier,
-                     sizeof(kRsaAlgorithmIdentifier)) == 0);
-  (*pos) += sizeof(kRsaAlgorithmIdentifier);
-  return true;
-}
-
-bool PrivateKeyInfoCodec::ReadVersion(uint8_t** pos, uint8_t* end) {
-  uint32_t length = 0;
-  if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length))
-    return false;
-
-  // The version should be zero.
-  for (uint32_t i = 0; i < length; ++i) {
-    READ_ASSERT(**pos == 0x00);
-    (*pos)++;
-  }
-
-  return true;
-}
-
-}  // namespace
-
-namespace crypto {
-
-RSAPrivateKey::~RSAPrivateKey() {
-  if (key_)
-    SECKEY_DestroyPrivateKey(key_);
-  if (public_key_)
-    SECKEY_DestroyPublicKey(public_key_);
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::Create(uint16_t num_bits) {
-  EnsureNSSInit();
-
-  ScopedPK11Slot slot(PK11_GetInternalSlot());
-  if (!slot) {
-    NOTREACHED();
-    return nullptr;
-  }
-
-  ScopedSECKEYPublicKey public_key;
-  ScopedSECKEYPrivateKey private_key;
-  if (!GenerateRSAKeyPairNSS(slot.get(), num_bits, false /* not permanent */,
-                             &public_key, &private_key)) {
-    return nullptr;
-  }
-
-  RSAPrivateKey* rsa_key = new RSAPrivateKey;
-  rsa_key->public_key_ = public_key.release();
-  rsa_key->key_ = private_key.release();
-  return rsa_key;
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
-    const std::vector<uint8_t>& input) {
-  EnsureNSSInit();
-
-  ScopedPK11Slot slot(PK11_GetInternalSlot());
-  if (!slot) {
-    NOTREACHED();
-    return nullptr;
-  }
-  ScopedSECKEYPrivateKey key(ImportNSSKeyFromPrivateKeyInfo(
-      slot.get(), input, false /* not permanent */));
-  if (!key || SECKEY_GetPrivateKeyType(key.get()) != rsaKey)
-    return nullptr;
-  return RSAPrivateKey::CreateFromKey(key.get());
-}
-
-// static
-RSAPrivateKey* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey* key) {
-  DCHECK(key);
-  if (SECKEY_GetPrivateKeyType(key) != rsaKey)
-    return NULL;
-  RSAPrivateKey* copy = new RSAPrivateKey();
-  copy->key_ = SECKEY_CopyPrivateKey(key);
-  copy->public_key_ = SECKEY_ConvertToPublicKey(key);
-  if (!copy->key_ || !copy->public_key_) {
-    NOTREACHED();
-    delete copy;
-    return NULL;
-  }
-  return copy;
-}
-
-RSAPrivateKey* RSAPrivateKey::Copy() const {
-  RSAPrivateKey* copy = new RSAPrivateKey();
-  copy->key_ = SECKEY_CopyPrivateKey(key_);
-  copy->public_key_ = SECKEY_CopyPublicKey(public_key_);
-  return copy;
-}
-
-bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const {
-  PrivateKeyInfoCodec private_key_info(true);
-
-  // Manually read the component attributes of the private key and build up
-  // the PrivateKeyInfo.
-  if (!ReadAttribute(key_, CKA_MODULUS, private_key_info.modulus()) ||
-      !ReadAttribute(key_, CKA_PUBLIC_EXPONENT,
-          private_key_info.public_exponent()) ||
-      !ReadAttribute(key_, CKA_PRIVATE_EXPONENT,
-          private_key_info.private_exponent()) ||
-      !ReadAttribute(key_, CKA_PRIME_1, private_key_info.prime1()) ||
-      !ReadAttribute(key_, CKA_PRIME_2, private_key_info.prime2()) ||
-      !ReadAttribute(key_, CKA_EXPONENT_1, private_key_info.exponent1()) ||
-      !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) ||
-      !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) {
-    NOTREACHED();
-    return false;
-  }
-
-  return private_key_info.Export(output);
-}
-
-bool RSAPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const {
-  ScopedSECItem der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_));
-  if (!der_pubkey.get()) {
-    NOTREACHED();
-    return false;
-  }
-
-  output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len);
-  return true;
-}
-
-RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) {
-  EnsureNSSInit();
-}
-
-}  // namespace crypto
diff --git a/crypto/secure_hash_default.cc b/crypto/secure_hash_default.cc
deleted file mode 100644
index b33010fd..0000000
--- a/crypto/secure_hash_default.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "crypto/secure_hash.h"
-
-#include <stddef.h>
-
-#include "base/logging.h"
-#include "base/pickle.h"
-#include "crypto/third_party/nss/chromium-blapi.h"
-#include "crypto/third_party/nss/chromium-sha256.h"
-
-namespace crypto {
-
-namespace {
-
-class SecureHashSHA256NSS : public SecureHash {
- public:
-  SecureHashSHA256NSS() {
-    SHA256_Begin(&ctx_);
-  }
-
-  SecureHashSHA256NSS(const SecureHashSHA256NSS& other) {
-    SHA256_Clone(&ctx_, const_cast<SHA256Context*>(&other.ctx_));
-  }
-
-  ~SecureHashSHA256NSS() override { memset(&ctx_, 0, sizeof(ctx_)); }
-
-  // SecureHash implementation:
-  void Update(const void* input, size_t len) override {
-    SHA256_Update(&ctx_, static_cast<const unsigned char*>(input), len);
-  }
-
-  void Finish(void* output, size_t len) override {
-    SHA256_End(&ctx_, static_cast<unsigned char*>(output), NULL,
-               static_cast<unsigned int>(len));
-  }
-
-  SecureHash* Clone() const override { return new SecureHashSHA256NSS(*this); }
-
-  size_t GetHashLength() const override { return SHA256_LENGTH; }
-
- private:
-  SHA256Context ctx_;
-};
-
-}  // namespace
-
-SecureHash* SecureHash::Create(Algorithm algorithm) {
-  switch (algorithm) {
-    case SHA256:
-      return new SecureHashSHA256NSS();
-    default:
-      NOTIMPLEMENTED();
-      return NULL;
-  }
-}
-
-}  // namespace crypto
diff --git a/crypto/signature_creator.h b/crypto/signature_creator.h
index abd1546..98329b8 100644
--- a/crypto/signature_creator.h
+++ b/crypto/signature_creator.h
@@ -13,13 +13,8 @@
 #include "build/build_config.h"
 #include "crypto/crypto_export.h"
 
-#if defined(USE_OPENSSL)
 // Forward declaration for openssl/*.h
 typedef struct env_md_ctx_st EVP_MD_CTX;
-#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX)
-// Forward declaration.
-struct SGNContextStr;
-#endif
 
 namespace crypto {
 
@@ -61,11 +56,7 @@
   // Private constructor. Use the Create() method instead.
   SignatureCreator();
 
-#if defined(USE_OPENSSL)
   EVP_MD_CTX* sign_context_;
-#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX)
-  SGNContextStr* sign_context_;
-#endif
 
   DISALLOW_COPY_AND_ASSIGN(SignatureCreator);
 };
diff --git a/crypto/signature_creator_nss.cc b/crypto/signature_creator_nss.cc
deleted file mode 100644
index 538be93..0000000
--- a/crypto/signature_creator_nss.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "crypto/signature_creator.h"
-
-#include <cryptohi.h>
-#include <keyhi.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include <memory>
-
-#include "base/logging.h"
-#include "crypto/nss_util.h"
-#include "crypto/rsa_private_key.h"
-
-namespace crypto {
-
-namespace {
-
-SECOidTag ToNSSSigOid(SignatureCreator::HashAlgorithm hash_alg) {
-  switch (hash_alg) {
-    case SignatureCreator::SHA1:
-      return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
-    case SignatureCreator::SHA256:
-      return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
-  }
-  return SEC_OID_UNKNOWN;
-}
-
-SECOidTag ToNSSHashOid(SignatureCreator::HashAlgorithm hash_alg) {
-  switch (hash_alg) {
-    case SignatureCreator::SHA1:
-      return SEC_OID_SHA1;
-    case SignatureCreator::SHA256:
-      return SEC_OID_SHA256;
-  }
-  return SEC_OID_UNKNOWN;
-}
-
-}  // namespace
-
-SignatureCreator::~SignatureCreator() {
-  if (sign_context_) {
-    SGN_DestroyContext(sign_context_, PR_TRUE);
-    sign_context_ = NULL;
-  }
-}
-
-// static
-SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key,
-                                           HashAlgorithm hash_alg) {
-  std::unique_ptr<SignatureCreator> result(new SignatureCreator);
-  result->sign_context_ = SGN_NewContext(ToNSSSigOid(hash_alg), key->key());
-  if (!result->sign_context_) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  SECStatus rv = SGN_Begin(result->sign_context_);
-  if (rv != SECSuccess) {
-    NOTREACHED();
-    return NULL;
-  }
-
-  return result.release();
-}
-
-// static
-bool SignatureCreator::Sign(RSAPrivateKey* key,
-                            HashAlgorithm hash_alg,
-                            const uint8_t* data,
-                            int data_len,
-                            std::vector<uint8_t>* signature) {
-  SECItem data_item;
-  data_item.type = siBuffer;
-  data_item.data = const_cast<unsigned char*>(data);
-  data_item.len = data_len;
-
-  SECItem signature_item;
-  SECStatus rv = SGN_Digest(key->key(), ToNSSHashOid(hash_alg), &signature_item,
-                            &data_item);
-  if (rv != SECSuccess) {
-    NOTREACHED();
-    return false;
-  }
-  signature->assign(signature_item.data,
-                    signature_item.data + signature_item.len);
-  SECITEM_FreeItem(&signature_item, PR_FALSE);
-  return true;
-}
-
-bool SignatureCreator::Update(const uint8_t* data_part, int data_part_len) {
-  SECStatus rv = SGN_Update(sign_context_, data_part, data_part_len);
-  if (rv != SECSuccess) {
-    NOTREACHED();
-    return false;
-  }
-
-  return true;
-}
-
-bool SignatureCreator::Final(std::vector<uint8_t>* signature) {
-  SECItem signature_item;
-  SECStatus rv = SGN_End(sign_context_, &signature_item);
-  if (rv != SECSuccess) {
-    return false;
-  }
-  signature->assign(signature_item.data,
-                    signature_item.data + signature_item.len);
-  SECITEM_FreeItem(&signature_item, PR_FALSE);
-  return true;
-}
-
-SignatureCreator::SignatureCreator() : sign_context_(NULL) {
-  EnsureNSSInit();
-}
-
-}  // namespace crypto
diff --git a/crypto/signature_verifier.h b/crypto/signature_verifier.h
index 5b7369fb..e6b6fc01 100644
--- a/crypto/signature_verifier.h
+++ b/crypto/signature_verifier.h
@@ -12,14 +12,8 @@
 #include "build/build_config.h"
 #include "crypto/crypto_export.h"
 
-#if defined(USE_OPENSSL)
 typedef struct env_md_st EVP_MD;
 typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
-#else
-typedef struct HASHContextStr HASHContext;
-typedef struct SECKEYPublicKeyStr SECKEYPublicKey;
-typedef struct VFYContextStr VFYContext;
-#endif
 
 namespace crypto {
 
@@ -96,7 +90,6 @@
   bool VerifyFinal();
 
  private:
-#if defined(USE_OPENSSL)
   bool CommonInit(int pkey_type,
                   const EVP_MD* digest,
                   const uint8_t* signature,
@@ -104,29 +97,13 @@
                   const uint8_t* public_key_info,
                   int public_key_info_len,
                   EVP_PKEY_CTX** pkey_ctx);
-#else
-  static SECKEYPublicKey* DecodePublicKeyInfo(const uint8_t* public_key_info,
-                                              int public_key_info_len);
-#endif
 
   void Reset();
 
   std::vector<uint8_t> signature_;
 
-#if defined(USE_OPENSSL)
   struct VerifyContext;
   VerifyContext* verify_context_;
-#else
-  // Used for all signature types except RSA-PSS.
-  VFYContext* vfy_context_;
-
-  // Used for RSA-PSS signatures.
-  HashAlgorithm hash_alg_;
-  HashAlgorithm mask_hash_alg_;
-  unsigned int salt_len_;
-  SECKEYPublicKey* public_key_;
-  HASHContext* hash_context_;
-#endif
 };
 
 }  // namespace crypto
diff --git a/crypto/signature_verifier_nss.cc b/crypto/signature_verifier_nss.cc
deleted file mode 100644
index edbd3f6..0000000
--- a/crypto/signature_verifier_nss.cc
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "crypto/signature_verifier.h"
-
-#include <cryptohi.h>
-#include <keyhi.h>
-#include <pk11pub.h>
-#include <secerr.h>
-#include <sechash.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include "base/logging.h"
-#include "crypto/nss_util.h"
-#include "crypto/third_party/nss/chromium-nss.h"
-
-namespace crypto {
-
-namespace {
-
-HASH_HashType ToNSSHashType(SignatureVerifier::HashAlgorithm hash_alg) {
-  switch (hash_alg) {
-    case SignatureVerifier::SHA1:
-      return HASH_AlgSHA1;
-    case SignatureVerifier::SHA256:
-      return HASH_AlgSHA256;
-  }
-  return HASH_AlgNULL;
-}
-
-SECOidTag ToNSSSignatureType(SignatureVerifier::SignatureAlgorithm sig_alg) {
-  switch (sig_alg) {
-    case SignatureVerifier::RSA_PKCS1_SHA1:
-      return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
-    case SignatureVerifier::RSA_PKCS1_SHA256:
-      return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
-    case SignatureVerifier::ECDSA_SHA256:
-      return SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
-  }
-  return SEC_OID_UNKNOWN;
-}
-
-SECStatus VerifyRSAPSS_End(SECKEYPublicKey* public_key,
-                           HASHContext* hash_context,
-                           HASH_HashType mask_hash_alg,
-                           unsigned int salt_len,
-                           const unsigned char* signature,
-                           unsigned int signature_len) {
-  unsigned int hash_len = HASH_ResultLenContext(hash_context);
-  std::vector<unsigned char> hash(hash_len);
-  HASH_End(hash_context, &hash[0], &hash_len, hash.size());
-
-  unsigned int modulus_len = SECKEY_PublicKeyStrength(public_key);
-  if (signature_len != modulus_len) {
-    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
-    return SECFailure;
-  }
-  std::vector<unsigned char> enc(signature_len);
-  SECStatus rv = PK11_PubEncryptRaw(public_key, &enc[0],
-                                    const_cast<unsigned char*>(signature),
-                                    signature_len, NULL);
-  if (rv != SECSuccess) {
-    LOG(WARNING) << "PK11_PubEncryptRaw failed";
-    return rv;
-  }
-  return emsa_pss_verify(&hash[0], &enc[0], enc.size(),
-                         HASH_GetType(hash_context), mask_hash_alg,
-                         salt_len);
-}
-
-}  // namespace
-
-SignatureVerifier::SignatureVerifier()
-    : vfy_context_(NULL),
-      hash_alg_(SHA1),
-      mask_hash_alg_(SHA1),
-      salt_len_(0),
-      public_key_(NULL),
-      hash_context_(NULL) {
-  EnsureNSSInit();
-}
-
-SignatureVerifier::~SignatureVerifier() {
-  Reset();
-}
-
-bool SignatureVerifier::VerifyInit(SignatureAlgorithm signature_algorithm,
-                                   const uint8_t* signature,
-                                   int signature_len,
-                                   const uint8_t* public_key_info,
-                                   int public_key_info_len) {
-  if (vfy_context_ || hash_context_)
-    return false;
-
-  signature_.assign(signature, signature + signature_len);
-
-  SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info,
-                                                    public_key_info_len);
-  if (!public_key)
-    return false;
-
-  SECItem sig;
-  sig.type = siBuffer;
-  sig.data = const_cast<uint8_t*>(signature);
-  sig.len = signature_len;
-  vfy_context_ = VFY_CreateContext(
-      public_key, &sig, ToNSSSignatureType(signature_algorithm), nullptr);
-  SECKEY_DestroyPublicKey(public_key);  // Done with public_key.
-  if (!vfy_context_) {
-    // A corrupted RSA signature could be detected without the data, so
-    // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE
-    // (-8182).
-    return false;
-  }
-
-  if (VFY_Begin(vfy_context_) != SECSuccess) {
-    NOTREACHED();
-    return false;
-  }
-  return true;
-}
-
-bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg,
-                                         HashAlgorithm mask_hash_alg,
-                                         int salt_len,
-                                         const uint8_t* signature,
-                                         int signature_len,
-                                         const uint8_t* public_key_info,
-                                         int public_key_info_len) {
-  if (vfy_context_ || hash_context_)
-    return false;
-
-  signature_.assign(signature, signature + signature_len);
-
-  SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info,
-                                                    public_key_info_len);
-  if (!public_key)
-    return false;
-
-  public_key_ = public_key;
-  hash_alg_ = hash_alg;
-  mask_hash_alg_ = mask_hash_alg;
-  salt_len_ = salt_len;
-  hash_context_ = HASH_Create(ToNSSHashType(hash_alg_));
-  if (!hash_context_)
-    return false;
-  HASH_Begin(hash_context_);
-  return true;
-}
-
-void SignatureVerifier::VerifyUpdate(const uint8_t* data_part,
-                                     int data_part_len) {
-  if (vfy_context_) {
-    SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len);
-    DCHECK_EQ(SECSuccess, rv);
-  } else {
-    HASH_Update(hash_context_, data_part, data_part_len);
-  }
-}
-
-bool SignatureVerifier::VerifyFinal() {
-  SECStatus rv;
-  if (vfy_context_) {
-    rv = VFY_End(vfy_context_);
-  } else {
-    rv = VerifyRSAPSS_End(public_key_, hash_context_,
-                          ToNSSHashType(mask_hash_alg_), salt_len_,
-                          signature_.data(),
-                          signature_.size());
-  }
-  Reset();
-
-  // If signature verification fails, the error code is
-  // SEC_ERROR_BAD_SIGNATURE (-8182).
-  return (rv == SECSuccess);
-}
-
-// static
-SECKEYPublicKey* SignatureVerifier::DecodePublicKeyInfo(
-    const uint8_t* public_key_info,
-    int public_key_info_len) {
-  CERTSubjectPublicKeyInfo* spki = NULL;
-  SECItem spki_der;
-  spki_der.type = siBuffer;
-  spki_der.data = const_cast<uint8_t*>(public_key_info);
-  spki_der.len = public_key_info_len;
-  spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der);
-  if (!spki)
-    return NULL;
-  SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki);
-  SECKEY_DestroySubjectPublicKeyInfo(spki);  // Done with spki.
-  return public_key;
-}
-
-void SignatureVerifier::Reset() {
-  if (vfy_context_) {
-    VFY_DestroyContext(vfy_context_, PR_TRUE);
-    vfy_context_ = NULL;
-  }
-  if (hash_context_) {
-    HASH_Destroy(hash_context_);
-    hash_context_ = NULL;
-  }
-  if (public_key_) {
-    SECKEY_DestroyPublicKey(public_key_);
-    public_key_ = NULL;
-  }
-  signature_.clear();
-}
-
-}  // namespace crypto
diff --git a/crypto/symmetric_key.h b/crypto/symmetric_key.h
index 14f74aeb7..b24e2df 100644
--- a/crypto/symmetric_key.h
+++ b/crypto/symmetric_key.h
@@ -17,9 +17,6 @@
 // See comments for crypto_nacl_win64 in crypto.gyp.
 // Must test for NACL_WIN64 before OS_WIN since former is a subset of latter.
 #include "crypto/scoped_capi_types.h"
-#elif defined(USE_NSS_CERTS) || \
-    (!defined(USE_OPENSSL) && (defined(OS_WIN) || defined(OS_MACOSX)))
-#include "crypto/scoped_nss_types.h"
 #endif
 
 namespace crypto {
@@ -62,10 +59,8 @@
 
 #if defined(NACL_WIN64)
   HCRYPTKEY key() const { return key_.get(); }
-#elif defined(USE_OPENSSL)
+#else
   const std::string& key() { return key_; }
-#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX)
-  PK11SymKey* key() const { return key_.get(); }
 #endif
 
   // Extracts the raw key from the platform specific data.
@@ -88,12 +83,9 @@
   // TODO(rsleevi): See if KP_EFFECTIVE_KEYLEN is the reason why CryptExportKey
   // fails with NTE_BAD_KEY/NTE_BAD_LEN
   std::string raw_key_;
-#elif defined(USE_OPENSSL)
+#else
   SymmetricKey() {}
   std::string key_;
-#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX)
-  explicit SymmetricKey(PK11SymKey* key);
-  ScopedPK11SymKey key_;
 #endif
 
   DISALLOW_COPY_AND_ASSIGN(SymmetricKey);
diff --git a/crypto/symmetric_key_nss.cc b/crypto/symmetric_key_nss.cc
deleted file mode 100644
index e3aacc7..0000000
--- a/crypto/symmetric_key_nss.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "crypto/symmetric_key.h"
-
-#include <nss.h>
-#include <pk11pub.h>
-#include <stddef.h>
-
-#include "base/logging.h"
-#include "crypto/nss_util.h"
-#include "crypto/scoped_nss_types.h"
-
-namespace crypto {
-
-SymmetricKey::~SymmetricKey() {}
-
-// static
-SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm,
-                                              size_t key_size_in_bits) {
-  DCHECK_EQ(AES, algorithm);
-
-  EnsureNSSInit();
-
-  // Whitelist supported key sizes to avoid accidentaly relying on
-  // algorithms available in NSS but not BoringSSL and vice
-  // versa. Note that BoringSSL does not support AES-192.
-  if (key_size_in_bits != 128 && key_size_in_bits != 256)
-    return NULL;
-
-  ScopedPK11Slot slot(PK11_GetInternalSlot());
-  if (!slot.get())
-    return NULL;
-
-  PK11SymKey* sym_key = PK11_KeyGen(slot.get(), CKM_AES_KEY_GEN, NULL,
-                                    key_size_in_bits / 8, NULL);
-  if (!sym_key)
-    return NULL;
-
-  return new SymmetricKey(sym_key);
-}
-
-// static
-SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm,
-                                                  const std::string& password,
-                                                  const std::string& salt,
-                                                  size_t iterations,
-                                                  size_t key_size_in_bits) {
-  EnsureNSSInit();
-  if (salt.empty() || iterations == 0 || key_size_in_bits == 0)
-    return NULL;
-
-  if (algorithm == AES) {
-    // Whitelist supported key sizes to avoid accidentaly relying on
-    // algorithms available in NSS but not BoringSSL and vice
-    // versa. Note that BoringSSL does not support AES-192.
-    if (key_size_in_bits != 128 && key_size_in_bits != 256)
-      return NULL;
-  }
-
-  SECItem password_item;
-  password_item.type = siBuffer;
-  password_item.data = reinterpret_cast<unsigned char*>(
-      const_cast<char *>(password.data()));
-  password_item.len = password.size();
-
-  SECItem salt_item;
-  salt_item.type = siBuffer;
-  salt_item.data = reinterpret_cast<unsigned char*>(
-      const_cast<char *>(salt.data()));
-  salt_item.len = salt.size();
-
-  SECOidTag cipher_algorithm =
-      algorithm == AES ? SEC_OID_AES_256_CBC : SEC_OID_HMAC_SHA1;
-  ScopedSECAlgorithmID alg_id(PK11_CreatePBEV2AlgorithmID(SEC_OID_PKCS5_PBKDF2,
-                                                          cipher_algorithm,
-                                                          SEC_OID_HMAC_SHA1,
-                                                          key_size_in_bits / 8,
-                                                          iterations,
-                                                          &salt_item));
-  if (!alg_id.get())
-    return NULL;
-
-  ScopedPK11Slot slot(PK11_GetInternalSlot());
-  if (!slot.get())
-    return NULL;
-
-  PK11SymKey* sym_key = PK11_PBEKeyGen(slot.get(), alg_id.get(), &password_item,
-                                       PR_FALSE, NULL);
-  if (!sym_key)
-    return NULL;
-
-  return new SymmetricKey(sym_key);
-}
-
-// static
-SymmetricKey* SymmetricKey::Import(Algorithm algorithm,
-                                   const std::string& raw_key) {
-  EnsureNSSInit();
-
-  if (algorithm == AES) {
-    // Whitelist supported key sizes to avoid accidentaly relying on
-    // algorithms available in NSS but not BoringSSL and vice
-    // versa. Note that BoringSSL does not support AES-192.
-    if (raw_key.size() != 128/8 && raw_key.size() != 256/8)
-      return NULL;
-  }
-
-  CK_MECHANISM_TYPE cipher =
-      algorithm == AES ? CKM_AES_CBC : CKM_SHA_1_HMAC;
-
-  SECItem key_item;
-  key_item.type = siBuffer;
-  key_item.data = reinterpret_cast<unsigned char*>(
-      const_cast<char *>(raw_key.data()));
-  key_item.len = raw_key.size();
-
-  ScopedPK11Slot slot(PK11_GetInternalSlot());
-  if (!slot.get())
-    return NULL;
-
-  // The exact value of the |origin| argument doesn't matter to NSS as long as
-  // it's not PK11_OriginFortezzaHack, so we pass PK11_OriginUnwrap as a
-  // placeholder.
-  PK11SymKey* sym_key = PK11_ImportSymKey(slot.get(), cipher, PK11_OriginUnwrap,
-                                          CKA_ENCRYPT, &key_item, NULL);
-  if (!sym_key)
-    return NULL;
-
-  return new SymmetricKey(sym_key);
-}
-
-bool SymmetricKey::GetRawKey(std::string* raw_key) {
-  SECStatus rv = PK11_ExtractKeyValue(key_.get());
-  if (SECSuccess != rv)
-    return false;
-
-  SECItem* key_item = PK11_GetKeyData(key_.get());
-  if (!key_item)
-    return false;
-
-  raw_key->assign(reinterpret_cast<char*>(key_item->data), key_item->len);
-  return true;
-}
-
-SymmetricKey::SymmetricKey(PK11SymKey* key) : key_(key) {
-  DCHECK(key);
-}
-
-}  // namespace crypto
diff --git a/crypto/third_party/nss/pk11akey.cc b/crypto/third_party/nss/pk11akey.cc
deleted file mode 100644
index 4db582fc6..0000000
--- a/crypto/third_party/nss/pk11akey.cc
+++ /dev/null
@@ -1,98 +0,0 @@
- /* ***** BEGIN LICENSE BLOCK *****
-  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
-  *
-  * The contents of this file are subject to the Mozilla Public License Version
-  * 1.1 (the "License"); you may not use this file except in compliance with
-  * the License. You may obtain a copy of the License at
-  * http://www.mozilla.org/MPL/
-  *
-  * Software distributed under the License is distributed on an "AS IS" basis,
-  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-  * for the specific language governing rights and limitations under the
-  * License.
-  *
-  * The Original Code is the Netscape security libraries.
-  *
-  * The Initial Developer of the Original Code is
-  * Netscape Communications Corporation.
-  * Portions created by the Initial Developer are Copyright (C) 1994-2000
-  * the Initial Developer. All Rights Reserved.
-  *
-  * Contributor(s):
-  *   Dr Stephen Henson <stephen.henson@gemplus.com>
-  *   Dr Vipul Gupta <vipul.gupta@sun.com>, and
-  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
-  *
-  * Alternatively, the contents of this file may be used under the terms of
-  * either the GNU General Public License Version 2 or later (the "GPL"), or
-  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-  * in which case the provisions of the GPL or the LGPL are applicable instead
-  * of those above. If you wish to allow use of your version of this file only
-  * under the terms of either the GPL or the LGPL, and not to allow others to
-  * use your version of this file under the terms of the MPL, indicate your
-  * decision by deleting the provisions above and replace them with the notice
-  * and other provisions required by the GPL or the LGPL. If you do not delete
-  * the provisions above, a recipient may use your version of this file under
-  * the terms of any one of the MPL, the GPL or the LGPL.
-  *
-  * ***** END LICENSE BLOCK ***** */
-
-#include "crypto/third_party/nss/chromium-nss.h"
-
-#include <pk11pub.h>
-
-#include "base/logging.h"
-
-// Based on PK11_ImportEncryptedPrivateKeyInfo function in
-// mozilla/security/nss/lib/pk11wrap/pk11akey.c.
-SECStatus ImportEncryptedECPrivateKeyInfoAndReturnKey(
-    PK11SlotInfo* slot,
-    SECKEYEncryptedPrivateKeyInfo* epki,
-    SECItem* password,
-    SECItem* nickname,
-    SECItem* public_value,
-    PRBool permanent,
-    PRBool sensitive,
-    SECKEYPrivateKey** private_key,
-    void* wincx) {
-  SECItem* crypto_param = NULL;
-
-  CK_ATTRIBUTE_TYPE usage = CKA_SIGN;
-
-  PK11SymKey* key = PK11_PBEKeyGen(slot,
-                                   &epki->algorithm,
-                                   password,
-                                   PR_FALSE,  // faulty3DES
-                                   wincx);
-  if (key == NULL) {
-    DLOG(ERROR) << "PK11_PBEKeyGen: " << PORT_GetError();
-    return SECFailure;
-  }
-
-  CK_MECHANISM_TYPE crypto_mech_type = PK11_GetPBECryptoMechanism(
-      &epki->algorithm, &crypto_param, password);
-  if (crypto_mech_type == CKM_INVALID_MECHANISM) {
-    DLOG(ERROR) << "PK11_GetPBECryptoMechanism: " << PORT_GetError();
-    PK11_FreeSymKey(key);
-    return SECFailure;
-  }
-
-  crypto_mech_type = PK11_GetPadMechanism(crypto_mech_type);
-
-  *private_key = PK11_UnwrapPrivKey(slot, key, crypto_mech_type, crypto_param,
-                                    &epki->encryptedData, nickname,
-                                    public_value, permanent, sensitive, CKK_EC,
-                                    &usage, 1, wincx);
-
-  if (crypto_param != NULL)
-    SECITEM_ZfreeItem(crypto_param, PR_TRUE);
-
-  PK11_FreeSymKey(key);
-
-  if (!*private_key) {
-    DLOG(ERROR) << "PK11_UnwrapPrivKey: " << PORT_GetError();
-    return SECFailure;
-  }
-
-  return SECSuccess;
-}
diff --git a/crypto/third_party/nss/rsawrapr.c b/crypto/third_party/nss/rsawrapr.c
deleted file mode 100644
index 73e498f9..0000000
--- a/crypto/third_party/nss/rsawrapr.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * PKCS#1 encoding and decoding functions.
- * This file is believed to contain no code licensed from other parties.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "seccomon.h"
-#include "secerr.h"
-#include "sechash.h"
-
-/* Needed for RSA-PSS functions */
-static const unsigned char eightZeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-
-/*
- * Mask generation function MGF1 as defined in PKCS #1 v2.1 / RFC 3447.
- */
-static SECStatus
-MGF1(HASH_HashType hashAlg, unsigned char *mask, unsigned int maskLen,
-     const unsigned char *mgfSeed, unsigned int mgfSeedLen)
-{
-    unsigned int digestLen;
-    PRUint32 counter, rounds;
-    unsigned char *tempHash, *temp;
-    const SECHashObject *hash;
-    void *hashContext;
-    unsigned char C[4];
-
-    hash = HASH_GetHashObject(hashAlg);
-    if (hash == NULL)
-        return SECFailure;
-
-    hashContext = (*hash->create)();
-    rounds = (maskLen + hash->length - 1) / hash->length;
-    for (counter = 0; counter < rounds; counter++) {
-        C[0] = (unsigned char)((counter >> 24) & 0xff);
-        C[1] = (unsigned char)((counter >> 16) & 0xff);
-        C[2] = (unsigned char)((counter >> 8) & 0xff);
-        C[3] = (unsigned char)(counter & 0xff);
-
-        /* This could be optimized when the clone functions in
-         * rawhash.c are implemented. */
-        (*hash->begin)(hashContext);
-        (*hash->update)(hashContext, mgfSeed, mgfSeedLen); 
-        (*hash->update)(hashContext, C, sizeof C);
-
-        tempHash = mask + counter * hash->length;
-        if (counter != (rounds-1)) {
-            (*hash->end)(hashContext, tempHash, &digestLen, hash->length);
-        } else { /* we're in the last round and need to cut the hash */
-            temp = (unsigned char *)PORT_Alloc(hash->length);
-            (*hash->end)(hashContext, temp, &digestLen, hash->length);
-            PORT_Memcpy(tempHash, temp, maskLen - counter * hash->length);
-            PORT_Free(temp);
-        }
-    }
-    (*hash->destroy)(hashContext, PR_TRUE);
-
-    return SECSuccess;
-}
-
-/*
- * Verify a RSA-PSS signature.
- * Described in RFC 3447, section 9.1.2.
- * We use mHash instead of M as input.
- * emBits from the RFC is just modBits - 1, see section 8.1.2.
- * We only support MGF1 as the MGF.
- *
- * NOTE: this code assumes modBits is a multiple of 8.
- */
-SECStatus
-emsa_pss_verify(const unsigned char *mHash,
-                const unsigned char *em, unsigned int emLen,
-                HASH_HashType hashAlg, HASH_HashType maskHashAlg,
-                unsigned int sLen)
-{
-    const SECHashObject *hash;
-    void *hash_context;
-    unsigned char *db;
-    unsigned char *H_;  /* H' from the RFC */
-    unsigned int i, dbMaskLen;
-    SECStatus rv;
-
-    hash = HASH_GetHashObject(hashAlg);
-    dbMaskLen = emLen - hash->length - 1;
-
-    /* Step 3 + 4 + 6 */
-    if ((emLen < (hash->length + sLen + 2)) ||
-	(em[emLen - 1] != 0xbc) ||
-	((em[0] & 0x80) != 0)) {
-	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
-	return SECFailure;
-    }
-
-    /* Step 7 */
-    db = (unsigned char *)PORT_Alloc(dbMaskLen);
-    if (db == NULL) {
-	PORT_SetError(SEC_ERROR_NO_MEMORY);
-	return SECFailure;
-    }
-    /* &em[dbMaskLen] points to H, used as mgfSeed */
-    MGF1(maskHashAlg, db, dbMaskLen, &em[dbMaskLen], hash->length);
-
-    /* Step 8 */
-    for (i = 0; i < dbMaskLen; i++) {
-	db[i] ^= em[i];
-    }
-
-    /* Step 9 */
-    db[0] &= 0x7f;
-
-    /* Step 10 */
-    for (i = 0; i < (dbMaskLen - sLen - 1); i++) {
-	if (db[i] != 0) {
-	    PORT_Free(db);
-	    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
-	    return SECFailure;
-	}
-    }
-    if (db[dbMaskLen - sLen - 1] != 0x01) {
-	PORT_Free(db);
-	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
-	return SECFailure;
-    }
-
-    /* Step 12 + 13 */
-    H_ = (unsigned char *)PORT_Alloc(hash->length);
-    if (H_ == NULL) {
-	PORT_Free(db);
-	PORT_SetError(SEC_ERROR_NO_MEMORY);
-	return SECFailure;
-    }
-    hash_context = (*hash->create)();
-    if (hash_context == NULL) {
-	PORT_Free(db);
-	PORT_Free(H_);
-	PORT_SetError(SEC_ERROR_NO_MEMORY);
-	return SECFailure;
-    }
-    (*hash->begin)(hash_context);
-    (*hash->update)(hash_context, eightZeros, 8);
-    (*hash->update)(hash_context, mHash, hash->length);
-    (*hash->update)(hash_context, &db[dbMaskLen - sLen], sLen);
-    (*hash->end)(hash_context, H_, &i, hash->length);
-    (*hash->destroy)(hash_context, PR_TRUE);
-
-    PORT_Free(db);
-
-    /* Step 14 */
-    if (PORT_Memcmp(H_, &em[dbMaskLen], hash->length) != 0) {
-	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
-	rv = SECFailure;
-    } else {
-	rv = SECSuccess;
-    }
-
-    PORT_Free(H_);
-    return rv;
-}
diff --git a/crypto/third_party/nss/secsign.cc b/crypto/third_party/nss/secsign.cc
deleted file mode 100644
index c9816fb0..0000000
--- a/crypto/third_party/nss/secsign.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Signature stuff.
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1994-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "crypto/third_party/nss/chromium-nss.h"
-
-#include <vector>
-
-#include <cryptohi.h>
-#include <pk11pub.h>
-#include <secerr.h>
-#include <sechash.h>
-#include <stdint.h>
-
-#include "base/logging.h"
-#include "build/build_config.h"
-
-SECStatus DerSignData(PLArenaPool *arena,
-                      SECItem *result,
-                      SECItem *input,
-                      SECKEYPrivateKey *key,
-                      SECOidTag algo_id) {
-  if (key->keyType != ecKey) {
-    return SEC_DerSignData(arena, result, input->data, input->len, key,
-                           algo_id);
-  }
-
-  // NSS has a private function sec_DecodeSigAlg it uses to figure out the
-  // correct hash from the algorithm id.
-  HASH_HashType hash_type;
-  switch (algo_id) {
-    case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
-      hash_type = HASH_AlgSHA1;
-      break;
-#ifdef SHA224_LENGTH
-    case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
-      hash_type = HASH_AlgSHA224;
-      break;
-#endif
-    case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
-      hash_type = HASH_AlgSHA256;
-      break;
-    case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
-      hash_type = HASH_AlgSHA384;
-      break;
-    case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
-      hash_type = HASH_AlgSHA512;
-      break;
-    default:
-      PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
-      return SECFailure;
-  }
-
-  // Hash the input.
-  std::vector<uint8_t> hash_data(HASH_ResultLen(hash_type));
-  SECStatus rv = HASH_HashBuf(
-      hash_type, &hash_data[0], input->data, input->len);
-  if (rv != SECSuccess)
-    return rv;
-  SECItem hash = {siBuffer, &hash_data[0], 
-		  static_cast<unsigned int>(hash_data.size())};
-
-  // Compute signature of hash.
-  int signature_len = PK11_SignatureLen(key);
-  std::vector<uint8_t> signature_data(signature_len);
-  SECItem sig = {siBuffer, &signature_data[0], 
-		 static_cast<unsigned int>(signature_len)};
-  rv = PK11_Sign(key, &sig, &hash);
-  if (rv != SECSuccess)
-    return rv;
-
-  CERTSignedData sd;
-  PORT_Memset(&sd, 0, sizeof(sd));
-  // Fill in tbsCertificate.
-  sd.data.data = (unsigned char*) input->data;
-  sd.data.len = input->len;
-
-  // Fill in signatureAlgorithm.
-  rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algo_id, 0);
-  if (rv != SECSuccess)
-    return rv;
-
-  // Fill in signatureValue.
-  rv = DSAU_EncodeDerSigWithLen(&sd.signature, &sig, sig.len);
-  if (rv != SECSuccess)
-    return rv;
-  sd.signature.len <<=  3;  // Convert to bit string.
-
-  // DER encode the signed data object.
-  void* encode_result = SEC_ASN1EncodeItem(
-      arena, result, &sd, SEC_ASN1_GET(CERT_SignedDataTemplate));
-
-  PORT_Free(sd.signature.data);
-
-  return encode_result ? SECSuccess : SECFailure;
-}
diff --git a/extensions/renderer/api/display_source/display_source_session.cc b/extensions/renderer/api/display_source/display_source_session.cc
index 20b14420..96e5bd5 100644
--- a/extensions/renderer/api/display_source/display_source_session.cc
+++ b/extensions/renderer/api/display_source/display_source_session.cc
@@ -14,6 +14,9 @@
     : auth_method(api::display_source::AUTHENTICATION_METHOD_NONE) {
 }
 
+DisplaySourceSessionParams::DisplaySourceSessionParams(
+    const DisplaySourceSessionParams&) = default;
+
 DisplaySourceSessionParams::~DisplaySourceSessionParams() = default;
 
 DisplaySourceSession::DisplaySourceSession()
diff --git a/extensions/renderer/api/display_source/display_source_session.h b/extensions/renderer/api/display_source/display_source_session.h
index 922126d9..a16ac5d 100644
--- a/extensions/renderer/api/display_source/display_source_session.h
+++ b/extensions/renderer/api/display_source/display_source_session.h
@@ -5,6 +5,8 @@
 #ifndef EXTENSIONS_RENDERER_API_DISPLAY_SOURCE_DISPLAY_SOURCE_SESSION_H_
 #define EXTENSIONS_RENDERER_API_DISPLAY_SOURCE_DISPLAY_SOURCE_SESSION_H_
 
+#include <string>
+
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
@@ -93,6 +95,7 @@
 
 struct DisplaySourceSessionParams {
   DisplaySourceSessionParams();
+  DisplaySourceSessionParams(const DisplaySourceSessionParams&);
   ~DisplaySourceSessionParams();
 
   int sink_id;
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_video_encoder.cc b/extensions/renderer/api/display_source/wifi_display/wifi_display_video_encoder.cc
index 7a3e8f4..cf137df 100644
--- a/extensions/renderer/api/display_source/wifi_display/wifi_display_video_encoder.cc
+++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_video_encoder.cc
@@ -12,6 +12,8 @@
 using VideoEncoderCallback = WiFiDisplayVideoEncoder::VideoEncoderCallback;
 
 WiFiDisplayVideoEncoder::InitParameters::InitParameters() = default;
+WiFiDisplayVideoEncoder::InitParameters::InitParameters(const InitParameters&) =
+    default;
 WiFiDisplayVideoEncoder::InitParameters::~InitParameters() = default;
 
 WiFiDisplayVideoEncoder::WiFiDisplayVideoEncoder() = default;
@@ -32,6 +34,3 @@
 }
 
 }  // namespace extensions
-
-
-
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_video_encoder.h b/extensions/renderer/api/display_source/wifi_display/wifi_display_video_encoder.h
index fd093ab..c612089 100644
--- a/extensions/renderer/api/display_source/wifi_display/wifi_display_video_encoder.h
+++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_video_encoder.h
@@ -56,6 +56,7 @@
 
   struct InitParameters {
     InitParameters();
+    InitParameters(const InitParameters&);
     ~InitParameters();
     gfx::Size frame_size;
     int frame_rate;
diff --git a/extensions/renderer/resources/binding.js b/extensions/renderer/resources/binding.js
index 13ac7f9..411f9f9d 100644
--- a/extensions/renderer/resources/binding.js
+++ b/extensions/renderer/resources/binding.js
@@ -166,6 +166,19 @@
   var jsModuleName = type.js_module;
   logging.CHECK(jsModuleName, 'Custom type ' + type.id +
                 ' has no "js_module" property.');
+  // This list contains all types that has a js_module property. It is ugly to
+  // hard-code them here, but the number of APIs that use js_module has not
+  // changed since the introduction of js_modules in crbug.com/222156.
+  // This whitelist serves as an extra line of defence to avoid exposing
+  // arbitrary extension modules when the |type| definition is poisoned.
+  var whitelistedModules = [
+    'ChromeDirectSetting',
+    'ChromeSetting',
+    'ContentSetting',
+    'StorageArea',
+  ];
+  logging.CHECK($Array.indexOf(whitelistedModules, jsModuleName) !== -1,
+                'Module ' + jsModuleName + ' does not define a custom type.');
   var jsModule = require(jsModuleName);
   logging.CHECK(jsModule, 'No module ' + jsModuleName + ' found for ' +
                 type.id + '.');
diff --git a/headless/BUILD.gn b/headless/BUILD.gn
index 088d3373..f1adf42 100644
--- a/headless/BUILD.gn
+++ b/headless/BUILD.gn
@@ -54,8 +54,156 @@
   ]
 }
 
+action("gen_devtools_client_api") {
+  script = "//headless/lib/browser/client_api_generator.py"
+
+  inputs = [
+    "//third_party/WebKit/Source/devtools/protocol.json",
+  ]
+
+  outputs = [
+    "$target_gen_dir/public/domains/accessibility.cc",
+    "$target_gen_dir/public/domains/accessibility.h",
+    "$target_gen_dir/public/domains/animation.cc",
+    "$target_gen_dir/public/domains/animation.h",
+    "$target_gen_dir/public/domains/application_cache.cc",
+    "$target_gen_dir/public/domains/application_cache.h",
+    "$target_gen_dir/public/domains/cache_storage.cc",
+    "$target_gen_dir/public/domains/cache_storage.h",
+    "$target_gen_dir/public/domains/console.cc",
+    "$target_gen_dir/public/domains/console.h",
+    "$target_gen_dir/public/domains/css.cc",
+    "$target_gen_dir/public/domains/css.h",
+    "$target_gen_dir/public/domains/database.cc",
+    "$target_gen_dir/public/domains/database.h",
+    "$target_gen_dir/public/domains/debugger.cc",
+    "$target_gen_dir/public/domains/debugger.h",
+    "$target_gen_dir/public/domains/device_orientation.cc",
+    "$target_gen_dir/public/domains/device_orientation.h",
+    "$target_gen_dir/public/domains/dom_debugger.cc",
+    "$target_gen_dir/public/domains/dom_debugger.h",
+    "$target_gen_dir/public/domains/dom.cc",
+    "$target_gen_dir/public/domains/dom.h",
+    "$target_gen_dir/public/domains/dom_storage.cc",
+    "$target_gen_dir/public/domains/dom_storage.h",
+    "$target_gen_dir/public/domains/emulation.cc",
+    "$target_gen_dir/public/domains/emulation.h",
+    "$target_gen_dir/public/domains/heap_profiler.cc",
+    "$target_gen_dir/public/domains/heap_profiler.h",
+    "$target_gen_dir/public/domains/indexeddb.cc",
+    "$target_gen_dir/public/domains/indexeddb.h",
+    "$target_gen_dir/public/domains/input.cc",
+    "$target_gen_dir/public/domains/input.h",
+    "$target_gen_dir/public/domains/inspector.cc",
+    "$target_gen_dir/public/domains/inspector.h",
+    "$target_gen_dir/public/domains/io.cc",
+    "$target_gen_dir/public/domains/io.h",
+    "$target_gen_dir/public/domains/layer_tree.cc",
+    "$target_gen_dir/public/domains/layer_tree.h",
+    "$target_gen_dir/public/domains/memory.cc",
+    "$target_gen_dir/public/domains/memory.h",
+    "$target_gen_dir/public/domains/network.cc",
+    "$target_gen_dir/public/domains/network.h",
+    "$target_gen_dir/public/domains/page.cc",
+    "$target_gen_dir/public/domains/page.h",
+    "$target_gen_dir/public/domains/profiler.cc",
+    "$target_gen_dir/public/domains/profiler.h",
+    "$target_gen_dir/public/domains/rendering.cc",
+    "$target_gen_dir/public/domains/rendering.h",
+    "$target_gen_dir/public/domains/runtime.cc",
+    "$target_gen_dir/public/domains/runtime.h",
+    "$target_gen_dir/public/domains/security.cc",
+    "$target_gen_dir/public/domains/security.h",
+    "$target_gen_dir/public/domains/service_worker.cc",
+    "$target_gen_dir/public/domains/service_worker.h",
+    "$target_gen_dir/public/domains/tracing.cc",
+    "$target_gen_dir/public/domains/tracing.h",
+    "$target_gen_dir/public/domains/type_conversions.h",
+    "$target_gen_dir/public/domains/types.cc",
+    "$target_gen_dir/public/domains/types.h",
+    "$target_gen_dir/public/domains/worker.cc",
+    "$target_gen_dir/public/domains/worker.h",
+  ]
+
+  sources = [
+    "lib/browser/domain_cc.template",
+    "lib/browser/domain_h.template",
+    "lib/browser/type_conversions_h.template",
+    "lib/browser/types_cc.template",
+    "lib/browser/types_h.template",
+  ]
+
+  args = [
+    "--protocol",
+    rebase_path(inputs[0], root_build_dir),
+    "--output_dir",
+    rebase_path(target_gen_dir) + "/public/domains",
+  ]
+}
+
 static_library("headless_lib") {
   sources = [
+    "$target_gen_dir/public/domains/accessibility.cc",
+    "$target_gen_dir/public/domains/accessibility.h",
+    "$target_gen_dir/public/domains/animation.cc",
+    "$target_gen_dir/public/domains/animation.h",
+    "$target_gen_dir/public/domains/application_cache.cc",
+    "$target_gen_dir/public/domains/application_cache.h",
+    "$target_gen_dir/public/domains/cache_storage.cc",
+    "$target_gen_dir/public/domains/cache_storage.h",
+    "$target_gen_dir/public/domains/console.cc",
+    "$target_gen_dir/public/domains/console.h",
+    "$target_gen_dir/public/domains/css.cc",
+    "$target_gen_dir/public/domains/css.h",
+    "$target_gen_dir/public/domains/database.cc",
+    "$target_gen_dir/public/domains/database.h",
+    "$target_gen_dir/public/domains/debugger.cc",
+    "$target_gen_dir/public/domains/debugger.h",
+    "$target_gen_dir/public/domains/device_orientation.cc",
+    "$target_gen_dir/public/domains/device_orientation.h",
+    "$target_gen_dir/public/domains/dom.cc",
+    "$target_gen_dir/public/domains/dom.h",
+    "$target_gen_dir/public/domains/dom_debugger.cc",
+    "$target_gen_dir/public/domains/dom_debugger.h",
+    "$target_gen_dir/public/domains/dom_storage.cc",
+    "$target_gen_dir/public/domains/dom_storage.h",
+    "$target_gen_dir/public/domains/emulation.cc",
+    "$target_gen_dir/public/domains/emulation.h",
+    "$target_gen_dir/public/domains/heap_profiler.cc",
+    "$target_gen_dir/public/domains/heap_profiler.h",
+    "$target_gen_dir/public/domains/indexeddb.cc",
+    "$target_gen_dir/public/domains/indexeddb.h",
+    "$target_gen_dir/public/domains/input.cc",
+    "$target_gen_dir/public/domains/input.h",
+    "$target_gen_dir/public/domains/inspector.cc",
+    "$target_gen_dir/public/domains/inspector.h",
+    "$target_gen_dir/public/domains/io.cc",
+    "$target_gen_dir/public/domains/io.h",
+    "$target_gen_dir/public/domains/layer_tree.cc",
+    "$target_gen_dir/public/domains/layer_tree.h",
+    "$target_gen_dir/public/domains/memory.cc",
+    "$target_gen_dir/public/domains/memory.h",
+    "$target_gen_dir/public/domains/network.cc",
+    "$target_gen_dir/public/domains/network.h",
+    "$target_gen_dir/public/domains/page.cc",
+    "$target_gen_dir/public/domains/page.h",
+    "$target_gen_dir/public/domains/profiler.cc",
+    "$target_gen_dir/public/domains/profiler.h",
+    "$target_gen_dir/public/domains/rendering.cc",
+    "$target_gen_dir/public/domains/rendering.h",
+    "$target_gen_dir/public/domains/runtime.cc",
+    "$target_gen_dir/public/domains/runtime.h",
+    "$target_gen_dir/public/domains/security.cc",
+    "$target_gen_dir/public/domains/security.h",
+    "$target_gen_dir/public/domains/service_worker.cc",
+    "$target_gen_dir/public/domains/service_worker.h",
+    "$target_gen_dir/public/domains/tracing.cc",
+    "$target_gen_dir/public/domains/tracing.h",
+    "$target_gen_dir/public/domains/type_conversions.h",
+    "$target_gen_dir/public/domains/types.cc",
+    "$target_gen_dir/public/domains/types.h",
+    "$target_gen_dir/public/domains/worker.cc",
+    "$target_gen_dir/public/domains/worker.h",
     "lib/browser/headless_browser_context.cc",
     "lib/browser/headless_browser_context.h",
     "lib/browser/headless_browser_impl.cc",
@@ -66,6 +214,8 @@
     "lib/browser/headless_content_browser_client.h",
     "lib/browser/headless_devtools.cc",
     "lib/browser/headless_devtools.h",
+    "lib/browser/headless_devtools_client_impl.cc",
+    "lib/browser/headless_devtools_client_impl.h",
     "lib/browser/headless_screen.cc",
     "lib/browser/headless_screen.h",
     "lib/browser/headless_url_request_context_getter.cc",
@@ -82,14 +232,19 @@
     "lib/utility/headless_content_utility_client.h",
     "public/headless_browser.cc",
     "public/headless_browser.h",
+    "public/headless_devtools_client.h",
+    "public/headless_devtools_host.h",
+    "public/headless_devtools_target.h",
     "public/headless_export.h",
     "public/headless_web_contents.h",
+    "public/internal/message_dispatcher.h",
+    "public/internal/value_conversions.h",
     "public/util/error_reporter.cc",
     "public/util/error_reporter.h",
-    "public/util/maybe.h",
   ]
 
   deps = [
+    ":gen_devtools_client_api",
     ":pak",
     "//base",
     "//components/devtools_http_handler",
@@ -112,6 +267,7 @@
   testonly = true
 
   deps = [
+    ":client_api_generator_tests",
     ":headless_browsertests",
     ":headless_unittests",
   ]
@@ -119,8 +275,8 @@
 
 test("headless_unittests") {
   sources = [
+    "public/domains/types_unittest.cc",
     "public/util/error_reporter_unittest.cc",
-    "public/util/maybe_unittest.cc",
   ]
 
   deps = [
@@ -131,9 +287,27 @@
   ]
 }
 
+action("client_api_generator_tests") {
+  _stamp = "$target_gen_dir/client_api_generator_unittests.stamp"
+  inputs = [
+    "lib/browser/client_api_generator.py",
+    "lib/browser/client_api_generator_unittest.py",
+  ]
+  outputs = [
+    _stamp,
+  ]
+
+  script = "lib/browser/client_api_generator_unittest.py"
+  args = [
+    "--stamp",
+    rebase_path(_stamp, root_build_dir),
+  ]
+}
+
 test("headless_browsertests") {
   sources = [
     "lib/headless_browser_browsertest.cc",
+    "lib/headless_devtools_client_browsertest.cc",
     "lib/headless_web_contents_browsertest.cc",
     "test/headless_browser_test.cc",
     "test/headless_browser_test.h",
diff --git a/headless/README.md b/headless/README.md
index be67643..9e3c7b0 100644
--- a/headless/README.md
+++ b/headless/README.md
@@ -55,10 +55,14 @@
   - `SetProxyServer` - Configures an HTTP/HTTPS proxy server to be used for
     accessing the network.
 
-## Client API
+## Client/DevTools API
 
 The headless client API is used to drive the browser and interact with loaded
 web pages. Its main classes are:
 
 - `HeadlessBrowser` - Represents the global headless browser instance.
 - `HeadlessWebContents` - Represents a single "tab" within the browser.
+- `HeadlessDevToolsClient` - Provides a C++ interface for inspecting and
+  controlling a tab. The API functions corresponds to [DevTools commands](https://developer.chrome.com/devtools/docs/debugger-protocol).
+  See the [client API documentation](https://docs.google.com/document/d/1rlqcp8nk-ZQvldNJWdbaMbwfDbJoOXvahPCDoPGOwhQ/edit#)
+  for more information.
diff --git a/headless/app/headless_shell.cc b/headless/app/headless_shell.cc
index 1031dbd..127c97b 100644
--- a/headless/app/headless_shell.cc
+++ b/headless/app/headless_shell.cc
@@ -13,13 +13,18 @@
 #include "base/strings/string_number_conversions.h"
 #include "content/public/common/content_switches.h"
 #include "headless/app/headless_shell_switches.h"
+#include "headless/public/domains/page.h"
 #include "headless/public/headless_browser.h"
+#include "headless/public/headless_devtools_client.h"
+#include "headless/public/headless_devtools_target.h"
 #include "headless/public/headless_web_contents.h"
 #include "net/base/ip_address.h"
 #include "ui/gfx/geometry/size.h"
 
 using headless::HeadlessBrowser;
+using headless::HeadlessDevToolsClient;
 using headless::HeadlessWebContents;
+namespace page = headless::page;
 
 namespace {
 // Address where to listen to incoming DevTools connections.
@@ -29,10 +34,14 @@
 // A sample application which demonstrates the use of the headless API.
 class HeadlessShell : public HeadlessWebContents::Observer {
  public:
-  HeadlessShell() : browser_(nullptr) {}
-  ~HeadlessShell() override {
-    if (web_contents_)
-      web_contents_->RemoveObserver(this);
+  HeadlessShell()
+      : browser_(nullptr), devtools_client_(HeadlessDevToolsClient::Create()) {}
+  ~HeadlessShell() override {}
+
+  void DevToolsTargetReady() override {
+    if (!RemoteDebuggingEnabled())
+      web_contents_->GetDevToolsTarget()->AttachClient(devtools_client_.get());
+    // TODO(skyostil): Implement more features to demonstrate the devtools API.
   }
 
   void OnStart(HeadlessBrowser* browser) {
@@ -58,9 +67,9 @@
   }
 
   void ShutdownIfNeeded() {
-    const base::CommandLine& command_line =
-        *base::CommandLine::ForCurrentProcess();
-    if (!command_line.HasSwitch(switches::kRemoteDebuggingPort)) {
+    if (!RemoteDebuggingEnabled()) {
+      web_contents_->GetDevToolsTarget()->DetachClient(devtools_client_.get());
+      web_contents_->RemoveObserver(this);
       web_contents_ = nullptr;
       browser_->Shutdown();
     }
@@ -71,8 +80,15 @@
     ShutdownIfNeeded();
   }
 
+  bool RemoteDebuggingEnabled() const {
+    const base::CommandLine& command_line =
+        *base::CommandLine::ForCurrentProcess();
+    return command_line.HasSwitch(switches::kRemoteDebuggingPort);
+  }
+
  private:
   HeadlessBrowser* browser_;  // Not owned.
+  std::unique_ptr<HeadlessDevToolsClient> devtools_client_;
   std::unique_ptr<HeadlessWebContents> web_contents_;
 
   DISALLOW_COPY_AND_ASSIGN(HeadlessShell);
diff --git a/headless/lib/browser/client_api_generator.py b/headless/lib/browser/client_api_generator.py
new file mode 100644
index 0000000..3fcef260
--- /dev/null
+++ b/headless/lib/browser/client_api_generator.py
@@ -0,0 +1,372 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import os.path
+import sys
+import re
+try:
+  import json
+except ImportError:
+  import simplejson as json
+
+# Path handling for libraries and templates
+# Paths have to be normalized because Jinja uses the exact template path to
+# determine the hash used in the cache filename, and we need a pre-caching step
+# to be concurrency-safe. Use absolute path because __file__ is absolute if
+# module is imported, and relative if executed directly.
+# If paths differ between pre-caching and individual file compilation, the cache
+# is regenerated, which causes a race condition and breaks concurrent build,
+# since some compile processes will try to read the partially written cache.
+module_path, module_filename = os.path.split(os.path.realpath(__file__))
+third_party_dir = os.path.normpath(os.path.join(
+    module_path, os.pardir, os.pardir, os.pardir, 'third_party'))
+templates_dir = module_path
+
+# jinja2 is in chromium's third_party directory.
+# Insert at 1 so at front to override system libraries, and
+# after path[0] == invoking script dir
+sys.path.insert(1, third_party_dir)
+import jinja2
+
+
+def ParseArguments(args):
+  """Parses command line arguments and returns a (json_api, output_dir) tuple.
+  """
+  cmdline_parser = argparse.ArgumentParser()
+  cmdline_parser.add_argument('--protocol', required=True)
+  cmdline_parser.add_argument('--output_dir', required=True)
+
+  args = cmdline_parser.parse_args(args)
+  with open(args.protocol, 'r') as f:
+    return json.load(f), args.output_dir
+
+
+def ToTitleCase(name):
+  return name[:1].upper() + name[1:]
+
+
+def DashToCamelCase(word):
+  return ''.join(ToTitleCase(x) for x in word.split('-'))
+
+
+def CamelCaseToHackerStyle(name):
+  # Do two passes to insert '_' chars to deal with overlapping matches (e.g.,
+  # 'LoLoLoL').
+  name = re.sub(r'([^_])([A-Z][a-z]+?)', r'\1_\2', name)
+  name = re.sub(r'([^_])([A-Z][a-z]+?)', r'\1_\2', name)
+  return name.lower()
+
+
+def MangleEnum(value):
+  # Rename NULL enumeration values to avoid a clash with the actual NULL.
+  return 'NONE' if value == 'NULL' else value
+
+
+def InitializeJinjaEnv(cache_dir):
+  jinja_env = jinja2.Environment(
+      loader=jinja2.FileSystemLoader(templates_dir),
+      # Bytecode cache is not concurrency-safe unless pre-cached:
+      # if pre-cached this is read-only, but writing creates a race condition.
+      bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir),
+      keep_trailing_newline=True,  # Newline-terminate generated files.
+      lstrip_blocks=True,  # So we can indent control flow tags.
+      trim_blocks=True)
+  jinja_env.filters.update({
+    'to_title_case': ToTitleCase,
+    'dash_to_camelcase': DashToCamelCase,
+    'camelcase_to_hacker_style': CamelCaseToHackerStyle,
+    'mangle_enum': MangleEnum,
+  })
+  jinja_env.add_extension('jinja2.ext.loopcontrols')
+  return jinja_env
+
+
+def PatchFullQualifiedRefs(json_api):
+  def PatchFullQualifiedRefsInDomain(json, domain_name):
+    if isinstance(json, list):
+      for item in json:
+        PatchFullQualifiedRefsInDomain(item, domain_name)
+
+    if not isinstance(json, dict):
+      return
+    for key in json:
+      if key != '$ref':
+        PatchFullQualifiedRefsInDomain(json[key], domain_name)
+        continue
+      if not '.' in json['$ref']:
+        json['$ref'] = domain_name + '.' + json['$ref']
+
+  for domain in json_api['domains']:
+    PatchFullQualifiedRefsInDomain(domain, domain['domain'])
+
+
+def CreateUserTypeDefinition(domain, type):
+  namespace = CamelCaseToHackerStyle(domain['domain'])
+  return {
+    'return_type': 'std::unique_ptr<headless::%s::%s>' % (
+        namespace, type['id']),
+    'pass_type': 'std::unique_ptr<headless::%s::%s>' % (namespace, type['id']),
+    'to_raw_type': '*%s',
+    'to_raw_return_type': '%s.get()',
+    'to_pass_type': 'std::move(%s)',
+    'type': 'std::unique_ptr<headless::%s::%s>' % (namespace, type['id']),
+    'raw_type': 'headless::%s::%s' % (namespace, type['id']),
+    'raw_pass_type': 'headless::%s::%s*' % (namespace, type['id']),
+    'raw_return_type': 'headless::%s::%s*' % (namespace, type['id']),
+  }
+
+
+def CreateEnumTypeDefinition(domain_name, type):
+  namespace = CamelCaseToHackerStyle(domain_name)
+  return {
+    'return_type': 'headless::%s::%s' % (namespace, type['id']),
+    'pass_type': 'headless::%s::%s' % (namespace, type['id']),
+    'to_raw_type': '%s',
+    'to_raw_return_type': '%s',
+    'to_pass_type': '%s',
+    'type': 'headless::%s::%s' % (namespace, type['id']),
+    'raw_type': 'headless::%s::%s' % (namespace, type['id']),
+    'raw_pass_type': 'headless::%s::%s' % (namespace, type['id']),
+    'raw_return_type': 'headless::%s::%s' % (namespace, type['id']),
+  }
+
+
+def CreateObjectTypeDefinition():
+  return {
+    'return_type': 'std::unique_ptr<base::DictionaryValue>',
+    'pass_type': 'std::unique_ptr<base::DictionaryValue>',
+    'to_raw_type': '*%s',
+    'to_raw_return_type': '%s.get()',
+    'to_pass_type': 'std::move(%s)',
+    'type': 'std::unique_ptr<base::DictionaryValue>',
+    'raw_type': 'base::DictionaryValue',
+    'raw_pass_type': 'base::DictionaryValue*',
+    'raw_return_type': 'base::DictionaryValue*',
+  }
+
+
+def WrapObjectTypeDefinition(type):
+  id = type.get('id', 'base::Value')
+  return {
+    'return_type': 'std::unique_ptr<%s>' % id,
+    'pass_type': 'std::unique_ptr<%s>' % id,
+    'to_raw_type': '*%s',
+    'to_raw_return_type': '%s.get()',
+    'to_pass_type': 'std::move(%s)',
+    'type': 'std::unique_ptr<%s>' % id,
+    'raw_type': id,
+    'raw_pass_type': '%s*' % id,
+    'raw_return_type': '%s*' % id,
+  }
+
+
+def CreateAnyTypeDefinition():
+  return {
+    'return_type': 'std::unique_ptr<base::Value>',
+    'pass_type': 'std::unique_ptr<base::Value>',
+    'to_raw_type': '*%s',
+    'to_raw_return_type': '%s.get()',
+    'to_pass_type': 'std::move(%s)',
+    'type': 'std::unique_ptr<base::Value>',
+    'raw_type': 'base::Value',
+    'raw_pass_type': 'base::Value*',
+    'raw_return_type': 'base::Value*',
+  }
+
+
+def CreateStringTypeDefinition(domain):
+  return {
+    'return_type': 'std::string',
+    'pass_type': 'const std::string&',
+    'to_pass_type': '%s',
+    'to_raw_type': '%s',
+    'to_raw_return_type': '%s',
+    'type': 'std::string',
+    'raw_type': 'std::string',
+    'raw_pass_type': 'const std::string&',
+    'raw_return_type': 'std::string',
+  }
+
+
+def CreatePrimitiveTypeDefinition(type):
+  typedefs = {
+    'number': 'double',
+    'integer': 'int',
+    'boolean': 'bool',
+    'string': 'std::string',
+  }
+  return {
+    'return_type': typedefs[type],
+    'pass_type': typedefs[type],
+    'to_pass_type': '%s',
+    'to_raw_type': '%s',
+    'to_raw_return_type': '%s',
+    'type': typedefs[type],
+    'raw_type': typedefs[type],
+    'raw_pass_type': typedefs[type],
+    'raw_return_type': typedefs[type],
+  }
+
+
+type_definitions = {}
+type_definitions['number'] = CreatePrimitiveTypeDefinition('number')
+type_definitions['integer'] = CreatePrimitiveTypeDefinition('integer')
+type_definitions['boolean'] = CreatePrimitiveTypeDefinition('boolean')
+type_definitions['string'] = CreatePrimitiveTypeDefinition('string')
+type_definitions['object'] = CreateObjectTypeDefinition()
+type_definitions['any'] = CreateAnyTypeDefinition()
+
+
+def WrapArrayDefinition(type):
+  return {
+    'return_type': 'std::vector<%s>' % type['type'],
+    'pass_type': 'std::vector<%s>' % type['type'],
+    'to_raw_type': '%s',
+    'to_raw_return_type': '&%s',
+    'to_pass_type': 'std::move(%s)',
+    'type': 'std::vector<%s>' % type['type'],
+    'raw_type': 'std::vector<%s>' % type['type'],
+    'raw_pass_type': 'std::vector<%s>*' % type['type'],
+    'raw_return_type': 'std::vector<%s>*' % type['type'],
+  }
+
+
+def CreateTypeDefinitions(json_api):
+  for domain in json_api['domains']:
+    if not ('types' in domain):
+      continue
+    for type in domain['types']:
+      if type['type'] == 'object':
+        if 'properties' in type:
+          type_definitions[domain['domain'] + '.' + type['id']] = (
+              CreateUserTypeDefinition(domain, type))
+        else:
+          type_definitions[domain['domain'] + '.' + type['id']] = (
+              CreateObjectTypeDefinition())
+      elif type['type'] == 'array':
+        items_type = type['items']['type']
+        type_definitions[domain['domain'] + '.' + type['id']] = (
+            WrapArrayDefinition(type_definitions[items_type]))
+      elif 'enum' in type:
+        type_definitions[domain['domain'] + '.' + type['id']] = (
+            CreateEnumTypeDefinition(domain['domain'], type))
+        type['$ref'] = domain['domain'] + '.' + type['id']
+      elif type['type'] == 'any':
+        type_definitions[domain['domain'] + '.' + type['id']] = (
+            CreateAnyTypeDefinition())
+      else:
+        type_definitions[domain['domain'] + '.' + type['id']] = (
+            CreatePrimitiveTypeDefinition(type['type']))
+
+
+def TypeDefinition(name):
+  return type_definitions[name]
+
+
+def ResolveType(property):
+  if '$ref' in property:
+    return type_definitions[property['$ref']]
+  elif property['type'] == 'object':
+    return WrapObjectTypeDefinition(property)
+  elif property['type'] == 'array':
+    return WrapArrayDefinition(ResolveType(property['items']))
+  return type_definitions[property['type']]
+
+
+def JoinArrays(dict, keys):
+  result = []
+  for key in keys:
+    if key in dict:
+      result += dict[key]
+  return result
+
+
+def SynthesizeEnumType(domain, owner, type):
+  type['id'] = ToTitleCase(owner) + ToTitleCase(type['name'])
+  type_definitions[domain['domain'] + '.' + type['id']] = (
+      CreateEnumTypeDefinition(domain['domain'], type))
+  type['$ref'] = domain['domain'] + '.' + type['id']
+  domain['types'].append(type)
+
+
+def SynthesizeCommandTypes(json_api):
+  """Generate types for command parameters, return values and enum
+     properties."""
+  for domain in json_api['domains']:
+    if not 'types' in domain:
+      domain['types'] = []
+    for type in domain['types']:
+      if type['type'] == 'object':
+        for property in type.get('properties', []):
+          if 'enum' in property and not '$ref' in property:
+            SynthesizeEnumType(domain, type['id'], property)
+
+    for command in domain.get('commands', []):
+      if 'parameters' in command:
+        for parameter in command['parameters']:
+          if 'enum' in parameter and not '$ref' in parameter:
+            SynthesizeEnumType(domain, command['name'], parameter)
+        parameters_type = {
+          'id': ToTitleCase(command['name']) + 'Params',
+          'type': 'object',
+          'description': 'Parameters for the %s command.' % ToTitleCase(
+              command['name']),
+          'properties': command['parameters']
+        }
+        domain['types'].append(parameters_type)
+      if 'returns' in command:
+        for parameter in command['returns']:
+          if 'enum' in parameter and not '$ref' in parameter:
+            SynthesizeEnumType(domain, command['name'], parameter)
+        result_type = {
+          'id': ToTitleCase(command['name']) + 'Result',
+          'type': 'object',
+          'description': 'Result for the %s command.' % ToTitleCase(
+              command['name']),
+          'properties': command['returns']
+        }
+        domain['types'].append(result_type)
+
+
+def Generate(jinja_env, output_dirname, json_api, class_name, file_types):
+  template_context = {
+    'api': json_api,
+    'join_arrays': JoinArrays,
+    'resolve_type': ResolveType,
+    'type_definition': TypeDefinition,
+  }
+  for file_type in file_types:
+    template = jinja_env.get_template('/%s_%s.template' % (
+        class_name, file_type))
+    output_file = '%s/%s.%s' % (output_dirname, class_name, file_type)
+    with open(output_file, 'w') as f:
+      f.write(template.render(template_context))
+
+
+def GenerateDomains(jinja_env, output_dirname, json_api, class_name,
+                    file_types):
+  for file_type in file_types:
+    template = jinja_env.get_template('/%s_%s.template' % (
+        class_name, file_type))
+    for domain in json_api['domains']:
+      template_context = {
+        'domain': domain,
+        'resolve_type': ResolveType,
+      }
+      domain_name = CamelCaseToHackerStyle(domain['domain'])
+      output_file = '%s/%s.%s' % (output_dirname, domain_name, file_type)
+      with open(output_file, 'w') as f:
+        f.write(template.render(template_context))
+
+
+if __name__ == '__main__':
+  json_api, output_dirname = ParseArguments(sys.argv[1:])
+  jinja_env = InitializeJinjaEnv(output_dirname)
+  SynthesizeCommandTypes(json_api)
+  PatchFullQualifiedRefs(json_api)
+  CreateTypeDefinitions(json_api)
+  Generate(jinja_env, output_dirname, json_api, 'types', ['cc', 'h'])
+  Generate(jinja_env, output_dirname, json_api, 'type_conversions', ['h'])
+  GenerateDomains(jinja_env, output_dirname, json_api, 'domain', ['cc', 'h'])
diff --git a/headless/lib/browser/client_api_generator_unittest.py b/headless/lib/browser/client_api_generator_unittest.py
new file mode 100644
index 0000000..f3609d49
--- /dev/null
+++ b/headless/lib/browser/client_api_generator_unittest.py
@@ -0,0 +1,386 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import client_api_generator
+import shutil
+import sys
+import tempfile
+import unittest
+
+
+class ClientApiGeneratorTest(unittest.TestCase):
+
+  def test_ArgumentParsing(self):
+    with tempfile.NamedTemporaryFile() as f:
+      f.write('{"foo": true}')
+      f.flush()
+      json_api, output_dir = client_api_generator.ParseArguments([
+          '--protocol', f.name, '--output_dir', 'out'])
+      self.assertEqual({'foo': True}, json_api)
+      self.assertEqual('out', output_dir)
+
+  def test_ToTitleCase(self):
+    self.assertEqual(client_api_generator.ToTitleCase('fooBar'), 'FooBar')
+
+  def test_DashToCamelCase(self):
+    self.assertEqual(client_api_generator.DashToCamelCase('foo-bar'), 'FooBar')
+    self.assertEqual(client_api_generator.DashToCamelCase('foo-'), 'Foo')
+    self.assertEqual(client_api_generator.DashToCamelCase('-bar'), 'Bar')
+
+  def test_CamelCaseToHackerStyle(self):
+    self.assertEqual(client_api_generator.CamelCaseToHackerStyle('FooBar'),
+                     'foo_bar')
+    self.assertEqual(client_api_generator.CamelCaseToHackerStyle('LoLoLoL'),
+                     'lo_lo_lol')
+
+  def test_MangleEnum(self):
+    self.assertEqual(client_api_generator.MangleEnum('FOO'), 'FOO')
+    self.assertEqual(client_api_generator.MangleEnum('NULL'), 'NONE')
+
+  def test_PatchFullQualifiedRefs(self):
+    json_api = {
+      'domains': [
+        {
+          'domain': 'domain0',
+          '$ref': 'reference',
+        },
+        {
+          'domain': 'domain1',
+          '$ref': 'reference',
+          'more': [{'$ref': 'domain0.thing'}],
+        }
+      ]
+    }
+    expected_json_api = {
+      'domains': [
+        {
+          'domain': 'domain0',
+          '$ref': 'domain0.reference',
+        },
+        {
+          'domain': 'domain1',
+          '$ref': 'domain1.reference',
+          'more': [{'$ref': 'domain0.thing'}],
+        }
+      ]
+    }
+    client_api_generator.PatchFullQualifiedRefs(json_api)
+    self.assertDictEqual(json_api, expected_json_api)
+
+  def test_NumberType(self):
+    json_api = {
+      'domains': [
+        {
+          'domain': 'domain',
+          'types': [
+            {
+              'id': 'TestType',
+              'type': 'number',
+            },
+          ]
+        },
+      ]
+    }
+    client_api_generator.CreateTypeDefinitions(json_api)
+    type = json_api['domains'][0]['types'][0]
+    resolved = client_api_generator.ResolveType(type)
+    self.assertEqual('double', resolved['raw_type'])
+
+  def test_IntegerType(self):
+    json_api = {
+      'domains': [
+        {
+          'domain': 'domain',
+          'types': [
+            {
+              'id': 'TestType',
+              'type': 'integer',
+            },
+          ]
+        },
+      ]
+    }
+    client_api_generator.CreateTypeDefinitions(json_api)
+    type = json_api['domains'][0]['types'][0]
+    resolved = client_api_generator.ResolveType(type)
+    self.assertEqual('int', resolved['raw_type'])
+
+  def test_BooleanType(self):
+    json_api = {
+      'domains': [
+        {
+          'domain': 'domain',
+          'types': [
+            {
+              'id': 'TestType',
+              'type': 'boolean',
+            },
+          ]
+        },
+      ]
+    }
+    client_api_generator.CreateTypeDefinitions(json_api)
+    type = json_api['domains'][0]['types'][0]
+    resolved = client_api_generator.ResolveType(type)
+    self.assertEqual('bool', resolved['raw_type'])
+
+  def test_StringType(self):
+    json_api = {
+      'domains': [
+        {
+          'domain': 'domain',
+          'types': [
+            {
+              'id': 'TestType',
+              'type': 'string',
+            },
+          ]
+        },
+      ]
+    }
+    client_api_generator.CreateTypeDefinitions(json_api)
+    type = json_api['domains'][0]['types'][0]
+    resolved = client_api_generator.ResolveType(type)
+    self.assertEqual('std::string', resolved['raw_type'])
+
+  def test_ObjectType(self):
+    json_api = {
+      'domains': [
+        {
+          'domain': 'domain',
+          'types': [
+            {
+              'id': 'TestType',
+              'type': 'object',
+              'properties': [
+                  {'name': 'p1', 'type': 'number'},
+                  {'name': 'p2', 'type': 'integer'},
+                  {'name': 'p3', 'type': 'boolean'},
+                  {'name': 'p4', 'type': 'string'},
+                  {'name': 'p5', 'type': 'any'},
+                  {'name': 'p6', 'type': 'object', '$ref': 'TestType'},
+              ],
+              'returns': [
+                  {'name': 'r1', 'type': 'number'},
+                  {'name': 'r2', 'type': 'integer'},
+                  {'name': 'r3', 'type': 'boolean'},
+                  {'name': 'r4', 'type': 'string'},
+                  {'name': 'r5', 'type': 'any'},
+                  {'name': 'r6', 'type': 'object', '$ref': 'TestType'},
+              ],
+            },
+          ]
+        },
+      ]
+    }
+    client_api_generator.CreateTypeDefinitions(json_api)
+    type = json_api['domains'][0]['types'][0]
+    resolved = client_api_generator.ResolveType(type)
+    self.assertEqual('TestType', resolved['raw_type'])
+
+  def test_AnyType(self):
+    json_api = {
+      'domains': [
+        {
+          'domain': 'domain',
+          'types': [
+            {
+              'id': 'TestType',
+              'type': 'any',
+            },
+          ]
+        },
+      ]
+    }
+    client_api_generator.CreateTypeDefinitions(json_api)
+    type = json_api['domains'][0]['types'][0]
+    resolved = client_api_generator.ResolveType(type)
+    self.assertEqual('base::Value', resolved['raw_type'])
+
+  def test_ArrayType(self):
+    json_api = {
+      'domains': [
+        {
+          'domain': 'domain',
+          'types': [
+            {
+              'id': 'TestType',
+              'type': 'array',
+              'items': {'type': 'integer'}
+            },
+          ]
+        },
+      ]
+    }
+    client_api_generator.CreateTypeDefinitions(json_api)
+    type = json_api['domains'][0]['types'][0]
+    resolved = client_api_generator.ResolveType(type)
+    self.assertEqual('std::vector<int>', resolved['raw_type'])
+
+  def test_EnumType(self):
+    json_api = {
+      'domains': [
+        {
+          'domain': 'domain',
+          'types': [
+            {
+              'id': 'TestType',
+              'type': 'string',
+              'enum': ['a', 'b', 'c']
+            },
+          ]
+        },
+      ]
+    }
+    client_api_generator.CreateTypeDefinitions(json_api)
+    type = json_api['domains'][0]['types'][0]
+    resolved = client_api_generator.ResolveType(type)
+    self.assertEqual('headless::domain::TestType', resolved['raw_type'])
+
+  def test_SynthesizeCommandTypes(self):
+    json_api = {
+      'domains': [
+        {
+          'domain': 'domain',
+          'commands': [
+            {
+              'name': 'TestCommand',
+              'parameters': [
+                  {'name': 'p1', 'type': 'number'},
+                  {'name': 'p2', 'type': 'integer'},
+                  {'name': 'p3', 'type': 'boolean'},
+                  {'name': 'p4', 'type': 'string'},
+                  {'name': 'p5', 'type': 'any'},
+                  {'name': 'p6', 'type': 'object', '$ref': 'TestType'},
+              ],
+              'returns': [
+                  {'name': 'r1', 'type': 'number'},
+                  {'name': 'r2', 'type': 'integer'},
+                  {'name': 'r3', 'type': 'boolean'},
+                  {'name': 'r4', 'type': 'string'},
+                  {'name': 'r5', 'type': 'any'},
+                  {'name': 'r6', 'type': 'object', '$ref': 'TestType'},
+              ],
+            },
+          ]
+        },
+      ]
+    }
+    expected_types = [
+      {
+        'type': 'object',
+        'id': 'TestCommandParams',
+        'description': 'Parameters for the TestCommand command.',
+        'properties': [
+          {'type': 'number', 'name': 'p1'},
+          {'type': 'integer', 'name': 'p2'},
+          {'type': 'boolean', 'name': 'p3'},
+          {'type': 'string', 'name': 'p4'},
+          {'type': 'any', 'name': 'p5'},
+          {'type': 'object', 'name': 'p6', '$ref': 'TestType'}
+        ],
+      },
+      {
+        'type': 'object',
+        'id': 'TestCommandResult',
+        'description': 'Result for the TestCommand command.',
+        'properties': [
+          {'type': 'number', 'name': 'r1'},
+          {'type': 'integer', 'name': 'r2'},
+          {'type': 'boolean', 'name': 'r3'},
+          {'type': 'string', 'name': 'r4'},
+          {'type': 'any', 'name': 'r5'},
+          {'type': 'object', 'name': 'r6', '$ref': 'TestType'}
+        ],
+      }
+    ]
+    client_api_generator.SynthesizeCommandTypes(json_api)
+    types = json_api['domains'][0]['types']
+    self.assertListEqual(types, expected_types)
+
+  def test_Generate(self):
+    json_api = {
+      'domains': [
+        {
+          'domain': 'domain',
+          'types': [
+            {
+              'id': 'TestType',
+              'type': 'object',
+              'properties': [
+                  {'name': 'p1', 'type': 'number'},
+                  {'name': 'p2', 'type': 'integer'},
+                  {'name': 'p3', 'type': 'boolean'},
+                  {'name': 'p4', 'type': 'string'},
+                  {'name': 'p5', 'type': 'any'},
+                  {'name': 'p6', 'type': 'object', '$ref': 'domain.TestType'},
+              ],
+              'returns': [
+                  {'name': 'r1', 'type': 'number'},
+                  {'name': 'r2', 'type': 'integer'},
+                  {'name': 'r3', 'type': 'boolean'},
+                  {'name': 'r4', 'type': 'string'},
+                  {'name': 'r5', 'type': 'any'},
+                  {'name': 'r6', 'type': 'object', '$ref': 'domain.TestType'},
+              ],
+            },
+          ]
+        },
+      ]
+    }
+    try:
+      dirname = tempfile.mkdtemp()
+      jinja_env = client_api_generator.InitializeJinjaEnv(dirname)
+      client_api_generator.Generate(jinja_env, dirname, json_api, 'types',
+                                    ['cc'])
+      client_api_generator.Generate(jinja_env, dirname, json_api, 'types',
+                                    ['h'])
+      # This is just a smoke test; we don't actually verify the generated output
+      # here.
+    finally:
+      shutil.rmtree(dirname)
+
+  def test_GenerateDomains(self):
+    json_api = {
+      'domains': [
+        {
+          'domain': 'domain0',
+          'types': [
+            {
+              'id': 'TestType',
+              'type': 'object',
+            },
+          ]
+        },
+        {
+          'domain': 'domain1',
+          'types': [
+            {
+              'id': 'TestType',
+              'type': 'object',
+            },
+          ]
+        },
+      ]
+    }
+    try:
+      dirname = tempfile.mkdtemp()
+      jinja_env = client_api_generator.InitializeJinjaEnv(dirname)
+      client_api_generator.GenerateDomains(jinja_env, dirname, json_api,
+                                          'domain', ['cc', 'h'])
+      # This is just a smoke test; we don't actually verify the generated output
+      # here.
+    finally:
+      shutil.rmtree(dirname)
+
+
+if __name__ == '__main__':
+  cmdline_parser = argparse.ArgumentParser()
+  cmdline_parser.add_argument('--stamp')
+  args = cmdline_parser.parse_args()
+  unittest.main(verbosity=2, exit=False, argv=sys.argv[:1])
+  if args.stamp:
+    with open(args.stamp, 'a') as f:
+      pass
diff --git a/headless/lib/browser/domain_cc.template b/headless/lib/browser/domain_cc.template
new file mode 100644
index 0000000..9a99bde
--- /dev/null
+++ b/headless/lib/browser/domain_cc.template
@@ -0,0 +1,86 @@
+// This file is generated
+
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "headless/public/domains/{{domain.domain | camelcase_to_hacker_style}}.h"
+
+#include "base/bind.h"
+
+namespace headless {
+
+namespace {{domain.domain | camelcase_to_hacker_style}} {
+
+Domain::Domain(internal::MessageDispatcher* dispatcher) : dispatcher_(dispatcher) {}
+
+Domain::~Domain() {}
+  {% for command in domain.commands %}
+    {# Skip redirected commands. #}
+    {% if "redirect" in command %}{% continue %}{% endif %}
+
+    {% set method_name = command.name | to_title_case %}
+    {% if "parameters" in command and "returns" in command %}
+void Domain::{{method_name}}(std::unique_ptr<{{method_name}}Params> params, base::Callback<void(std::unique_ptr<{{method_name}}Result>)> callback) {
+  dispatcher_->SendMessage("{{domain.domain}}.{{command.name}}", params->Serialize(), base::Bind(&Domain::Handle{{method_name}}Response, callback));
+    {% elif "parameters" in command %}
+void Domain::{{method_name}}(std::unique_ptr<{{method_name}}Params> params, base::Callback<void()> callback) {
+  dispatcher_->SendMessage("{{domain.domain}}.{{command.name}}", params->Serialize(), std::move(callback));
+    {% elif "returns" in command %}
+void Domain::{{method_name}}(base::Callback<void(std::unique_ptr<{{method_name}}Result>)> callback) {
+  dispatcher_->SendMessage("{{domain.domain}}.{{command.name}}", base::Bind(&Domain::Handle{{method_name}}Response, std::move(callback)));
+    {% else %}
+void Domain::{{method_name}}(base::Callback<void()> callback) {
+  dispatcher_->SendMessage("{{domain.domain}}.{{command.name}}", std::move(callback));
+    {% endif %}
+}
+    {# Generate convenience methods that take the required parameters directly. #}
+    {% if not "parameters" in command %}{% continue %}{% endif %}
+
+void Domain::{{method_name}}({##}
+    {% for parameter in command.parameters -%}
+        {% if parameter.get("optional", False) -%}
+          {% break %}
+        {% endif %}
+        {% if not loop.first %}, {% endif %}
+{{resolve_type(parameter).pass_type}} {{parameter.name | camelcase_to_hacker_style -}}
+    {% endfor %}
+    {% if "parameters" in command and not command.parameters[0].get("optional", False) %}, {% endif %}{# -#}
+    {% if "returns" in command -%}
+      base::Callback<void(std::unique_ptr<{{method_name}}Result>)> callback{##}
+    {% else -%}
+      base::Callback<void()> callback{##}
+    {% endif %}) {
+    {# Build the parameters object. #}
+  std::unique_ptr<{{method_name}}Params> params = {{method_name}}Params::Builder()
+    {% for parameter in command.parameters -%}
+        {% if parameter.get("optional", False) -%}
+          {% break %}
+        {% endif %}
+      .Set{{parameter.name | to_title_case}}(std::move({{parameter.name | camelcase_to_hacker_style}}))
+    {% endfor %}
+      .Build();
+    {# Send the message. #}
+  {{method_name}}(std::move(params), std::move(callback));
+}
+  {% endfor %}
+
+{# Generate response handlers for commands that need them. #}
+{% for command in domain.commands %}
+  {% if not "returns" in command %}{% continue %}{% endif %}
+  {% set method_name = command.name | to_title_case %}
+
+// static
+void Domain::Handle{{method_name}}Response(base::Callback<void(std::unique_ptr<{{method_name}}Result>)> callback, const base::Value& response) {
+  if (callback.is_null())
+    return;
+  ErrorReporter errors;
+  std::unique_ptr<{{method_name}}Result> result = {{method_name}}Result::Parse(response, &errors);
+  DCHECK(!errors.HasErrors());
+  callback.Run(std::move(result));
+}
+{% endfor %}
+
+}  // namespace {{domain.domain | camelcase_to_hacker_style}}
+
+} // namespace headless
diff --git a/headless/lib/browser/domain_h.template b/headless/lib/browser/domain_h.template
new file mode 100644
index 0000000..0cd03c3
--- /dev/null
+++ b/headless/lib/browser/domain_h.template
@@ -0,0 +1,77 @@
+// This file is generated
+
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef HEADLESS_PUBLIC_DOMAINS_{{domain.domain | camelcase_to_hacker_style | upper}}_H_
+#define HEADLESS_PUBLIC_DOMAINS_{{domain.domain | camelcase_to_hacker_style | upper}}_H_
+
+#include "base/callback.h"
+#include "base/values.h"
+#include "headless/public/domains/types.h"
+#include "headless/public/headless_export.h"
+#include "headless/public/internal/message_dispatcher.h"
+
+namespace headless {
+namespace {{domain.domain | camelcase_to_hacker_style}} {
+
+{% if domain.description %}
+// {{domain.description}}
+{% endif %}
+class HEADLESS_EXPORT Domain {
+ public:
+  Domain(internal::MessageDispatcher* dispatcher);
+  ~Domain();
+
+  {# Generate methods for each command. #}
+  {% for command in domain.commands %}
+    {# Skip redirected commands. #}
+    {% if "redirect" in command %}{% continue %}{% endif %}
+    {% set method_name = command.name | to_title_case %}
+    {% if command.description %}
+  // {{ command.description }}
+    {% endif %}
+    {% if "parameters" in command and "returns" in command %}
+  void {{method_name}}(std::unique_ptr<{{method_name}}Params> params, base::Callback<void(std::unique_ptr<{{method_name}}Result>)> callback = base::Callback<void(std::unique_ptr<{{method_name}}Result>)>());
+    {% elif "parameters" in command %}
+  void {{method_name}}(std::unique_ptr<{{method_name}}Params> params, base::Callback<void()> callback = base::Callback<void()>());
+    {% elif "returns" in command %}
+  void {{method_name}}(base::Callback<void(std::unique_ptr<{{method_name}}Result>)> callback = base::Callback<void(std::unique_ptr<{{method_name}}Result>)>());
+    {% else %}
+  void {{method_name}}(base::Callback<void()> callback = base::Callback<void()>());
+    {% endif %}
+    {# Generate convenience methods that take the required parameters directly. #}
+    {% if not "parameters" in command %}{% continue %}{% endif %}
+  void {{method_name}}({##}
+  {% for parameter in command.parameters -%}
+      {% if parameter.get("optional", False) -%}
+        {% break %}
+      {% endif %}
+      {% if not loop.first %}, {% endif %}
+{{resolve_type(parameter).pass_type}} {{parameter.name | camelcase_to_hacker_style -}}
+    {% endfor %}
+    {% if "parameters" in command and not command.parameters[0].get("optional", False) %}, {% endif %}{# -#}
+    {% if "returns" in command -%}
+      base::Callback<void(std::unique_ptr<{{method_name}}Result>)> callback = base::Callback<void(std::unique_ptr<{{method_name}}Result>)>(){##}
+    {% else -%}
+      base::Callback<void()> callback = base::Callback<void()>(){##}
+    {% endif %});
+  {% endfor %}
+ private:
+  {# Generate response handlers for commands that need them. #}
+  {% for command in domain.commands %}
+    {% if not "returns" in command %}{% continue %}{% endif %}
+    {% set method_name = command.name | to_title_case %}
+  static void Handle{{method_name}}Response(base::Callback<void(std::unique_ptr<{{method_name}}Result>)> callback, const base::Value& response);
+  {% endfor %}
+
+  internal::MessageDispatcher* dispatcher_;  // Not owned.
+
+  DISALLOW_COPY_AND_ASSIGN(Domain);
+};
+
+}  // namespace {{domain.domain | camelcase_to_hacker_style}}
+}  // namespace headless
+
+#endif  // HEADLESS_PUBLIC_DOMAINS_{{domain.domain | camelcase_to_hacker_style | upper}}_H_
diff --git a/headless/lib/browser/headless_devtools_client_impl.cc b/headless/lib/browser/headless_devtools_client_impl.cc
new file mode 100644
index 0000000..8ce84533
--- /dev/null
+++ b/headless/lib/browser/headless_devtools_client_impl.cc
@@ -0,0 +1,308 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "headless/lib/browser/headless_devtools_client_impl.h"
+
+#include <memory>
+
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/memory/ptr_util.h"
+#include "base/values.h"
+#include "content/public/browser/devtools_agent_host.h"
+
+namespace headless {
+
+// static
+std::unique_ptr<HeadlessDevToolsClient> HeadlessDevToolsClient::Create() {
+  return base::WrapUnique(new HeadlessDevToolsClientImpl());
+}
+
+// static
+HeadlessDevToolsClientImpl* HeadlessDevToolsClientImpl::From(
+    HeadlessDevToolsClient* client) {
+  // This downcast is safe because there is only one implementation of
+  // HeadlessDevToolsClient.
+  return static_cast<HeadlessDevToolsClientImpl*>(client);
+}
+
+HeadlessDevToolsClientImpl::HeadlessDevToolsClientImpl()
+    : agent_host_(nullptr),
+      next_message_id_(0),
+      accessibility_domain_(this),
+      animation_domain_(this),
+      application_cache_domain_(this),
+      cache_storage_domain_(this),
+      console_domain_(this),
+      css_domain_(this),
+      database_domain_(this),
+      debugger_domain_(this),
+      device_orientation_domain_(this),
+      dom_debugger_domain_(this),
+      dom_domain_(this),
+      dom_storage_domain_(this),
+      emulation_domain_(this),
+      heap_profiler_domain_(this),
+      indexeddb_domain_(this),
+      input_domain_(this),
+      inspector_domain_(this),
+      io_domain_(this),
+      layer_tree_domain_(this),
+      memory_domain_(this),
+      network_domain_(this),
+      page_domain_(this),
+      profiler_domain_(this),
+      rendering_domain_(this),
+      runtime_domain_(this),
+      security_domain_(this),
+      service_worker_domain_(this),
+      tracing_domain_(this),
+      worker_domain_(this) {}
+
+HeadlessDevToolsClientImpl::~HeadlessDevToolsClientImpl() {}
+
+void HeadlessDevToolsClientImpl::AttachToHost(
+    content::DevToolsAgentHost* agent_host) {
+  DCHECK(!agent_host_);
+  agent_host_ = agent_host;
+  agent_host_->AttachClient(this);
+}
+
+void HeadlessDevToolsClientImpl::DetachFromHost(
+    content::DevToolsAgentHost* agent_host) {
+  DCHECK_EQ(agent_host_, agent_host);
+  agent_host_->DetachClient();
+  agent_host_ = nullptr;
+  pending_messages_.clear();
+}
+
+void HeadlessDevToolsClientImpl::DispatchProtocolMessage(
+    content::DevToolsAgentHost* agent_host,
+    const std::string& json_message) {
+  DCHECK_EQ(agent_host_, agent_host);
+  std::unique_ptr<base::Value> message =
+      base::JSONReader::Read(json_message, base::JSON_PARSE_RFC);
+  base::DictionaryValue* message_dict;
+  if (!message || !message->GetAsDictionary(&message_dict)) {
+    NOTREACHED() << "Badly formed reply";
+    return;
+  }
+  int id = 0;
+  DCHECK(message_dict->GetInteger("id", &id));
+  auto it = pending_messages_.find(id);
+  if (it == pending_messages_.end()) {
+    NOTREACHED() << "Unexpected reply";
+    return;
+  }
+  base::DictionaryValue* result_dict;
+  if (message_dict->GetDictionary("result", &result_dict)) {
+    it->second.callback_with_result.Run(*result_dict);
+  } else {
+    it->second.callback.Run();
+  }
+  pending_messages_.erase(it);
+}
+
+void HeadlessDevToolsClientImpl::AgentHostClosed(
+    content::DevToolsAgentHost* agent_host,
+    bool replaced_with_another_client) {
+  DCHECK_EQ(agent_host_, agent_host);
+  agent_host = nullptr;
+  pending_messages_.clear();
+}
+
+accessibility::Domain* HeadlessDevToolsClientImpl::GetAccessibility() {
+  return &accessibility_domain_;
+}
+
+animation::Domain* HeadlessDevToolsClientImpl::GetAnimation() {
+  return &animation_domain_;
+}
+
+application_cache::Domain* HeadlessDevToolsClientImpl::GetApplicationCache() {
+  return &application_cache_domain_;
+}
+
+cache_storage::Domain* HeadlessDevToolsClientImpl::GetCacheStorage() {
+  return &cache_storage_domain_;
+}
+
+console::Domain* HeadlessDevToolsClientImpl::GetConsole() {
+  return &console_domain_;
+}
+
+css::Domain* HeadlessDevToolsClientImpl::GetCSS() {
+  return &css_domain_;
+}
+
+database::Domain* HeadlessDevToolsClientImpl::GetDatabase() {
+  return &database_domain_;
+}
+
+debugger::Domain* HeadlessDevToolsClientImpl::GetDebugger() {
+  return &debugger_domain_;
+}
+
+device_orientation::Domain* HeadlessDevToolsClientImpl::GetDeviceOrientation() {
+  return &device_orientation_domain_;
+}
+
+dom_debugger::Domain* HeadlessDevToolsClientImpl::GetDOMDebugger() {
+  return &dom_debugger_domain_;
+}
+
+dom::Domain* HeadlessDevToolsClientImpl::GetDOM() {
+  return &dom_domain_;
+}
+
+dom_storage::Domain* HeadlessDevToolsClientImpl::GetDOMStorage() {
+  return &dom_storage_domain_;
+}
+
+emulation::Domain* HeadlessDevToolsClientImpl::GetEmulation() {
+  return &emulation_domain_;
+}
+
+heap_profiler::Domain* HeadlessDevToolsClientImpl::GetHeapProfiler() {
+  return &heap_profiler_domain_;
+}
+
+indexeddb::Domain* HeadlessDevToolsClientImpl::GetIndexedDB() {
+  return &indexeddb_domain_;
+}
+
+input::Domain* HeadlessDevToolsClientImpl::GetInput() {
+  return &input_domain_;
+}
+
+inspector::Domain* HeadlessDevToolsClientImpl::GetInspector() {
+  return &inspector_domain_;
+}
+
+io::Domain* HeadlessDevToolsClientImpl::GetIO() {
+  return &io_domain_;
+}
+
+layer_tree::Domain* HeadlessDevToolsClientImpl::GetLayerTree() {
+  return &layer_tree_domain_;
+}
+
+memory::Domain* HeadlessDevToolsClientImpl::GetMemory() {
+  return &memory_domain_;
+}
+
+network::Domain* HeadlessDevToolsClientImpl::GetNetwork() {
+  return &network_domain_;
+}
+
+page::Domain* HeadlessDevToolsClientImpl::GetPage() {
+  return &page_domain_;
+}
+
+profiler::Domain* HeadlessDevToolsClientImpl::GetProfiler() {
+  return &profiler_domain_;
+}
+
+rendering::Domain* HeadlessDevToolsClientImpl::GetRendering() {
+  return &rendering_domain_;
+}
+
+runtime::Domain* HeadlessDevToolsClientImpl::GetRuntime() {
+  return &runtime_domain_;
+}
+
+security::Domain* HeadlessDevToolsClientImpl::GetSecurity() {
+  return &security_domain_;
+}
+
+service_worker::Domain* HeadlessDevToolsClientImpl::GetServiceWorker() {
+  return &service_worker_domain_;
+}
+
+tracing::Domain* HeadlessDevToolsClientImpl::GetTracing() {
+  return &tracing_domain_;
+}
+
+worker::Domain* HeadlessDevToolsClientImpl::GetWorker() {
+  return &worker_domain_;
+}
+
+template <typename CallbackType>
+void HeadlessDevToolsClientImpl::FinalizeAndSendMessage(
+    base::DictionaryValue* message,
+    CallbackType callback) {
+  DCHECK(agent_host_);
+  int id = next_message_id_++;
+  message->SetInteger("id", id);
+  std::string json_message;
+  base::JSONWriter::Write(*message, &json_message);
+  pending_messages_[id] = PendingMessage(callback);
+  agent_host_->DispatchProtocolMessage(json_message);
+}
+
+template <typename CallbackType>
+void HeadlessDevToolsClientImpl::SendMessageWithParams(
+    const char* method,
+    std::unique_ptr<base::Value> params,
+    CallbackType callback) {
+  base::DictionaryValue message;
+  message.SetString("method", method);
+  message.Set("params", std::move(params));
+  FinalizeAndSendMessage(&message, std::move(callback));
+}
+
+template <typename CallbackType>
+void HeadlessDevToolsClientImpl::SendMessageWithoutParams(
+    const char* method,
+    CallbackType callback) {
+  base::DictionaryValue message;
+  message.SetString("method", method);
+  FinalizeAndSendMessage(&message, std::move(callback));
+}
+
+void HeadlessDevToolsClientImpl::SendMessage(
+    const char* method,
+    std::unique_ptr<base::Value> params,
+    base::Callback<void(const base::Value&)> callback) {
+  SendMessageWithParams(method, std::move(params), std::move(callback));
+}
+
+void HeadlessDevToolsClientImpl::SendMessage(
+    const char* method,
+    std::unique_ptr<base::Value> params,
+    base::Callback<void()> callback) {
+  SendMessageWithParams(method, std::move(params), std::move(callback));
+}
+
+void HeadlessDevToolsClientImpl::SendMessage(
+    const char* method,
+    base::Callback<void(const base::Value&)> callback) {
+  SendMessageWithoutParams(method, std::move(callback));
+}
+
+void HeadlessDevToolsClientImpl::SendMessage(const char* method,
+                                             base::Callback<void()> callback) {
+  SendMessageWithoutParams(method, std::move(callback));
+}
+
+HeadlessDevToolsClientImpl::PendingMessage::PendingMessage() {}
+
+HeadlessDevToolsClientImpl::PendingMessage::PendingMessage(
+    PendingMessage&& other) = default;
+
+HeadlessDevToolsClientImpl::PendingMessage::PendingMessage(
+    base::Callback<void()> callback)
+    : callback(callback) {}
+
+HeadlessDevToolsClientImpl::PendingMessage::PendingMessage(
+    base::Callback<void(const base::Value&)> callback)
+    : callback_with_result(callback) {}
+
+HeadlessDevToolsClientImpl::PendingMessage::~PendingMessage() {}
+
+HeadlessDevToolsClientImpl::PendingMessage&
+HeadlessDevToolsClientImpl::PendingMessage::operator=(PendingMessage&& other) =
+    default;
+
+}  // namespace headless
diff --git a/headless/lib/browser/headless_devtools_client_impl.h b/headless/lib/browser/headless_devtools_client_impl.h
new file mode 100644
index 0000000..fb5442c
--- /dev/null
+++ b/headless/lib/browser/headless_devtools_client_impl.h
@@ -0,0 +1,183 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef HEADLESS_LIB_BROWSER_HEADLESS_DEVTOOLS_CLIENT_IMPL_H_
+#define HEADLESS_LIB_BROWSER_HEADLESS_DEVTOOLS_CLIENT_IMPL_H_
+
+#include <unordered_map>
+
+#include "content/public/browser/devtools_agent_host_client.h"
+#include "headless/public/domains/accessibility.h"
+#include "headless/public/domains/animation.h"
+#include "headless/public/domains/application_cache.h"
+#include "headless/public/domains/cache_storage.h"
+#include "headless/public/domains/console.h"
+#include "headless/public/domains/css.h"
+#include "headless/public/domains/database.h"
+#include "headless/public/domains/debugger.h"
+#include "headless/public/domains/device_orientation.h"
+#include "headless/public/domains/dom.h"
+#include "headless/public/domains/dom_debugger.h"
+#include "headless/public/domains/dom_storage.h"
+#include "headless/public/domains/emulation.h"
+#include "headless/public/domains/heap_profiler.h"
+#include "headless/public/domains/indexeddb.h"
+#include "headless/public/domains/input.h"
+#include "headless/public/domains/inspector.h"
+#include "headless/public/domains/io.h"
+#include "headless/public/domains/layer_tree.h"
+#include "headless/public/domains/memory.h"
+#include "headless/public/domains/network.h"
+#include "headless/public/domains/page.h"
+#include "headless/public/domains/profiler.h"
+#include "headless/public/domains/rendering.h"
+#include "headless/public/domains/runtime.h"
+#include "headless/public/domains/security.h"
+#include "headless/public/domains/service_worker.h"
+#include "headless/public/domains/tracing.h"
+#include "headless/public/domains/worker.h"
+#include "headless/public/headless_devtools_client.h"
+#include "headless/public/internal/message_dispatcher.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace content {
+class DevToolsAgentHost;
+}
+
+namespace headless {
+
+class HeadlessDevToolsClientImpl : public HeadlessDevToolsClient,
+                                   public content::DevToolsAgentHostClient,
+                                   public internal::MessageDispatcher {
+ public:
+  HeadlessDevToolsClientImpl();
+  ~HeadlessDevToolsClientImpl() override;
+
+  static HeadlessDevToolsClientImpl* From(HeadlessDevToolsClient* client);
+
+  // HeadlessDevToolsClient implementation:
+  accessibility::Domain* GetAccessibility() override;
+  animation::Domain* GetAnimation() override;
+  application_cache::Domain* GetApplicationCache() override;
+  cache_storage::Domain* GetCacheStorage() override;
+  console::Domain* GetConsole() override;
+  css::Domain* GetCSS() override;
+  database::Domain* GetDatabase() override;
+  debugger::Domain* GetDebugger() override;
+  device_orientation::Domain* GetDeviceOrientation() override;
+  dom::Domain* GetDOM() override;
+  dom_debugger::Domain* GetDOMDebugger() override;
+  dom_storage::Domain* GetDOMStorage() override;
+  emulation::Domain* GetEmulation() override;
+  heap_profiler::Domain* GetHeapProfiler() override;
+  indexeddb::Domain* GetIndexedDB() override;
+  input::Domain* GetInput() override;
+  inspector::Domain* GetInspector() override;
+  io::Domain* GetIO() override;
+  layer_tree::Domain* GetLayerTree() override;
+  memory::Domain* GetMemory() override;
+  network::Domain* GetNetwork() override;
+  page::Domain* GetPage() override;
+  profiler::Domain* GetProfiler() override;
+  rendering::Domain* GetRendering() override;
+  runtime::Domain* GetRuntime() override;
+  security::Domain* GetSecurity() override;
+  service_worker::Domain* GetServiceWorker() override;
+  tracing::Domain* GetTracing() override;
+  worker::Domain* GetWorker() override;
+
+  // content::DevToolstAgentHostClient implementation:
+  void DispatchProtocolMessage(content::DevToolsAgentHost* agent_host,
+                               const std::string& json_message) override;
+  void AgentHostClosed(content::DevToolsAgentHost* agent_host,
+                       bool replaced_with_another_client) override;
+
+  // internal::MessageDispatcher implementation:
+  void SendMessage(const char* method,
+                   std::unique_ptr<base::Value> params,
+                   base::Callback<void(const base::Value&)> callback) override;
+  void SendMessage(const char* method,
+                   std::unique_ptr<base::Value> params,
+                   base::Callback<void()> callback) override;
+  void SendMessage(const char* method,
+                   base::Callback<void(const base::Value&)> callback) override;
+  void SendMessage(const char* method,
+                   base::Callback<void()> callback) override;
+
+  void AttachToHost(content::DevToolsAgentHost* agent_host);
+  void DetachFromHost(content::DevToolsAgentHost* agent_host);
+
+ private:
+  // Represents a message for which we are still waiting for a reply. Contains
+  // a callback with or without a result parameter depending on the message that
+  // is pending.
+  struct PendingMessage {
+    PendingMessage();
+    PendingMessage(PendingMessage&& other);
+    explicit PendingMessage(base::Callback<void()> callback);
+    explicit PendingMessage(base::Callback<void(const base::Value&)> callback);
+    ~PendingMessage();
+
+    PendingMessage& operator=(PendingMessage&& other);
+
+    // TODO(skyostil): Use a class union once allowed.
+    base::Callback<void()> callback;
+    base::Callback<void(const base::Value&)> callback_with_result;
+  };
+
+  template <typename CallbackType>
+  void FinalizeAndSendMessage(base::DictionaryValue* message,
+                              CallbackType callback);
+
+  template <typename CallbackType>
+  void SendMessageWithParams(const char* method,
+                             std::unique_ptr<base::Value> params,
+                             CallbackType callback);
+
+  template <typename CallbackType>
+  void SendMessageWithoutParams(const char* method, CallbackType callback);
+
+  content::DevToolsAgentHost* agent_host_;  // Not owned.
+  int next_message_id_;
+  std::unordered_map<int, PendingMessage> pending_messages_;
+
+  accessibility::Domain accessibility_domain_;
+  animation::Domain animation_domain_;
+  application_cache::Domain application_cache_domain_;
+  cache_storage::Domain cache_storage_domain_;
+  console::Domain console_domain_;
+  css::Domain css_domain_;
+  database::Domain database_domain_;
+  debugger::Domain debugger_domain_;
+  device_orientation::Domain device_orientation_domain_;
+  dom_debugger::Domain dom_debugger_domain_;
+  dom::Domain dom_domain_;
+  dom_storage::Domain dom_storage_domain_;
+  emulation::Domain emulation_domain_;
+  heap_profiler::Domain heap_profiler_domain_;
+  indexeddb::Domain indexeddb_domain_;
+  input::Domain input_domain_;
+  inspector::Domain inspector_domain_;
+  io::Domain io_domain_;
+  layer_tree::Domain layer_tree_domain_;
+  memory::Domain memory_domain_;
+  network::Domain network_domain_;
+  page::Domain page_domain_;
+  profiler::Domain profiler_domain_;
+  rendering::Domain rendering_domain_;
+  runtime::Domain runtime_domain_;
+  security::Domain security_domain_;
+  service_worker::Domain service_worker_domain_;
+  tracing::Domain tracing_domain_;
+  worker::Domain worker_domain_;
+
+  DISALLOW_COPY_AND_ASSIGN(HeadlessDevToolsClientImpl);
+};
+
+}  // namespace headless
+
+#endif  // HEADLESS_LIB_BROWSER_HEADLESS_DEVTOOLS_CLIENT_IMPL_H_
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc
index f58dfe0..94eae96 100644
--- a/headless/lib/browser/headless_web_contents_impl.cc
+++ b/headless/lib/browser/headless_web_contents_impl.cc
@@ -8,6 +8,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
 #include "base/trace_event/trace_event.h"
+#include "content/public/browser/devtools_agent_host.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
@@ -19,6 +20,7 @@
 #include "content/public/common/bindings_policy.h"
 #include "content/public/common/service_registry.h"
 #include "content/public/renderer/render_frame.h"
+#include "headless/lib/browser/headless_devtools_client_impl.h"
 #include "ui/aura/window.h"
 
 namespace headless {
@@ -31,7 +33,10 @@
 
   ~WebContentsObserverAdapter() override {}
 
-  void RenderViewReady() override { observer_->WebContentsReady(); }
+  void RenderViewReady() override {
+    DCHECK(web_contents()->GetMainFrame()->IsRenderFrameLive());
+    observer_->DevToolsTargetReady();
+  }
 
   void DocumentOnLoadCompletedInMainFrame() override {
     observer_->DocumentOnLoadCompletedInMainFrame();
@@ -107,6 +112,21 @@
   observer_map_.erase(it);
 }
 
+HeadlessDevToolsTarget* HeadlessWebContentsImpl::GetDevToolsTarget() {
+  return web_contents()->GetMainFrame()->IsRenderFrameLive() ? this : nullptr;
+}
+
+void HeadlessWebContentsImpl::AttachClient(HeadlessDevToolsClient* client) {
+  if (!agent_host_)
+    agent_host_ = content::DevToolsAgentHost::GetOrCreateFor(web_contents());
+  HeadlessDevToolsClientImpl::From(client)->AttachToHost(agent_host_.get());
+}
+
+void HeadlessWebContentsImpl::DetachClient(HeadlessDevToolsClient* client) {
+  DCHECK(agent_host_);
+  HeadlessDevToolsClientImpl::From(client)->DetachFromHost(agent_host_.get());
+}
+
 content::WebContents* HeadlessWebContentsImpl::web_contents() const {
   return web_contents_.get();
 }
diff --git a/headless/lib/browser/headless_web_contents_impl.h b/headless/lib/browser/headless_web_contents_impl.h
index e1cdc2d1..c56c50ee3 100644
--- a/headless/lib/browser/headless_web_contents_impl.h
+++ b/headless/lib/browser/headless_web_contents_impl.h
@@ -5,6 +5,7 @@
 #ifndef HEADLESS_LIB_BROWSER_HEADLESS_WEB_CONTENTS_IMPL_H_
 #define HEADLESS_LIB_BROWSER_HEADLESS_WEB_CONTENTS_IMPL_H_
 
+#include "headless/public/headless_devtools_target.h"
 #include "headless/public/headless_web_contents.h"
 
 #include <memory>
@@ -15,8 +16,9 @@
 }
 
 namespace content {
-class WebContents;
 class BrowserContext;
+class DevToolsAgentHost;
+class WebContents;
 }
 
 namespace gfx {
@@ -24,9 +26,11 @@
 }
 
 namespace headless {
+class HeadlessDevToolsHostImpl;
 class WebContentsObserverAdapter;
 
-class HeadlessWebContentsImpl : public HeadlessWebContents {
+class HeadlessWebContentsImpl : public HeadlessWebContents,
+                                public HeadlessDevToolsTarget {
  public:
   HeadlessWebContentsImpl(content::BrowserContext* context,
                           aura::Window* parent_window,
@@ -36,6 +40,11 @@
   // HeadlessWebContents implementation:
   void AddObserver(Observer* observer) override;
   void RemoveObserver(Observer* observer) override;
+  HeadlessDevToolsTarget* GetDevToolsTarget() override;
+
+  // HeadlessDevToolsTarget implementation:
+  void AttachClient(HeadlessDevToolsClient* client) override;
+  void DetachClient(HeadlessDevToolsClient* client) override;
 
   content::WebContents* web_contents() const;
   bool OpenURL(const GURL& url);
@@ -44,6 +53,7 @@
   class Delegate;
   std::unique_ptr<Delegate> web_contents_delegate_;
   std::unique_ptr<content::WebContents> web_contents_;
+  scoped_refptr<content::DevToolsAgentHost> agent_host_;
 
   using ObserverMap =
       std::unordered_map<HeadlessWebContents::Observer*,
diff --git a/headless/lib/browser/type_conversions_h.template b/headless/lib/browser/type_conversions_h.template
new file mode 100644
index 0000000..286b0e5
--- /dev/null
+++ b/headless/lib/browser/type_conversions_h.template
@@ -0,0 +1,77 @@
+// This file is generated
+
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef HEADLESS_PUBLIC_DOMAINS_TYPE_CONVERSIONS_H_
+#define HEADLESS_PUBLIC_DOMAINS_TYPE_CONVERSIONS_H_
+
+#include "headless/public/domains/types.h"
+#include "headless/public/internal/value_conversions.h"
+
+namespace headless {
+namespace internal {
+
+{% for domain in api.domains %}
+  {% for type in domain.types %}
+    {% set namespace = domain.domain | camelcase_to_hacker_style %}
+    {% if "enum" in type %}
+template <>
+struct FromValue<{{namespace}}::{{type.id}}> {
+  static {{namespace}}::{{type.id}} Parse(const base::Value& value, ErrorReporter* errors) {
+      {% set default = namespace + '::' + type.id + '::' + type.enum[0] | dash_to_camelcase | camelcase_to_hacker_style | upper | mangle_enum %}
+    std::string string_value;
+    if (!value.GetAsString(&string_value)) {
+      errors->AddError("string enum value expected");
+      {# Return an arbitrary enum member -- the caller will just ignore it. #}
+      return {{default}};
+    }
+      {% for literal in type.enum %}
+    if (string_value == "{{literal}}")
+      return {{namespace}}::{{type.id}}::{{literal | dash_to_camelcase | camelcase_to_hacker_style | upper | mangle_enum}};
+      {% endfor %}
+    errors->AddError("invalid enum value");
+    return {{default}};
+  }
+};
+
+template <typename T>
+std::unique_ptr<base::Value> ToValueImpl(const {{namespace}}::{{type.id}}& value, T*) {
+  switch (value) {
+      {% for literal in type.enum %}
+    case {{namespace}}::{{type.id}}::{{literal | dash_to_camelcase | camelcase_to_hacker_style | upper | mangle_enum}}:
+      return base::WrapUnique(new base::StringValue("{{literal}}"));
+      {% endfor %}
+  };
+  NOTREACHED();
+  return nullptr;
+}
+      {% continue %}
+    {% endif %}
+
+    {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %}
+template <>
+struct FromValue<{{namespace}}::{{type.id}}> {
+  static std::unique_ptr<{{namespace}}::{{type.id}}> Parse(const base::Value& value, ErrorReporter* errors) {
+    return {{namespace}}::{{type.id}}::Parse(value, errors);
+  }
+};
+
+template <typename T>
+std::unique_ptr<base::Value> ToValueImpl(const {{namespace}}::{{type.id}}& value, T*) {
+  return value.Serialize();
+}
+
+  {% endfor %}
+{% endfor %}
+
+template <typename T>
+std::unique_ptr<base::Value> ToValue(const T& value) {
+  return ToValueImpl(value, static_cast<T*>(nullptr));
+}
+
+}  // namespace internal
+}  // namespace headless
+
+#endif  // HEADLESS_PUBLIC_DOMAINS_TYPE_CONVERSIONS_H_
diff --git a/headless/lib/browser/types_cc.template b/headless/lib/browser/types_cc.template
new file mode 100644
index 0000000..5be72cf
--- /dev/null
+++ b/headless/lib/browser/types_cc.template
@@ -0,0 +1,130 @@
+// This file is generated
+
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "headless/public/domains/types.h"
+
+#include "base/memory/ptr_util.h"
+#include "headless/public/domains/type_conversions.h"
+
+namespace headless {
+
+// ------------- Enum values from types.
+{% for domain in api.domains %}
+  {% continue %}
+
+namespace internal {
+
+  {% for type in domain.types %}
+// {{type}}
+    {% if type.type == "array" %}
+template <>
+struct FromValue<{{resolve_type(type).raw_type}}> {
+  static {{resolve_type(type).raw_type}} Parse(const base::Value& value, ErrorReporter* errors) {
+    {{resolve_type(type).raw_type}} result;
+    const base::ListValue* list;
+    if (!value.GetAsList(&list)) {
+      errors->AddError("list value expected");
+      return result;
+    }
+    errors->Push();
+    for (const auto& item : *list)
+      result.push_back(FromValue<{{resolve_type(type).raw_type}}::value_type>::Parse(*item, errors));
+    errors->Pop();
+    return result;
+  }
+};
+
+      {% continue %}
+    {% endif %}
+#}
+    {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %}
+    {% set namespace = domain.domain | camelcase_to_hacker_style %}
+template <>
+struct FromValue<{{namespace}}::{{type.id}}> {
+  static std::unique_ptr<{{namespace}}::{{type.id}}> Parse(const base::Value& value, ErrorReporter* errors) {
+    return {{namespace}}::{{type.id}}::Parse(value, errors);
+  }
+};
+
+template <typename T>
+std::unique_ptr<base::Value> ToValueImpl(const {{namespace}}::{{type.id}}& value, T*) {
+  return value.Serialize();
+}
+
+  {% endfor %}
+}  // namespace internal
+{% endfor %}
+
+{% for domain in api.domains %}
+
+namespace {{domain.domain | camelcase_to_hacker_style}} {
+  {% for type in domain.types %}
+    {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %}
+
+std::unique_ptr<{{type.id}}> {{type.id}}::Parse(const base::Value& value, ErrorReporter* errors) {
+  errors->Push();
+  errors->SetName("{{type.id}}");
+  const base::DictionaryValue* object;
+  if (!value.GetAsDictionary(&object)) {
+    errors->AddError("object expected");
+    errors->Pop();
+    return nullptr;
+  }
+
+  std::unique_ptr<{{type.id}}> result(new {{type.id}}());
+  errors->Push();
+  errors->SetName("{{type.id}}");
+    {% for property in type.properties %}
+      {% set value_name = property.name | camelcase_to_hacker_style + "_value" %}
+  const base::Value* {{value_name}};
+  if (object->Get("{{property.name}}", &{{value_name}})) {
+    errors->SetName("{{property.name}}");
+      {% if property.optional %}
+    result->{{property.name | camelcase_to_hacker_style}}_ = internal::FromValue<{{resolve_type(property).raw_type}}>::Parse(*{{value_name}}, errors);
+      {% else %}
+    result->{{property.name | camelcase_to_hacker_style}}_ = internal::FromValue<{{resolve_type(property).raw_type}}>::Parse(*{{value_name}}, errors);
+      {% endif %}
+      {% if property.optional %}
+  }
+      {% else %}
+  } else {
+    errors->AddError("required property missing: {{property.name}}");
+  }
+      {% endif %}
+    {% endfor %}
+  errors->Pop();
+  errors->Pop();
+  if (errors->HasErrors())
+    return nullptr;
+  return result;
+}
+
+std::unique_ptr<base::Value> {{type.id}}::Serialize() const {
+  std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
+    {% for property in type.properties %}
+      {% set type = resolve_type(property) %}
+      {% if property.optional %}
+  if ({{property.name | camelcase_to_hacker_style}}_)
+    result->Set("{{property.name}}", internal::ToValue({{type.to_raw_type % ("%s_.value()" % property.name | camelcase_to_hacker_style)}}));
+      {% else %}
+  result->Set("{{property.name}}", internal::ToValue({{type.to_raw_type % ("%s_" % property.name | camelcase_to_hacker_style)}}));
+      {% endif %}
+    {% endfor %}
+  return std::move(result);
+}
+
+std::unique_ptr<{{type.id}}> {{type.id}}::Clone() const {
+  ErrorReporter errors;
+  std::unique_ptr<{{type.id}}> result = Parse(*Serialize(), &errors);
+  DCHECK(!errors.HasErrors());
+  return result;
+}
+
+  {% endfor %}
+}  // namespace {{domain.domain | camelcase_to_hacker_style}}
+{% endfor %}
+
+} // namespace headless
diff --git a/headless/lib/browser/types_h.template b/headless/lib/browser/types_h.template
new file mode 100644
index 0000000..0d883ea
--- /dev/null
+++ b/headless/lib/browser/types_h.template
@@ -0,0 +1,158 @@
+// This file is generated
+
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef HEADLESS_PUBLIC_DOMAINS_TYPES_H_
+#define HEADLESS_PUBLIC_DOMAINS_TYPES_H_
+
+#include "base/optional.h"
+#include "base/values.h"
+#include "headless/public/headless_export.h"
+#include "headless/public/util/error_reporter.h"
+
+#include "base/memory/ptr_util.h"
+
+namespace headless {
+
+// ------------- Forward declarations and typedefs.
+
+{% for domain in api.domains %}
+
+namespace {{domain.domain | camelcase_to_hacker_style}} {
+  {% for type in domain.types %}
+    {% if type.type == "object" %}
+      {% if "properties" in type %}
+class {{type.id}};
+      {% else %}
+using {{type.id}} = base::Value;
+      {% endif %}
+    {% endif %}
+  {% endfor %}
+}  // namespace {{domain.domain}}
+{% endfor %}
+
+{% for domain in api.domains %}
+namespace {{domain.domain | camelcase_to_hacker_style}} {
+  {% for type in domain.types %}
+    {% if "enum" in type %}
+enum class {{type.id}} {
+      {% for literal in type.enum %}
+  {{ literal | dash_to_camelcase | camelcase_to_hacker_style | upper | mangle_enum}}{{',' if not loop.last}}
+      {% endfor %}
+};
+
+    {% endif %}
+  {% endfor %}
+}  // namespace {{domain.domain | camelcase_to_hacker_style}}
+
+{% endfor %}
+
+// ------------- Type and builder declarations.
+{% for domain in api.domains %}
+
+namespace {{domain.domain | camelcase_to_hacker_style}} {
+  {% for type in domain.types %}
+    {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %}
+
+    {% if type.description %}
+// {{type.description}}
+    {% endif %}
+class HEADLESS_EXPORT {{type.id}} {
+ public:
+  static {{resolve_type(type).pass_type}} Parse(const base::Value& value, ErrorReporter* errors);
+  ~{{type.id}}() { }
+    {% for property in type.properties %}
+
+    {% if property.description %}
+  // {{property.description}}
+    {% endif %}
+      {% if property.optional %}
+  bool Has{{property.name | to_title_case}}() { return !!{{property.name | camelcase_to_hacker_style}}_; }
+  {{resolve_type(property).raw_return_type}} Get{{property.name | to_title_case}}() { return {{resolve_type(property).to_raw_return_type % ("%s_.value()" % property.name | camelcase_to_hacker_style)}}; }
+  void Set{{property.name | to_title_case}}({{resolve_type(property).pass_type}} value) { {{property.name | camelcase_to_hacker_style}}_ = {{resolve_type(property).to_pass_type % 'value'}}; }
+      {% else %}
+  {{resolve_type(property).raw_return_type}} Get{{property.name | to_title_case}}() { return {{resolve_type(property).to_raw_return_type % ("%s_" % property.name | camelcase_to_hacker_style)}}; }
+  void Set{{property.name | to_title_case}}({{resolve_type(property).pass_type}} value) { {{property.name | camelcase_to_hacker_style}}_ = {{resolve_type(property).to_pass_type % 'value'}}; }
+      {% endif %}
+    {% endfor %}
+
+  std::unique_ptr<base::Value> Serialize() const;
+  {{resolve_type(type).pass_type}} Clone() const;
+
+  template<int STATE>
+  class {{type.id}}Builder {
+  public:
+    enum {
+      kNoFieldsSet = 0,
+    {% set count = 0 %}
+    {% for property in type.properties %}
+      {% if not(property.optional) %}
+        {% set count = count + 1 %}
+      k{{property.name | to_title_case}}Set = 1 << {{count}},
+      {% endif %}
+    {% endfor %}
+      kAllRequiredFieldsSet = (
+    {%- for property in type.properties %}
+      {% if not(property.optional) %}k{{property.name | to_title_case}}Set | {%endif %}
+    {% endfor %}0)
+    };
+
+    {% for property in type.properties %}
+      {% if property.optional %}
+    {{type.id}}Builder<STATE>& Set{{property.name | to_title_case}}({{resolve_type(property).pass_type}} value) {
+      result_->Set{{property.name | to_title_case}}({{resolve_type(property).to_pass_type % 'value'}});
+      return *this;
+    }
+      {% else %}
+    {{type.id}}Builder<STATE | k{{property.name | to_title_case}}Set>& Set{{property.name | to_title_case}}({{resolve_type(property).pass_type}} value) {
+      static_assert(!(STATE & k{{property.name | to_title_case}}Set), "property {{property.name}} should not have already been set");
+      result_->Set{{property.name | to_title_case}}({{resolve_type(property).to_pass_type % 'value'}});
+      return CastState<k{{property.name | to_title_case}}Set>();
+    }
+      {% endif %}
+
+    {% endfor %}
+    {{resolve_type(type).pass_type}} Build() {
+      static_assert(STATE == kAllRequiredFieldsSet, "all required fields should have been set");
+      return std::move(result_);
+    }
+
+   private:
+    friend class {{type.id}};
+    {{type.id}}Builder() : result_(new {{type.id}}()) { }
+
+    template<int STEP> {{type.id}}Builder<STATE | STEP>& CastState() {
+      return *reinterpret_cast<{{type.id}}Builder<STATE | STEP>*>(this);
+    }
+
+    {{resolve_type(type).type}} result_;
+  };
+
+  static {{type.id}}Builder<0> Builder() {
+    return {{type.id}}Builder<0>();
+  }
+
+ private:
+  {{type.id}}() { }
+
+    {% for property in type.properties %}
+      {% if property.optional %}
+  base::Optional<{{resolve_type(property).type}}> {{property.name | camelcase_to_hacker_style}}_;
+      {% else %}
+  {{resolve_type(property).type}} {{property.name | camelcase_to_hacker_style}}_;
+      {% endif %}
+    {% endfor %}
+
+  DISALLOW_COPY_AND_ASSIGN({{type.id}});
+};
+
+  {% endfor %}
+
+}  // namespace {{domain.domain | camelcase_to_hacker_style}}
+{% endfor %}
+
+}  // namespace headless
+
+#endif  // HEADLESS_PUBLIC_DOMAINS_TYPES_H_
diff --git a/headless/lib/headless_devtools_client_browsertest.cc b/headless/lib/headless_devtools_client_browsertest.cc
new file mode 100644
index 0000000..d67682a
--- /dev/null
+++ b/headless/lib/headless_devtools_client_browsertest.cc
@@ -0,0 +1,113 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+
+#include "content/public/test/browser_test.h"
+#include "headless/public/domains/page.h"
+#include "headless/public/domains/runtime.h"
+#include "headless/public/headless_browser.h"
+#include "headless/public/headless_devtools_client.h"
+#include "headless/public/headless_devtools_target.h"
+#include "headless/public/headless_web_contents.h"
+#include "headless/test/headless_browser_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/size.h"
+#include "url/gurl.h"
+
+namespace headless {
+
+#define DEVTOOLS_CLIENT_TEST_F(TEST_FIXTURE_NAME)                        \
+  IN_PROC_BROWSER_TEST_F(TEST_FIXTURE_NAME, RunAsyncTest) { RunTest(); } \
+  class AsyncHeadlessBrowserTestNeedsSemicolon##TEST_FIXTURE_NAME {}
+
+// A test fixture which attaches a devtools client before starting the test.
+class HeadlessDevToolsClientTest : public HeadlessBrowserTest,
+                                   public HeadlessWebContents::Observer {
+ public:
+  HeadlessDevToolsClientTest()
+      : devtools_client_(HeadlessDevToolsClient::Create()) {}
+  ~HeadlessDevToolsClientTest() override {}
+
+  // HeadlessWebContentsObserver implementation:
+  void DevToolsTargetReady() override {
+    EXPECT_TRUE(web_contents_->GetDevToolsTarget());
+    web_contents_->GetDevToolsTarget()->AttachClient(devtools_client_.get());
+    RunDevToolsClientTest();
+  }
+
+  virtual void RunDevToolsClientTest() = 0;
+
+ protected:
+  void RunTest() {
+    web_contents_ =
+        browser()->CreateWebContents(GURL("about:blank"), gfx::Size(800, 600));
+    web_contents_->AddObserver(this);
+
+    RunAsynchronousTest();
+
+    web_contents_->GetDevToolsTarget()->DetachClient(devtools_client_.get());
+    web_contents_->RemoveObserver(this);
+    web_contents_ = nullptr;
+  }
+
+  std::unique_ptr<HeadlessWebContents> web_contents_;
+  std::unique_ptr<HeadlessDevToolsClient> devtools_client_;
+};
+
+class HeadlessDevToolsClientNavigationTest : public HeadlessDevToolsClientTest {
+ public:
+  void RunDevToolsClientTest() override {
+    EXPECT_TRUE(embedded_test_server()->Start());
+    std::unique_ptr<page::NavigateParams> params =
+        page::NavigateParams::Builder()
+            .SetUrl(embedded_test_server()->GetURL("/hello.html").spec())
+            .Build();
+    devtools_client_->GetPage()->Navigate(std::move(params));
+  }
+
+  // TODO(skyostil): Wait for a load event once we support them.
+  void DidFinishNavigation(bool success) override {
+    EXPECT_TRUE(success);
+    FinishAsynchronousTest();
+  }
+};
+
+DEVTOOLS_CLIENT_TEST_F(HeadlessDevToolsClientNavigationTest);
+
+class HeadlessDevToolsClientEvalTest : public HeadlessDevToolsClientTest {
+ public:
+  void RunDevToolsClientTest() override {
+    std::unique_ptr<runtime::EvaluateParams> params =
+        runtime::EvaluateParams::Builder().SetExpression("1 + 2").Build();
+    devtools_client_->GetRuntime()->Evaluate(
+        std::move(params),
+        base::Bind(&HeadlessDevToolsClientEvalTest::OnFirstResult,
+                   base::Unretained(this)));
+    // Test the convenience overload which only takes the required command
+    // parameters.
+    devtools_client_->GetRuntime()->Evaluate(
+        "24 * 7", base::Bind(&HeadlessDevToolsClientEvalTest::OnSecondResult,
+                             base::Unretained(this)));
+  }
+
+  void OnFirstResult(std::unique_ptr<runtime::EvaluateResult> result) {
+    int value;
+    EXPECT_TRUE(result->GetResult()->HasValue());
+    EXPECT_TRUE(result->GetResult()->GetValue()->GetAsInteger(&value));
+    EXPECT_EQ(3, value);
+  }
+
+  void OnSecondResult(std::unique_ptr<runtime::EvaluateResult> result) {
+    int value;
+    EXPECT_TRUE(result->GetResult()->HasValue());
+    EXPECT_TRUE(result->GetResult()->GetValue()->GetAsInteger(&value));
+    EXPECT_EQ(168, value);
+    FinishAsynchronousTest();
+  }
+};
+
+DEVTOOLS_CLIENT_TEST_F(HeadlessDevToolsClientEvalTest);
+
+}  // namespace headless
diff --git a/headless/public/domains/README.md b/headless/public/domains/README.md
new file mode 100644
index 0000000..a3f8898c
--- /dev/null
+++ b/headless/public/domains/README.md
@@ -0,0 +1,3 @@
+The client API domain classes are autogenerated. You can find them under the
+out-directory, e.g., out/Debug/gen/headless/public/domains, or in
+[Code Search](https://code.google.com/p/chromium/codesearch#search/&q=f%3Agen/headless/public/domains&sq=package:chromium&type=cs).
diff --git a/headless/public/domains/types_unittest.cc b/headless/public/domains/types_unittest.cc
new file mode 100644
index 0000000..c665d95
--- /dev/null
+++ b/headless/public/domains/types_unittest.cc
@@ -0,0 +1,200 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/json/json_reader.h"
+#include "headless/public/domains/types.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace headless {
+
+TEST(TypesTest, IntegerProperty) {
+  std::unique_ptr<accessibility::GetAXNodeParams> object(
+      accessibility::GetAXNodeParams::Builder().SetNodeId(123).Build());
+  EXPECT_TRUE(object);
+  EXPECT_EQ(123, object->GetNodeId());
+
+  std::unique_ptr<accessibility::GetAXNodeParams> clone(object->Clone());
+  EXPECT_TRUE(clone);
+  EXPECT_EQ(123, clone->GetNodeId());
+}
+
+TEST(TypesTest, IntegerPropertyParseError) {
+  const char* json = "{\"nodeId\": \"foo\"}";
+  std::unique_ptr<base::Value> object = base::JSONReader::Read(json);
+  EXPECT_TRUE(object);
+
+  ErrorReporter errors;
+  EXPECT_FALSE(accessibility::GetAXNodeParams::Parse(*object, &errors));
+  EXPECT_TRUE(errors.HasErrors());
+}
+
+TEST(TypesTest, BooleanProperty) {
+  std::unique_ptr<memory::SetPressureNotificationsSuppressedParams> object(
+      memory::SetPressureNotificationsSuppressedParams::Builder()
+          .SetSuppressed(true)
+          .Build());
+  EXPECT_TRUE(object);
+  EXPECT_TRUE(object->GetSuppressed());
+
+  std::unique_ptr<memory::SetPressureNotificationsSuppressedParams> clone(
+      object->Clone());
+  EXPECT_TRUE(clone);
+  EXPECT_TRUE(clone->GetSuppressed());
+}
+
+TEST(TypesTest, BooleanPropertyParseError) {
+  const char* json = "{\"suppressed\": \"foo\"}";
+  std::unique_ptr<base::Value> object = base::JSONReader::Read(json);
+  EXPECT_TRUE(object);
+
+  ErrorReporter errors;
+  EXPECT_FALSE(memory::SetPressureNotificationsSuppressedParams::Parse(
+      *object, &errors));
+  EXPECT_TRUE(errors.HasErrors());
+}
+
+TEST(TypesTest, DoubleProperty) {
+  std::unique_ptr<page::SetGeolocationOverrideParams> object(
+      page::SetGeolocationOverrideParams::Builder().SetLatitude(3.14).Build());
+  EXPECT_TRUE(object);
+  EXPECT_EQ(3.14, object->GetLatitude());
+
+  std::unique_ptr<page::SetGeolocationOverrideParams> clone(object->Clone());
+  EXPECT_TRUE(clone);
+  EXPECT_EQ(3.14, clone->GetLatitude());
+}
+
+TEST(TypesTest, DoublePropertyParseError) {
+  const char* json = "{\"latitude\": \"foo\"}";
+  std::unique_ptr<base::Value> object = base::JSONReader::Read(json);
+  EXPECT_TRUE(object);
+
+  ErrorReporter errors;
+  EXPECT_FALSE(page::SetGeolocationOverrideParams::Parse(*object, &errors));
+  EXPECT_TRUE(errors.HasErrors());
+}
+
+TEST(TypesTest, StringProperty) {
+  std::unique_ptr<page::NavigateParams> object(
+      page::NavigateParams::Builder().SetUrl("url").Build());
+  EXPECT_TRUE(object);
+  EXPECT_EQ("url", object->GetUrl());
+
+  std::unique_ptr<page::NavigateParams> clone(object->Clone());
+  EXPECT_TRUE(clone);
+  EXPECT_EQ("url", clone->GetUrl());
+}
+
+TEST(TypesTest, StringPropertyParseError) {
+  const char* json = "{\"url\": false}";
+  std::unique_ptr<base::Value> object = base::JSONReader::Read(json);
+  EXPECT_TRUE(object);
+
+  ErrorReporter errors;
+  EXPECT_FALSE(page::NavigateParams::Parse(*object, &errors));
+  EXPECT_TRUE(errors.HasErrors());
+}
+
+TEST(TypesTest, EnumProperty) {
+  std::unique_ptr<runtime::RemoteObject> object(
+      runtime::RemoteObject::Builder()
+          .SetType(runtime::RemoteObjectType::UNDEFINED)
+          .Build());
+  EXPECT_TRUE(object);
+  EXPECT_EQ(runtime::RemoteObjectType::UNDEFINED, object->GetType());
+
+  std::unique_ptr<runtime::RemoteObject> clone(object->Clone());
+  EXPECT_TRUE(clone);
+  EXPECT_EQ(runtime::RemoteObjectType::UNDEFINED, clone->GetType());
+}
+
+TEST(TypesTest, EnumPropertyParseError) {
+  const char* json = "{\"type\": false}";
+  std::unique_ptr<base::Value> object = base::JSONReader::Read(json);
+  EXPECT_TRUE(object);
+
+  ErrorReporter errors;
+  EXPECT_FALSE(runtime::RemoteObject::Parse(*object, &errors));
+  EXPECT_TRUE(errors.HasErrors());
+}
+
+TEST(TypesTest, ArrayProperty) {
+  std::vector<int> values;
+  values.push_back(1);
+  values.push_back(2);
+  values.push_back(3);
+
+  std::unique_ptr<dom::QuerySelectorAllResult> object(
+      dom::QuerySelectorAllResult::Builder().SetNodeIds(values).Build());
+  EXPECT_TRUE(object);
+  EXPECT_EQ(3u, object->GetNodeIds()->size());
+  EXPECT_EQ(1, object->GetNodeIds()->at(0));
+  EXPECT_EQ(2, object->GetNodeIds()->at(1));
+  EXPECT_EQ(3, object->GetNodeIds()->at(2));
+
+  std::unique_ptr<dom::QuerySelectorAllResult> clone(object->Clone());
+  EXPECT_TRUE(clone);
+  EXPECT_EQ(3u, clone->GetNodeIds()->size());
+  EXPECT_EQ(1, clone->GetNodeIds()->at(0));
+  EXPECT_EQ(2, clone->GetNodeIds()->at(1));
+  EXPECT_EQ(3, clone->GetNodeIds()->at(2));
+}
+
+TEST(TypesTest, ArrayPropertyParseError) {
+  const char* json = "{\"nodeIds\": true}";
+  std::unique_ptr<base::Value> object = base::JSONReader::Read(json);
+  EXPECT_TRUE(object);
+
+  ErrorReporter errors;
+  EXPECT_FALSE(dom::QuerySelectorAllResult::Parse(*object, &errors));
+  EXPECT_TRUE(errors.HasErrors());
+}
+
+TEST(TypesTest, ObjectProperty) {
+  std::unique_ptr<runtime::RemoteObject> subobject(
+      runtime::RemoteObject::Builder()
+          .SetType(runtime::RemoteObjectType::SYMBOL)
+          .Build());
+  std::unique_ptr<runtime::EvaluateResult> object(
+      runtime::EvaluateResult::Builder()
+          .SetResult(std::move(subobject))
+          .Build());
+  EXPECT_TRUE(object);
+  EXPECT_EQ(runtime::RemoteObjectType::SYMBOL, object->GetResult()->GetType());
+
+  std::unique_ptr<runtime::EvaluateResult> clone(object->Clone());
+  EXPECT_TRUE(clone);
+  EXPECT_EQ(runtime::RemoteObjectType::SYMBOL, clone->GetResult()->GetType());
+}
+
+TEST(TypesTest, ObjectPropertyParseError) {
+  const char* json = "{\"result\": 42}";
+  std::unique_ptr<base::Value> object = base::JSONReader::Read(json);
+  EXPECT_TRUE(object);
+
+  ErrorReporter errors;
+  EXPECT_FALSE(runtime::EvaluateResult::Parse(*object, &errors));
+  EXPECT_TRUE(errors.HasErrors());
+}
+
+TEST(TypesTest, AnyProperty) {
+  std::unique_ptr<base::Value> value(new base::FundamentalValue(123));
+  std::unique_ptr<accessibility::AXValue> object(
+      accessibility::AXValue::Builder()
+          .SetType(accessibility::AXValueType::INTEGER)
+          .SetValue(std::move(value))
+          .Build());
+  EXPECT_TRUE(object);
+  EXPECT_EQ(base::Value::TYPE_INTEGER, object->GetValue()->GetType());
+
+  std::unique_ptr<accessibility::AXValue> clone(object->Clone());
+  EXPECT_TRUE(clone);
+  EXPECT_EQ(base::Value::TYPE_INTEGER, clone->GetValue()->GetType());
+
+  int clone_value;
+  EXPECT_TRUE(clone->GetValue()->GetAsInteger(&clone_value));
+  EXPECT_EQ(123, clone_value);
+}
+
+}  // namespace headless
diff --git a/headless/public/headless_devtools_client.h b/headless/public/headless_devtools_client.h
new file mode 100644
index 0000000..a71ce65
--- /dev/null
+++ b/headless/public/headless_devtools_client.h
@@ -0,0 +1,157 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef HEADLESS_PUBLIC_HEADLESS_DEVTOOLS_CLIENT_H_
+#define HEADLESS_PUBLIC_HEADLESS_DEVTOOLS_CLIENT_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "headless/public/headless_export.h"
+
+namespace headless {
+
+namespace accessibility {
+class Domain;
+}
+namespace animation {
+class Domain;
+}
+namespace application_cache {
+class Domain;
+}
+namespace cache_storage {
+class Domain;
+}
+namespace console {
+class Domain;
+}
+namespace css {
+class Domain;
+}
+namespace database {
+class Domain;
+}
+namespace debugger {
+class Domain;
+}
+namespace device_orientation {
+class Domain;
+}
+namespace dom {
+class Domain;
+}
+namespace dom_debugger {
+class Domain;
+}
+namespace dom_storage {
+class Domain;
+}
+namespace emulation {
+class Domain;
+}
+namespace heap_profiler {
+class Domain;
+}
+namespace indexeddb {
+class Domain;
+}
+namespace input {
+class Domain;
+}
+namespace inspector {
+class Domain;
+}
+namespace io {
+class Domain;
+}
+namespace layer_tree {
+class Domain;
+}
+namespace memory {
+class Domain;
+}
+namespace network {
+class Domain;
+}
+namespace page {
+class Domain;
+}
+namespace profiler {
+class Domain;
+}
+namespace rendering {
+class Domain;
+}
+namespace runtime {
+class Domain;
+}
+namespace security {
+class Domain;
+}
+namespace service_worker {
+class Domain;
+}
+namespace tracing {
+class Domain;
+}
+namespace worker {
+class Domain;
+}
+
+// An interface for controlling and receiving events from a devtools target.
+class HEADLESS_EXPORT HeadlessDevToolsClient {
+ public:
+  virtual ~HeadlessDevToolsClient() {}
+
+  static std::unique_ptr<HeadlessDevToolsClient> Create();
+
+  // DevTools commands are split into domains which corresponds to the getters
+  // below. Each domain can be used to send commands and to subscribe to events.
+  //
+  // See http://chromedevtools.github.io/debugger-protocol-viewer/ for
+  // the capabilities of each domain.
+  virtual accessibility::Domain* GetAccessibility() = 0;
+  virtual animation::Domain* GetAnimation() = 0;
+  virtual application_cache::Domain* GetApplicationCache() = 0;
+  virtual cache_storage::Domain* GetCacheStorage() = 0;
+  virtual console::Domain* GetConsole() = 0;
+  virtual css::Domain* GetCSS() = 0;
+  virtual database::Domain* GetDatabase() = 0;
+  virtual debugger::Domain* GetDebugger() = 0;
+  virtual device_orientation::Domain* GetDeviceOrientation() = 0;
+  virtual dom::Domain* GetDOM() = 0;
+  virtual dom_debugger::Domain* GetDOMDebugger() = 0;
+  virtual dom_storage::Domain* GetDOMStorage() = 0;
+  virtual emulation::Domain* GetEmulation() = 0;
+  virtual heap_profiler::Domain* GetHeapProfiler() = 0;
+  virtual indexeddb::Domain* GetIndexedDB() = 0;
+  virtual input::Domain* GetInput() = 0;
+  virtual inspector::Domain* GetInspector() = 0;
+  virtual io::Domain* GetIO() = 0;
+  virtual layer_tree::Domain* GetLayerTree() = 0;
+  virtual memory::Domain* GetMemory() = 0;
+  virtual network::Domain* GetNetwork() = 0;
+  virtual page::Domain* GetPage() = 0;
+  virtual profiler::Domain* GetProfiler() = 0;
+  virtual rendering::Domain* GetRendering() = 0;
+  virtual runtime::Domain* GetRuntime() = 0;
+  virtual security::Domain* GetSecurity() = 0;
+  virtual service_worker::Domain* GetServiceWorker() = 0;
+  virtual tracing::Domain* GetTracing() = 0;
+  virtual worker::Domain* GetWorker() = 0;
+
+  // TODO(skyostil): Add notification for disconnection.
+
+ private:
+  friend class HeadlessDevToolsClientImpl;
+
+  HeadlessDevToolsClient() {}
+
+  DISALLOW_COPY_AND_ASSIGN(HeadlessDevToolsClient);
+};
+
+}  // namespace headless
+
+#endif  // HEADLESS_PUBLIC_HEADLESS_DEVTOOLS_CLIENT_H_
diff --git a/headless/public/headless_devtools_target.h b/headless/public/headless_devtools_target.h
new file mode 100644
index 0000000..941fe6f5
--- /dev/null
+++ b/headless/public/headless_devtools_target.h
@@ -0,0 +1,37 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef HEADLESS_PUBLIC_HEADLESS_DEVTOOLS_TARGET_H_
+#define HEADLESS_PUBLIC_HEADLESS_DEVTOOLS_TARGET_H_
+
+#include "base/macros.h"
+#include "headless/public/headless_export.h"
+
+namespace headless {
+class HeadlessDevToolsClient;
+
+// A target which can be controlled and inspected using DevTools.
+class HEADLESS_EXPORT HeadlessDevToolsTarget {
+ public:
+  HeadlessDevToolsTarget() {}
+  virtual ~HeadlessDevToolsTarget() {}
+
+  // Attach or detach a client to this target. A client must be attached in
+  // order to send commands or receive notifications from the target.
+  //
+  // A single client may be attached to at most one target at a time. Note that
+  // currently also only one client may be attached to a single target at a
+  // time.
+  //
+  // |client| must outlive this target.
+  virtual void AttachClient(HeadlessDevToolsClient* client) = 0;
+  virtual void DetachClient(HeadlessDevToolsClient* client) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(HeadlessDevToolsTarget);
+};
+
+}  // namespace headless
+
+#endif  // HEADLESS_PUBLIC_HEADLESS_DEVTOOLS_TARGET_H_
diff --git a/headless/public/headless_web_contents.h b/headless/public/headless_web_contents.h
index 04ac95300..d9b29b7 100644
--- a/headless/public/headless_web_contents.h
+++ b/headless/public/headless_web_contents.h
@@ -12,6 +12,7 @@
 #include "url/gurl.h"
 
 namespace headless {
+class HeadlessDevToolsTarget;
 
 // Class representing contents of a browser tab. Should be accessed from browser
 // main thread.
@@ -23,12 +24,12 @@
   class Observer {
    public:
     // All the following notifications will be called on browser main thread.
-    virtual void DocumentOnLoadCompletedInMainFrame(){};
-    virtual void DidFinishNavigation(bool success){};
+    virtual void DocumentOnLoadCompletedInMainFrame() {}
+    virtual void DidFinishNavigation(bool success) {}
 
-    // After this event, this HeadlessWebContents instance is ready to be
-    // controlled using a DevTools client.
-    virtual void WebContentsReady(){};
+    // Indicates that this HeadlessWebContents instance is now ready to be
+    // inspected using a HeadlessDevToolsClient.
+    virtual void DevToolsTargetReady() {}
 
    protected:
     Observer() {}
@@ -43,6 +44,11 @@
   virtual void AddObserver(Observer* observer) = 0;
   virtual void RemoveObserver(Observer* observer) = 0;
 
+  // Return a DevTools target corresponding to this tab. Note that this method
+  // won't return a valid value until Observer::DevToolsTargetReady has been
+  // signaled.
+  virtual HeadlessDevToolsTarget* GetDevToolsTarget() = 0;
+
  private:
   friend class HeadlessWebContentsImpl;
   HeadlessWebContents() {}
diff --git a/headless/public/internal/message_dispatcher.h b/headless/public/internal/message_dispatcher.h
new file mode 100644
index 0000000..32352f4
--- /dev/null
+++ b/headless/public/internal/message_dispatcher.h
@@ -0,0 +1,31 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef HEADLESS_PUBLIC_INTERNAL_MESSAGE_DISPATCHER_H_
+#define HEADLESS_PUBLIC_INTERNAL_MESSAGE_DISPATCHER_H_
+
+namespace headless {
+namespace internal {
+
+// An internal interface for sending DevTools messages from the domain agents.
+class MessageDispatcher {
+ public:
+  virtual void SendMessage(
+      const char* method,
+      std::unique_ptr<base::Value> params,
+      base::Callback<void(const base::Value&)> callback) = 0;
+  virtual void SendMessage(const char* method,
+                           std::unique_ptr<base::Value> params,
+                           base::Callback<void()> callback) = 0;
+  virtual void SendMessage(
+      const char* method,
+      base::Callback<void(const base::Value&)> callback) = 0;
+  virtual void SendMessage(const char* method,
+                           base::Callback<void()> callback) = 0;
+};
+
+}  // namespace internal
+}  // namespace headless
+
+#endif  // HEADLESS_PUBLIC_INTERNAL_MESSAGE_DISPATCHER_H_
diff --git a/headless/public/internal/value_conversions.h b/headless/public/internal/value_conversions.h
new file mode 100644
index 0000000..17c6eda
--- /dev/null
+++ b/headless/public/internal/value_conversions.h
@@ -0,0 +1,163 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef HEADLESS_PUBLIC_INTERNAL_VALUE_CONVERSIONS_H_
+#define HEADLESS_PUBLIC_INTERNAL_VALUE_CONVERSIONS_H_
+
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#include "headless/public/util/error_reporter.h"
+
+namespace headless {
+namespace internal {
+
+// Generic conversion from a type to a base::Value. Implemented in
+// type_conversions.h after all type-specific ToValueImpls have been defined.
+template <typename T>
+std::unique_ptr<base::Value> ToValue(const T& value);
+
+// Generic conversion from a base::Value to a type. Note that this generic
+// variant is never defined. Instead, we declare a specific template
+// specialization for all the used types.
+template <typename T>
+struct FromValue {
+  static std::unique_ptr<T> Parse(const base::Value& value,
+                                  ErrorReporter* errors);
+};
+
+// ToValueImpl is a helper used by the ToValue template for dispatching into
+// type-specific serializers. It uses a dummy |T*| argument as a way to
+// partially specialize vector types.
+template <typename T>
+std::unique_ptr<base::Value> ToValueImpl(int value, T*) {
+  return base::WrapUnique(new base::FundamentalValue(value));
+}
+
+template <typename T>
+std::unique_ptr<base::Value> ToValueImpl(double value, T*) {
+  return base::WrapUnique(new base::FundamentalValue(value));
+}
+
+template <typename T>
+std::unique_ptr<base::Value> ToValueImpl(bool value, T*) {
+  return base::WrapUnique(new base::FundamentalValue(value));
+}
+
+template <typename T>
+std::unique_ptr<base::Value> ToValueImpl(const std::string& value, T*) {
+  return base::WrapUnique(new base::StringValue(value));
+}
+
+template <typename T>
+std::unique_ptr<base::Value> ToValueImpl(const base::Value& value, T*) {
+  return value.CreateDeepCopy();
+}
+
+template <typename T>
+std::unique_ptr<base::Value> ToValueImpl(const std::vector<T>& vector,
+                                         const std::vector<T>*) {
+  std::unique_ptr<base::ListValue> result(new base::ListValue());
+  for (const auto& it : vector)
+    result->Append(ToValue(it));
+  return std::move(result);
+}
+
+template <typename T>
+std::unique_ptr<base::Value> ToValueImpl(const std::unique_ptr<T>& value,
+                                         std::unique_ptr<T>*) {
+  return ToValue(value.get());
+}
+
+// FromValue specializations for basic types.
+template <>
+struct FromValue<bool> {
+  static bool Parse(const base::Value& value, ErrorReporter* errors) {
+    bool result = false;
+    if (!value.GetAsBoolean(&result))
+      errors->AddError("boolean value expected");
+    return result;
+  }
+};
+
+template <>
+struct FromValue<int> {
+  static int Parse(const base::Value& value, ErrorReporter* errors) {
+    int result = 0;
+    if (!value.GetAsInteger(&result))
+      errors->AddError("integer value expected");
+    return result;
+  }
+};
+
+template <>
+struct FromValue<double> {
+  static double Parse(const base::Value& value, ErrorReporter* errors) {
+    double result = 0;
+    if (!value.GetAsDouble(&result))
+      errors->AddError("double value expected");
+    return result;
+  }
+};
+
+template <>
+struct FromValue<std::string> {
+  static std::string Parse(const base::Value& value, ErrorReporter* errors) {
+    std::string result;
+    if (!value.GetAsString(&result))
+      errors->AddError("string value expected");
+    return result;
+  }
+};
+
+template <>
+struct FromValue<base::DictionaryValue> {
+  static std::unique_ptr<base::DictionaryValue> Parse(const base::Value& value,
+                                                      ErrorReporter* errors) {
+    const base::DictionaryValue* result;
+    if (!value.GetAsDictionary(&result)) {
+      errors->AddError("dictionary value expected");
+      return nullptr;
+    }
+    return result->CreateDeepCopy();
+  }
+};
+
+template <>
+struct FromValue<base::Value> {
+  static std::unique_ptr<base::Value> Parse(const base::Value& value,
+                                            ErrorReporter* errors) {
+    return value.CreateDeepCopy();
+  }
+};
+
+template <typename T>
+struct FromValue<std::unique_ptr<T>> {
+  static std::unique_ptr<T> Parse(const base::Value& value,
+                                  ErrorReporter* errors) {
+    return FromValue<T>::Parse(value, errors);
+  }
+};
+
+template <typename T>
+struct FromValue<std::vector<T>> {
+  static std::vector<T> Parse(const base::Value& value, ErrorReporter* errors) {
+    std::vector<T> result;
+    const base::ListValue* list;
+    if (!value.GetAsList(&list)) {
+      errors->AddError("list value expected");
+      return result;
+    }
+    errors->Push();
+    for (const auto& item : *list)
+      result.push_back(FromValue<T>::Parse(*item, errors));
+    errors->Pop();
+    return result;
+  }
+};
+
+}  // namespace internal
+}  // namespace headless
+
+#endif  // HEADLESS_PUBLIC_INTERNAL_VALUE_CONVERSIONS_H_
diff --git a/headless/public/util/maybe.h b/headless/public/util/maybe.h
deleted file mode 100644
index 18540a36..0000000
--- a/headless/public/util/maybe.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef HEADLESS_PUBLIC_UTIL_MAYBE_H_
-#define HEADLESS_PUBLIC_UTIL_MAYBE_H_
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/macros.h"
-
-namespace headless {
-
-// A simple Maybe which may or may not have a value. Based on v8::Maybe.
-template <typename T>
-class Maybe {
- public:
-  Maybe() : has_value_(false) {}
-
-  bool IsNothing() const { return !has_value_; }
-  bool IsJust() const { return has_value_; }
-
-  // Will crash if the Maybe<> is nothing.
-  T& FromJust() {
-    DCHECK(IsJust());
-    return value_;
-  }
-  const T& FromJust() const {
-    DCHECK(IsJust());
-    return value_;
-  }
-
-  T FromMaybe(const T& default_value) const {
-    return has_value_ ? value_ : default_value;
-  }
-
-  bool operator==(const Maybe& other) const {
-    return (IsJust() == other.IsJust()) &&
-           (!IsJust() || FromJust() == other.FromJust());
-  }
-
-  bool operator!=(const Maybe& other) const { return !operator==(other); }
-
-  Maybe& operator=(Maybe&& other) {
-    has_value_ = other.has_value_;
-    value_ = std::move(other.value_);
-    return *this;
-  }
-
-  Maybe& operator=(const Maybe& other) {
-    has_value_ = other.has_value_;
-    value_ = other.value_;
-    return *this;
-  }
-
-  Maybe(const Maybe& other) = default;
-  Maybe(Maybe&& other) = default;
-
- private:
-  template <class U>
-  friend Maybe<U> Nothing();
-  template <class U>
-  friend Maybe<U> Just(const U& u);
-  template <class U>
-  friend Maybe<typename std::remove_reference<U>::type> Just(U&& u);
-
-  explicit Maybe(const T& t) : has_value_(true), value_(t) {}
-  explicit Maybe(T&& t) : has_value_(true), value_(std::move(t)) {}
-
-  bool has_value_;
-  T value_;
-};
-
-template <class T>
-Maybe<T> Nothing() {
-  return Maybe<T>();
-}
-
-template <class T>
-Maybe<T> Just(const T& t) {
-  return Maybe<T>(t);
-}
-
-template <class T>
-Maybe<typename std::remove_reference<T>::type> Just(T&& t) {
-  return Maybe<typename std::remove_reference<T>::type>(std::move(t));
-}
-
-}  // namespace headless
-
-#endif  // HEADLESS_PUBLIC_UTIL_MAYBE_H_
diff --git a/headless/public/util/maybe_unittest.cc b/headless/public/util/maybe_unittest.cc
deleted file mode 100644
index fb926961..0000000
--- a/headless/public/util/maybe_unittest.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "headless/public/util/maybe.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace headless {
-namespace {
-
-class MoveOnlyType {
- public:
-  MoveOnlyType() {}
-  MoveOnlyType(MoveOnlyType&& other) {}
-
-  void operator=(MoveOnlyType&& other) {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MoveOnlyType);
-};
-
-}  // namespace
-
-TEST(MaybeTest, Nothing) {
-  Maybe<int> maybe;
-  EXPECT_TRUE(maybe.IsNothing());
-  EXPECT_FALSE(maybe.IsJust());
-}
-
-TEST(MaybeTest, Just) {
-  Maybe<int> maybe = Just(1);
-  EXPECT_FALSE(maybe.IsNothing());
-  EXPECT_TRUE(maybe.IsJust());
-  EXPECT_EQ(1, maybe.FromJust());
-
-  const Maybe<int> const_maybe = Just(2);
-  EXPECT_EQ(2, const_maybe.FromJust());
-}
-
-TEST(MaybeTest, Equality) {
-  Maybe<int> a;
-  Maybe<int> b;
-  EXPECT_EQ(a, b);
-  EXPECT_EQ(b, a);
-
-  a = Just(1);
-  EXPECT_NE(a, b);
-  EXPECT_NE(b, a);
-
-  b = Just(2);
-  EXPECT_NE(a, b);
-  EXPECT_NE(b, a);
-
-  b = Just(1);
-  EXPECT_EQ(a, b);
-  EXPECT_EQ(b, a);
-}
-
-TEST(MaybeTest, Assignment) {
-  Maybe<int> a = Just(1);
-  Maybe<int> b = Nothing<int>();
-  EXPECT_NE(a, b);
-
-  b = a;
-  EXPECT_EQ(a, b);
-}
-
-TEST(MaybeTest, MoveOnlyType) {
-  MoveOnlyType value;
-  Maybe<MoveOnlyType> a = Just(std::move(value));
-  EXPECT_TRUE(a.IsJust());
-
-  Maybe<MoveOnlyType> b = Just(MoveOnlyType());
-  EXPECT_TRUE(b.IsJust());
-
-  Maybe<MoveOnlyType> c = Nothing<MoveOnlyType>();
-  c = std::move(a);
-  EXPECT_TRUE(c.IsJust());
-
-  MoveOnlyType d = std::move(b.FromJust());
-}
-
-}  // namespace headless
diff --git a/headless/test/headless_browser_test.cc b/headless/test/headless_browser_test.cc
index 0525782..2424231 100644
--- a/headless/test/headless_browser_test.cc
+++ b/headless/test/headless_browser_test.cc
@@ -98,6 +98,7 @@
 void HeadlessBrowserTest::RunAsynchronousTest() {
   base::MessageLoop::ScopedNestableTaskAllower nestable_allower(
       base::MessageLoop::current());
+  EXPECT_FALSE(run_loop_);
   run_loop_ = base::WrapUnique(new base::RunLoop());
   run_loop_->Run();
   run_loop_ = nullptr;
diff --git a/ios/chrome/browser/ios_chrome_io_thread.mm b/ios/chrome/browser/ios_chrome_io_thread.mm
index 763c028..f0fa384 100644
--- a/ios/chrome/browser/ios_chrome_io_thread.mm
+++ b/ios/chrome/browser/ios_chrome_io_thread.mm
@@ -54,7 +54,6 @@
 #include "net/cert/ct_verifier.h"
 #include "net/cert/multi_log_ct_verifier.h"
 #include "net/cert/multi_threaded_cert_verifier.h"
-#include "net/cert_net/nss_ocsp.h"
 #include "net/cookies/cookie_monster.h"
 #include "net/cookies/cookie_store.h"
 #include "net/dns/host_cache.h"
@@ -146,17 +145,11 @@
 class SystemURLRequestContext : public net::URLRequestContext {
  public:
   SystemURLRequestContext() {
-#if defined(USE_NSS_VERIFIER)
-    net::SetURLRequestContextForNSSHttpIO(this);
-#endif
   }
 
  private:
   ~SystemURLRequestContext() override {
     AssertNoURLRequests();
-#if defined(USE_NSS_VERIFIER)
-    net::SetURLRequestContextForNSSHttpIO(nullptr);
-#endif
   }
 };
 
@@ -389,10 +382,6 @@
   TRACE_EVENT0("startup", "IOSChromeIOThread::Init");
   DCHECK_CURRENTLY_ON(web::WebThread::IO);
 
-#if defined(USE_NSS_VERIFIER)
-  net::SetMessageLoopForNSSHttpIO();
-#endif
-
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
 
@@ -491,10 +480,6 @@
 }
 
 void IOSChromeIOThread::CleanUp() {
-#if defined(USE_NSS_VERIFIER)
-  net::ShutdownNSSHttpIO();
-#endif
-
   system_url_request_context_getter_ = nullptr;
 
   // Release objects that the net::URLRequestContext could have been pointing
diff --git a/ios/chrome/common/material_timing.h b/ios/chrome/common/material_timing.h
index 035128a..5e433671 100644
--- a/ios/chrome/common/material_timing.h
+++ b/ios/chrome/common/material_timing.h
@@ -36,16 +36,21 @@
 // Returns a timing funtion related to the given |curve|.
 CAMediaTimingFunction* TimingFunction(Curve curve);
 
+}  // material
+}  // ios
+
+@interface UIView (CrMaterialAnimations)
+
 // Performs a standard UIView animation using a material timing |curve|.
 // Note: any curve option specified in |options| will be ignored in favor of the
 // specified curve value.
 // See also: +[UIView animateWithDuration:delay:animations:completion].
-void Animate(NSTimeInterval duration,
-             NSTimeInterval delay,
-             Curve curve,
-             UIViewAnimationOptions options,
-             void (^animations)(void),
-             void (^completion)(BOOL));
++ (void)cr_animateWithDuration:(NSTimeInterval)duration
+                         delay:(NSTimeInterval)delay
+                         curve:(ios::material::Curve)curve
+                       options:(UIViewAnimationOptions)options
+                    animations:(void (^)(void))animations
+                    completion:(void (^)(BOOL finished))completion;
 
 // Performs a standard UIView transition animation using a material timing
 // |curve|.
@@ -53,14 +58,13 @@
 // specified curve value.
 // See also:
 // +[UIView transitionWithView:duration:options:animations:completion].
-void Transition(UIView* view,
-                NSTimeInterval duration,
-                Curve curve,
-                UIViewAnimationOptions options,
-                void (^animations)(void),
-                void (^completion)(BOOL));
++ (void)cr_transitionWithView:(UIView*)view
+                     duration:(NSTimeInterval)duration
+                        curve:(ios::material::Curve)curve
+                      options:(UIViewAnimationOptions)options
+                   animations:(void (^)(void))animations
+                   completion:(void (^)(BOOL finished))completion;
 
-}  // material
-}  // ios
+@end
 
 #endif  // IOS_CHROME_COMMON_MATERIAL_TIMING_H_
diff --git a/ios/chrome/common/material_timing.mm b/ios/chrome/common/material_timing.mm
index 4f81b49..d883aaca 100644
--- a/ios/chrome/common/material_timing.mm
+++ b/ios/chrome/common/material_timing.mm
@@ -67,12 +67,17 @@
   }
 }
 
-void Animate(NSTimeInterval duration,
-             NSTimeInterval delay,
-             Curve curve,
-             UIViewAnimationOptions options,
-             void (^animations)(void),
-             void (^completion)(BOOL)) {
+}  // material
+}  // ios
+
+@implementation UIView (CrMaterialAnimations)
+
++ (void)cr_animateWithDuration:(NSTimeInterval)duration
+                         delay:(NSTimeInterval)delay
+                         curve:(ios::material::Curve)curve
+                       options:(UIViewAnimationOptions)options
+                    animations:(void (^)(void))animations
+                    completion:(void (^)(BOOL finished))completion {
   [CATransaction begin];
   [CATransaction setAnimationTimingFunction:TimingFunction(curve)];
   [UIView animateWithDuration:duration
@@ -83,12 +88,12 @@
   [CATransaction commit];
 }
 
-void Transition(UIView* view,
-                NSTimeInterval duration,
-                Curve curve,
-                UIViewAnimationOptions options,
-                void (^animations)(void),
-                void (^completion)(BOOL)) {
++ (void)cr_transitionWithView:(UIView*)view
+                     duration:(NSTimeInterval)duration
+                        curve:(ios::material::Curve)curve
+                      options:(UIViewAnimationOptions)options
+                   animations:(void (^)(void))animations
+                   completion:(void (^)(BOOL finished))completion {
   [CATransaction begin];
   [CATransaction setAnimationTimingFunction:TimingFunction(curve)];
   [UIView transitionWithView:view
@@ -99,5 +104,4 @@
   [CATransaction commit];
 }
 
-}  // material
-}  // ios
+@end
diff --git a/ios/crnet/crnet_environment.mm b/ios/crnet/crnet_environment.mm
index b564111..f8c98ed 100644
--- a/ios/crnet/crnet_environment.mm
+++ b/ios/crnet/crnet_environment.mm
@@ -26,7 +26,6 @@
 #include "base/threading/worker_pool.h"
 #include "components/prefs/json_pref_store.h"
 #include "components/prefs/pref_filter.h"
-#include "crypto/nss_util.h"
 #include "ios/crnet/sdch_owner_pref_storage.h"
 #include "ios/net/cookies/cookie_store_ios.h"
 #include "ios/net/crn_http_protocol_handler.h"
@@ -38,7 +37,6 @@
 #include "net/base/network_change_notifier.h"
 #include "net/base/sdch_manager.h"
 #include "net/cert/cert_verifier.h"
-#include "net/cert_net/nss_ocsp.h"
 #include "net/cookies/cookie_store.h"
 #include "net/http/http_auth_handler_factory.h"
 #include "net/http/http_cache.h"
@@ -154,14 +152,6 @@
   url::Initialize();
   base::CommandLine::Init(0, nullptr);
 
-#if defined(USE_NSS_VERIFIER)
-  // This needs to happen on the main thread. NSPR's initialization sets up its
-  // memory allocator; if this is not done before other threads are created,
-  // this initialization can race to cause accidental free/allocation
-  // mismatches.
-  crypto::EnsureNSPRInit();
-#endif
-
   // Without doing this, StatisticsRecorder::FactoryGet() leaks one histogram
   // per call after the first for a given name.
   base::StatisticsRecorder::Initialize();
@@ -292,9 +282,6 @@
   proxy_config_service_ = net::ProxyService::CreateSystemProxyConfigService(
       network_io_thread_->task_runner(), nullptr);
 
-#if defined(USE_NSS_VERIFIER)
-  net::SetURLRequestContextForNSSHttpIO(main_context_.get());
-#endif
   main_context_getter_ = new CrNetURLRequestContextGetter(
       main_context_.get(), network_io_thread_->task_runner());
   base::subtle::MemoryBarrier();
@@ -312,9 +299,6 @@
 
 CrNetEnvironment::~CrNetEnvironment() {
   net::HTTPProtocolHandlerDelegate::SetInstance(nullptr);
-#if defined(USE_NSS_VERIFIER)
-  net::SetURLRequestContextForNSSHttpIO(nullptr);
-#endif
 }
 
 net::URLRequestContextGetter* CrNetEnvironment::GetMainContextGetter() {
diff --git a/ios/web/app/web_main_loop.mm b/ios/web/app/web_main_loop.mm
index 017ffa4..f02ca85 100644
--- a/ios/web/app/web_main_loop.mm
+++ b/ios/web/app/web_main_loop.mm
@@ -19,7 +19,6 @@
 #include "base/process/process_metrics.h"
 #include "base/system_monitor/system_monitor.h"
 #include "base/threading/thread_restrictions.h"
-#include "crypto/nss_util.h"
 #include "ios/web/net/cookie_notification_bridge.h"
 #include "ios/web/public/app/web_main_parts.h"
 #include "ios/web/public/web_client.h"
@@ -52,14 +51,6 @@
 void WebMainLoop::EarlyInitialization() {
   if (parts_) {
     parts_->PreEarlyInitialization();
-  }
-
-#if defined(USE_NSS_VERIFIER)
-  // We want to be sure to init NSPR on the main thread.
-  crypto::EnsureNSPRInit();
-#endif
-
-  if (parts_) {
     parts_->PostEarlyInitialization();
   }
 }
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 0e282398..cbea3b80 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -160,77 +160,6 @@
       ]
     }
 
-    if (use_openssl) {
-      sources -= [
-        "base/nss_memio.c",
-        "base/nss_memio.h",
-        "cert/ct_log_verifier_nss.cc",
-        "cert/ct_objects_extractor_nss.cc",
-        "cert/jwk_serializer_nss.cc",
-        "cert/scoped_nss_types.h",
-        "cert/x509_util_nss.cc",
-        "quic/crypto/aead_base_decrypter_nss.cc",
-        "quic/crypto/aead_base_encrypter_nss.cc",
-        "quic/crypto/aes_128_gcm_12_decrypter_nss.cc",
-        "quic/crypto/aes_128_gcm_12_encrypter_nss.cc",
-        "quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc",
-        "quic/crypto/chacha20_poly1305_rfc7539_encrypter_nss.cc",
-        "quic/crypto/channel_id_nss.cc",
-        "quic/crypto/p256_key_exchange_nss.cc",
-        "quic/crypto/proof_source_chromium_nss.cc",
-        "socket/nss_ssl_util.cc",
-        "socket/nss_ssl_util.h",
-        "socket/ssl_client_socket_nss.cc",
-        "socket/ssl_client_socket_nss.h",
-        "socket/ssl_server_socket_nss.cc",
-        "socket/ssl_server_socket_nss.h",
-        "ssl/token_binding_nss.cc",
-      ]
-      if (is_ios) {
-        sources -= [
-          "cert/x509_util_ios.cc",
-          "cert/x509_util_ios.h",
-        ]
-      }
-    } else {
-      sources -= [
-        "cert/ct_log_verifier_openssl.cc",
-        "cert/ct_objects_extractor_openssl.cc",
-        "cert/jwk_serializer_openssl.cc",
-        "cert/x509_util_openssl.cc",
-        "cert/x509_util_openssl.h",
-        "quic/crypto/aead_base_decrypter_openssl.cc",
-        "quic/crypto/aead_base_encrypter_openssl.cc",
-        "quic/crypto/aes_128_gcm_12_decrypter_openssl.cc",
-        "quic/crypto/aes_128_gcm_12_encrypter_openssl.cc",
-        "quic/crypto/chacha20_poly1305_rfc7539_decrypter_openssl.cc",
-        "quic/crypto/chacha20_poly1305_rfc7539_encrypter_openssl.cc",
-        "quic/crypto/channel_id_openssl.cc",
-        "quic/crypto/p256_key_exchange_openssl.cc",
-        "quic/crypto/proof_source_chromium_openssl.cc",
-        "quic/crypto/scoped_evp_aead_ctx.cc",
-        "quic/crypto/scoped_evp_aead_ctx.h",
-        "socket/ssl_client_socket_openssl.cc",
-        "socket/ssl_client_socket_openssl.h",
-        "socket/ssl_server_socket_openssl.cc",
-        "socket/ssl_server_socket_openssl.h",
-        "ssl/openssl_ssl_util.cc",
-        "ssl/openssl_ssl_util.h",
-        "ssl/ssl_client_session_cache_openssl.cc",
-        "ssl/ssl_client_session_cache_openssl.h",
-        "ssl/ssl_key_logger.cc",
-        "ssl/ssl_key_logger.h",
-        "ssl/ssl_platform_key.h",
-        "ssl/ssl_platform_key_task_runner.cc",
-        "ssl/ssl_platform_key_task_runner.h",
-        "ssl/test_ssl_private_key.cc",
-        "ssl/test_ssl_private_key.h",
-        "ssl/threaded_ssl_private_key.cc",
-        "ssl/threaded_ssl_private_key.h",
-        "ssl/token_binding_openssl.cc",
-      ]
-    }
-
     if (!use_openssl_certs) {
       sources -= [
         "base/crypto_module_openssl.cc",
@@ -302,40 +231,26 @@
         "ssl/client_key_store.h",
         "ssl/ssl_platform_key_nss.cc",
       ]
-    } else if (use_openssl) {
+    } else {
       # client_cert_store_nss.c requires NSS_CmpCertChainWCANames from NSS's
       # libssl, but our bundled copy is not built in OpenSSL ports. Pull that
       # file in directly.
       sources += [ "third_party/nss/ssl/cmpcert.c" ]
     }
 
-    if (!use_nss_verifier) {
+    if (!use_nss_certs) {
       # These files are part of the partial implementation of NSS for
       # cert verification, so keep them in that case.
       sources -= [
         "cert/cert_verify_proc_nss.cc",
         "cert/cert_verify_proc_nss.h",
         "cert/test_root_certs_nss.cc",
-        "cert/x509_util_nss_certs.cc",
+        "cert/x509_util_nss.cc",
         "cert_net/nss_ocsp.cc",
         "cert_net/nss_ocsp.h",
       ]
     }
 
-    if (is_ios && use_nss_verifier) {
-      sources -= [
-        "cert/cert_verify_proc_ios.cc",
-        "cert/cert_verify_proc_ios.h",
-        "cert/x509_certificate_openssl_ios.cc",
-      ]
-
-      deps += [
-        "//net/third_party/nss/ssl:libssl",
-        "//third_party/nss",
-        "//third_party/nss:nspr",
-      ]
-    }
-
     if (is_chromecast && use_nss_certs) {
       sources += [ "ssl/ssl_platform_key_chromecast.cc" ]
       sources -= [ "ssl/ssl_platform_key_nss.cc" ]
@@ -380,6 +295,7 @@
         "base/network_interfaces_mac.cc",
         "base/network_interfaces_mac.h",
         "base/platform_mime_util_mac.mm",
+        "cert/test_root_certs_mac.cc",
         "proxy/proxy_resolver_mac.cc",
         "proxy/proxy_server_mac.cc",
       ]
@@ -387,11 +303,6 @@
       sources -= [ "disk_cache/blockfile/file_posix.cc" ]
     }
 
-    if (is_ios && !use_nss_verifier) {
-      net_unfiltered_sources += [ "cert/test_root_certs_mac.cc" ]
-      sources -= [ "cert/x509_certificate_ios.cc" ]
-    }
-
     if (is_ios || is_mac) {
       sources += gypi_values.net_base_mac_ios_sources
     }
@@ -721,7 +632,7 @@
     public_deps += [ "//third_party/protobuf:py_proto" ]
   }
 
-  if (use_nss_verifier) {
+  if (use_nss_certs) {
     public_deps += [ "//crypto:platform" ]
   }
 
@@ -1462,11 +1373,9 @@
   data = [
     "data/",
   ]
-  data_deps = []
-
-  if (use_openssl) {
-    data_deps += [ "third_party/nist-pkits/" ]
-  }
+  data_deps = [
+    "third_party/nist-pkits/",
+  ]
 
   if (is_linux || is_mac || is_win) {
     deps += [
@@ -1525,15 +1434,6 @@
     }
   }
 
-  if (use_openssl) {
-    sources -= [ "quic/test_tools/crypto_test_utils_nss.cc" ]
-  } else {
-    sources -= [
-      "quic/test_tools/crypto_test_utils_openssl.cc",
-      "ssl/ssl_client_session_cache_openssl_unittest.cc",
-    ]
-  }
-
   if (use_kerberos) {
     defines += [ "USE_KERBEROS" ]
   }
@@ -1551,7 +1451,7 @@
     sources -= [ "http/http_auth_handler_negotiate_unittest.cc" ]
   }
 
-  if (!use_nss_verifier) {
+  if (!use_nss_certs) {
     # Only include this test when using NSS for cert verification.
     sources -= [ "cert_net/nss_ocsp_unittest.cc" ]
   }
diff --git a/net/base/nss_memio.c b/net/base/nss_memio.c
deleted file mode 100644
index 895b7b2..0000000
--- a/net/base/nss_memio.c
+++ /dev/null
@@ -1,541 +0,0 @@
-// Copyright (c) 2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-// Written in NSPR style to also be suitable for adding to the NSS demo suite
-
-/* memio is a simple NSPR I/O layer that lets you decouple NSS from
- * the real network.  It's rather like openssl's memory bio,
- * and is useful when your app absolutely, positively doesn't
- * want to let NSS do its own networking.
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <prerror.h>
-#include <prinit.h>
-#include <prlog.h>
-
-#include "nss_memio.h"
-
-/*--------------- private memio types -----------------------*/
-
-/*----------------------------------------------------------------------
- Simple private circular buffer class.  Size cannot be changed once allocated.
-----------------------------------------------------------------------*/
-
-struct memio_buffer {
-    int head;     /* where to take next byte out of buf */
-    int tail;     /* where to put next byte into buf */
-    int bufsize;  /* number of bytes allocated to buf */
-    /* TODO(port): error handling is pessimistic right now.
-     * Once an error is set, the socket is considered broken
-     * (PR_WOULD_BLOCK_ERROR not included).
-     */
-    PRErrorCode last_err;
-    char *buf;
-};
-
-
-/* The 'secret' field of a PRFileDesc created by memio_CreateIOLayer points
- * to one of these.
- * In the public header, we use struct memio_Private as a typesafe alias
- * for this.  This causes a few ugly typecasts in the private file, but
- * seems safer.
- */
-struct PRFilePrivate {
-    /* read requests are satisfied from this buffer */
-    struct memio_buffer readbuf;
-
-    /* write requests are satisfied from this buffer */
-    struct memio_buffer writebuf;
-
-    /* SSL needs to know socket peer's name */
-    PRNetAddr peername;
-
-    /* if set, empty I/O returns EOF instead of EWOULDBLOCK */
-    int eof;
-
-    /* if set, the number of bytes requested from readbuf that were not
-     * fulfilled (due to readbuf being empty) */
-    int read_requested;
-};
-
-/*--------------- private memio_buffer functions ---------------------*/
-
-/* Forward declarations.  */
-
-/* Allocate a memio_buffer of given size. */
-static void memio_buffer_new(struct memio_buffer *mb, int size);
-
-/* Deallocate a memio_buffer allocated by memio_buffer_new. */
-static void memio_buffer_destroy(struct memio_buffer *mb);
-
-/* How many bytes can be read out of the buffer without wrapping */
-static int memio_buffer_used_contiguous(const struct memio_buffer *mb);
-
-/* How many bytes exist after the wrap? */
-static int memio_buffer_wrapped_bytes(const struct memio_buffer *mb);
-
-/* How many bytes can be written into the buffer without wrapping */
-static int memio_buffer_unused_contiguous(const struct memio_buffer *mb);
-
-/* Write n bytes into the buffer.  Returns number of bytes written. */
-static int memio_buffer_put(struct memio_buffer *mb, const char *buf, int n);
-
-/* Read n bytes from the buffer.  Returns number of bytes read. */
-static int memio_buffer_get(struct memio_buffer *mb, char *buf, int n);
-
-/* Allocate a memio_buffer of given size. */
-static void memio_buffer_new(struct memio_buffer *mb, int size)
-{
-    mb->head = 0;
-    mb->tail = 0;
-    mb->bufsize = size;
-    mb->buf = malloc(size);
-}
-
-/* Deallocate a memio_buffer allocated by memio_buffer_new. */
-static void memio_buffer_destroy(struct memio_buffer *mb)
-{
-    free(mb->buf);
-    mb->buf = NULL;
-    mb->bufsize = 0;
-    mb->head = 0;
-    mb->tail = 0;
-}
-
-/* How many bytes can be read out of the buffer without wrapping */
-static int memio_buffer_used_contiguous(const struct memio_buffer *mb)
-{
-    return (((mb->tail >= mb->head) ? mb->tail : mb->bufsize) - mb->head);
-}
-
-/* How many bytes exist after the wrap? */
-static int memio_buffer_wrapped_bytes(const struct memio_buffer *mb)
-{
-    return (mb->tail >= mb->head) ? 0 : mb->tail;
-}
-
-/* How many bytes can be written into the buffer without wrapping */
-static int memio_buffer_unused_contiguous(const struct memio_buffer *mb)
-{
-    if (mb->head > mb->tail) return mb->head - mb->tail - 1;
-    return mb->bufsize - mb->tail - (mb->head == 0);
-}
-
-/* Write n bytes into the buffer.  Returns number of bytes written. */
-static int memio_buffer_put(struct memio_buffer *mb, const char *buf, int n)
-{
-    int len;
-    int transferred = 0;
-
-    /* Handle part before wrap */
-    len = PR_MIN(n, memio_buffer_unused_contiguous(mb));
-    if (len > 0) {
-        /* Buffer not full */
-        memcpy(&mb->buf[mb->tail], buf, len);
-        mb->tail += len;
-        if (mb->tail == mb->bufsize)
-            mb->tail = 0;
-        n -= len;
-        buf += len;
-        transferred += len;
-
-        /* Handle part after wrap */
-        len = PR_MIN(n, memio_buffer_unused_contiguous(mb));
-        if (len > 0) {
-            /* Output buffer still not full, input buffer still not empty */
-            memcpy(&mb->buf[mb->tail], buf, len);
-            mb->tail += len;
-            if (mb->tail == mb->bufsize)
-                mb->tail = 0;
-            transferred += len;
-        }
-    }
-
-    return transferred;
-}
-
-
-/* Read n bytes from the buffer.  Returns number of bytes read. */
-static int memio_buffer_get(struct memio_buffer *mb, char *buf, int n)
-{
-    int len;
-    int transferred = 0;
-
-    /* Handle part before wrap */
-    len = PR_MIN(n, memio_buffer_used_contiguous(mb));
-    if (len) {
-        memcpy(buf, &mb->buf[mb->head], len);
-        mb->head += len;
-        if (mb->head == mb->bufsize)
-            mb->head = 0;
-        n -= len;
-        buf += len;
-        transferred += len;
-
-        /* Handle part after wrap */
-        len = PR_MIN(n, memio_buffer_used_contiguous(mb));
-        if (len) {
-            memcpy(buf, &mb->buf[mb->head], len);
-            mb->head += len;
-            if (mb->head == mb->bufsize)
-                mb->head = 0;
-            transferred += len;
-        }
-    }
-
-    return transferred;
-}
-
-/*--------------- private memio functions -----------------------*/
-
-static PRStatus PR_CALLBACK memio_Close(PRFileDesc *fd)
-{
-    struct PRFilePrivate *secret = fd->secret;
-    memio_buffer_destroy(&secret->readbuf);
-    memio_buffer_destroy(&secret->writebuf);
-    free(secret);
-    fd->dtor(fd);
-    return PR_SUCCESS;
-}
-
-static PRStatus PR_CALLBACK memio_Shutdown(PRFileDesc *fd, PRIntn how)
-{
-    /* TODO: pass shutdown status to app somehow */
-    return PR_SUCCESS;
-}
-
-/* If there was a network error in the past taking bytes
- * out of the buffer, return it to the next call that
- * tries to read from an empty buffer.
- */
-static int PR_CALLBACK memio_Recv(PRFileDesc *fd, void *buf, PRInt32 len,
-                                  PRIntn flags, PRIntervalTime timeout)
-{
-    struct PRFilePrivate *secret;
-    struct memio_buffer *mb;
-    int rv;
-
-    if (flags) {
-        PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
-        return -1;
-    }
-
-    secret = fd->secret;
-    mb = &secret->readbuf;
-    PR_ASSERT(mb->bufsize);
-    rv = memio_buffer_get(mb, buf, len);
-    if (rv == 0 && !secret->eof) {
-        secret->read_requested = len;
-        /* If there is no more data in the buffer, report any pending errors
-         * that were previously observed. Note that both the readbuf and the
-         * writebuf are checked for errors, since the application may have
-         * encountered a socket error while writing that would otherwise not
-         * be reported until the application attempted to write again - which
-         * it may never do.
-         */
-        if (mb->last_err)
-            PR_SetError(mb->last_err, 0);
-        else if (secret->writebuf.last_err)
-            PR_SetError(secret->writebuf.last_err, 0);
-        else
-            PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
-        return -1;
-    }
-
-    secret->read_requested = 0;
-    return rv;
-}
-
-static int PR_CALLBACK memio_Read(PRFileDesc *fd, void *buf, PRInt32 len)
-{
-    /* pull bytes from buffer */
-    return memio_Recv(fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT);
-}
-
-static int PR_CALLBACK memio_Send(PRFileDesc *fd, const void *buf, PRInt32 len,
-                                  PRIntn flags, PRIntervalTime timeout)
-{
-    struct PRFilePrivate *secret;
-    struct memio_buffer *mb;
-    int rv;
-
-    secret = fd->secret;
-    mb = &secret->writebuf;
-    PR_ASSERT(mb->bufsize);
-
-    /* Note that the read error state is not reported, because it cannot be
-     * reported until all buffered data has been read. If there is an error
-     * with the next layer, attempting to call Send again will report the
-     * error appropriately.
-     */
-    if (mb->last_err) {
-        PR_SetError(mb->last_err, 0);
-        return -1;
-    }
-    rv = memio_buffer_put(mb, buf, len);
-    if (rv == 0) {
-        PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
-        return -1;
-    }
-    return rv;
-}
-
-static int PR_CALLBACK memio_Write(PRFileDesc *fd, const void *buf, PRInt32 len)
-{
-    /* append bytes to buffer */
-    return memio_Send(fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT);
-}
-
-static PRStatus PR_CALLBACK memio_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
-{
-    /* TODO: fail if memio_SetPeerName has not been called */
-    struct PRFilePrivate *secret = fd->secret;
-    *addr = secret->peername;
-    return PR_SUCCESS;
-}
-
-static PRStatus memio_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)
-{
-    /*
-     * Even in the original version for real tcp sockets,
-     * PR_SockOpt_Nonblocking is a special case that does not
-     * translate to a getsockopt() call
-     */
-    if (PR_SockOpt_Nonblocking == data->option) {
-        data->value.non_blocking = PR_TRUE;
-        return PR_SUCCESS;
-    }
-    PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0);
-    return PR_FAILURE;
-}
-
-/*--------------- private memio data -----------------------*/
-
-/*
- * Implement just the bare minimum number of methods needed to make ssl happy.
- *
- * Oddly, PR_Recv calls ssl_Recv calls ssl_SocketIsBlocking calls
- * PR_GetSocketOption, so we have to provide an implementation of
- * PR_GetSocketOption that just says "I'm nonblocking".
- */
-
-static struct PRIOMethods  memio_layer_methods = {
-    PR_DESC_LAYERED,
-    memio_Close,
-    memio_Read,
-    memio_Write,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    memio_Shutdown,
-    memio_Recv,
-    memio_Send,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    memio_GetPeerName,
-    NULL,
-    NULL,
-    memio_GetSocketOption,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-};
-
-static PRDescIdentity memio_identity = PR_INVALID_IO_LAYER;
-
-static PRStatus memio_InitializeLayerName(void)
-{
-    memio_identity = PR_GetUniqueIdentity("memio");
-    return PR_SUCCESS;
-}
-
-/*--------------- public memio functions -----------------------*/
-
-PRFileDesc *memio_CreateIOLayer(int readbufsize, int writebufsize)
-{
-    PRFileDesc *fd;
-    struct PRFilePrivate *secret;
-    static PRCallOnceType once;
-
-    PR_CallOnce(&once, memio_InitializeLayerName);
-
-    fd = PR_CreateIOLayerStub(memio_identity, &memio_layer_methods);
-    secret = malloc(sizeof(struct PRFilePrivate));
-    memset(secret, 0, sizeof(*secret));
-
-    memio_buffer_new(&secret->readbuf, readbufsize);
-    memio_buffer_new(&secret->writebuf, writebufsize);
-    fd->secret = secret;
-    return fd;
-}
-
-void memio_SetPeerName(PRFileDesc *fd, const PRNetAddr *peername)
-{
-    PRFileDesc *memiofd = PR_GetIdentitiesLayer(fd, memio_identity);
-    struct PRFilePrivate *secret = memiofd->secret;
-    secret->peername = *peername;
-}
-
-memio_Private *memio_GetSecret(PRFileDesc *fd)
-{
-    PRFileDesc *memiofd = PR_GetIdentitiesLayer(fd, memio_identity);
-    struct PRFilePrivate *secret =  memiofd->secret;
-    return (memio_Private *)secret;
-}
-
-int memio_GetReadRequest(memio_Private *secret)
-{
-    return ((PRFilePrivate *)secret)->read_requested;
-}
-
-int memio_GetReadParams(memio_Private *secret, char **buf)
-{
-    struct memio_buffer* mb = &((PRFilePrivate *)secret)->readbuf;
-    PR_ASSERT(mb->bufsize);
-
-    *buf = &mb->buf[mb->tail];
-    return memio_buffer_unused_contiguous(mb);
-}
-
-int memio_GetReadableBufferSize(memio_Private *secret)
-{
-    struct memio_buffer* mb = &((PRFilePrivate *)secret)->readbuf;
-    PR_ASSERT(mb->bufsize);
-
-    return memio_buffer_used_contiguous(mb);
-}
-
-void memio_PutReadResult(memio_Private *secret, int bytes_read)
-{
-    struct memio_buffer* mb = &((PRFilePrivate *)secret)->readbuf;
-    PR_ASSERT(mb->bufsize);
-
-    if (bytes_read > 0) {
-        mb->tail += bytes_read;
-        if (mb->tail == mb->bufsize)
-            mb->tail = 0;
-    } else if (bytes_read == 0) {
-        /* Record EOF condition and report to caller when buffer runs dry */
-        ((PRFilePrivate *)secret)->eof = PR_TRUE;
-    } else /* if (bytes_read < 0) */ {
-        mb->last_err = bytes_read;
-    }
-
-    /* Clear read_requested now that the read has been satisfied. */
-    ((PRFilePrivate *)secret)->read_requested = 0;
-}
-
-int memio_GetWriteParams(memio_Private *secret,
-                         const char **buf1, unsigned int *len1,
-                         const char **buf2, unsigned int *len2)
-{
-    struct memio_buffer* mb = &((PRFilePrivate *)secret)->writebuf;
-    PR_ASSERT(mb->bufsize);
-
-    if (mb->last_err)
-        return mb->last_err;
-
-    *buf1 = &mb->buf[mb->head];
-    *len1 = memio_buffer_used_contiguous(mb);
-    *buf2 = mb->buf;
-    *len2 = memio_buffer_wrapped_bytes(mb);
-    return 0;
-}
-
-void memio_PutWriteResult(memio_Private *secret, int bytes_written)
-{
-    struct memio_buffer* mb = &((PRFilePrivate *)secret)->writebuf;
-    PR_ASSERT(mb->bufsize);
-
-    if (bytes_written > 0) {
-        mb->head += bytes_written;
-        if (mb->head >= mb->bufsize)
-            mb->head -= mb->bufsize;
-    } else if (bytes_written < 0) {
-        mb->last_err = bytes_written;
-    }
-}
-
-/*--------------- private memio_buffer self-test -----------------*/
-
-/* Even a trivial unit test is very helpful when doing circular buffers. */
-/*#define TRIVIAL_SELF_TEST*/
-#ifdef TRIVIAL_SELF_TEST
-#include <stdio.h>
-
-#define TEST_BUFLEN 7
-
-#define CHECKEQ(a, b) { \
-    if ((a) != (b)) { \
-        printf("%d != %d, Test failed line %d\n", a, b, __LINE__); \
-        exit(1); \
-    } \
-}
-
-int main()
-{
-    struct memio_buffer mb;
-    char buf[100];
-    int i;
-
-    memio_buffer_new(&mb, TEST_BUFLEN);
-
-    CHECKEQ(memio_buffer_unused_contiguous(&mb), TEST_BUFLEN-1);
-    CHECKEQ(memio_buffer_used_contiguous(&mb), 0);
-
-    CHECKEQ(memio_buffer_put(&mb, "howdy", 5), 5);
-
-    CHECKEQ(memio_buffer_unused_contiguous(&mb), TEST_BUFLEN-1-5);
-    CHECKEQ(memio_buffer_used_contiguous(&mb), 5);
-    CHECKEQ(memio_buffer_wrapped_bytes(&mb), 0);
-
-    CHECKEQ(memio_buffer_put(&mb, "!", 1), 1);
-
-    CHECKEQ(memio_buffer_unused_contiguous(&mb), 0);
-    CHECKEQ(memio_buffer_used_contiguous(&mb), 6);
-    CHECKEQ(memio_buffer_wrapped_bytes(&mb), 0);
-
-    CHECKEQ(memio_buffer_get(&mb, buf, 6), 6);
-    CHECKEQ(memcmp(buf, "howdy!", 6), 0);
-
-    CHECKEQ(memio_buffer_unused_contiguous(&mb), 1);
-    CHECKEQ(memio_buffer_used_contiguous(&mb), 0);
-
-    CHECKEQ(memio_buffer_put(&mb, "01234", 5), 5);
-
-    CHECKEQ(memio_buffer_used_contiguous(&mb), 1);
-    CHECKEQ(memio_buffer_wrapped_bytes(&mb), 4);
-    CHECKEQ(memio_buffer_unused_contiguous(&mb), TEST_BUFLEN-1-5);
-
-    CHECKEQ(memio_buffer_put(&mb, "5", 1), 1);
-
-    CHECKEQ(memio_buffer_unused_contiguous(&mb), 0);
-    CHECKEQ(memio_buffer_used_contiguous(&mb), 1);
-
-    /* TODO: add more cases */
-
-    printf("Test passed\n");
-    exit(0);
-}
-
-#endif
diff --git a/net/base/nss_memio.h b/net/base/nss_memio.h
deleted file mode 100644
index b2b873bd..0000000
--- a/net/base/nss_memio.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-// Written in NSPR style to also be suitable for adding to the NSS demo suite
-
-#ifndef __MEMIO_H
-#define __MEMIO_H
-
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "prio.h"
-
-/* Opaque structure.  Really just a more typesafe alias for PRFilePrivate. */
-struct memio_Private;
-typedef struct memio_Private memio_Private;
-
-/*----------------------------------------------------------------------
- NSPR I/O layer that terminates in a pair of circular buffers
- rather than talking to the real network.
- To use this with NSS:
- 1) call memio_CreateIOLayer to create a fake NSPR socket
- 2) call SSL_ImportFD to ssl-ify the socket
- 3) Do your own networking calls to set up a TCP connection
- 4) call memio_SetPeerName to tell NSS about the other end of the connection
- 5) While at the same time doing plaintext nonblocking NSPR I/O as
-    usual to the nspr file descriptor returned by SSL_ImportFD,
-    your app must shuttle encrypted data between
-    the real network and memio's network buffers.
-    memio_GetReadParams/memio_PutReadResult
-    are the hooks you need to pump data into memio's input buffer,
-    and memio_GetWriteParams/memio_PutWriteResult
-    are the hooks you need to pump data out of memio's output buffer.
-----------------------------------------------------------------------*/
-
-/* Create the I/O layer and its two circular buffers. */
-PRFileDesc *memio_CreateIOLayer(int readbufsize, int writebufsize);
-
-/* Must call before trying to make an ssl connection */
-void memio_SetPeerName(PRFileDesc *fd, const PRNetAddr *peername);
-
-/* Return a private pointer needed by the following
- * four functions.  (We could have passed a PRFileDesc to
- * them, but that would be slower.  Better for the caller
- * to grab the pointer once and cache it.
- * This may be a premature optimization.)
- */
-memio_Private *memio_GetSecret(PRFileDesc *fd);
-
-/* Ask memio how many bytes were requested by a higher layer if the
- * last attempt to read data resulted in PR_WOULD_BLOCK_ERROR, due to the
- * transport buffer being empty. If the last attempt to read data from the
- * memio did not result in PR_WOULD_BLOCK_ERROR, returns 0.
- */
-int memio_GetReadRequest(memio_Private *secret);
-
-/* Ask memio where to put bytes from the network, and how many it can handle.
- * Returns bytes available to write, or 0 if none available.
- * Puts current buffer position into *buf.
- */
-int memio_GetReadParams(memio_Private *secret, char **buf);
-
-/* Ask memio how many bytes are contained in the internal buffer.
- * Returns bytes available to read, or 0 if none available.
- */
-int memio_GetReadableBufferSize(memio_Private *secret);
-
-/* Tell memio how many bytes were read from the network.
- * If bytes_read is 0, causes EOF to be reported to
- * NSS after it reads the last byte from the circular buffer.
- * If bytes_read is < 0, it is treated as an NSPR error code.
- * See nspr/pr/src/md/unix/unix_errors.c for how to
- * map from Unix errors to NSPR error codes.
- * On EWOULDBLOCK or the equivalent, don't call this function.
- */
-void memio_PutReadResult(memio_Private *secret, int bytes_read);
-
-/* Ask memio what data it has to send to the network.
- * If there was previous a write error, the NSPR error code is returned.
- * Otherwise, it returns 0 and provides up to two buffers of data by
- * writing the positions and lengths into |buf1|, |len1| and |buf2|, |len2|.
- */
-int memio_GetWriteParams(memio_Private *secret,
-                         const char **buf1, unsigned int *len1,
-                         const char **buf2, unsigned int *len2);
-
-/* Tell memio how many bytes were sent to the network.
- * If bytes_written is < 0, it is treated as an NSPR error code.
- * See nspr/pr/src/md/unix/unix_errors.c for how to
- * map from Unix errors to NSPR error codes.
- * On EWOULDBLOCK or the equivalent, don't call this function.
- */
-void memio_PutWriteResult(memio_Private *secret, int bytes_written);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/net/cert/cert_verify_proc.cc b/net/cert/cert_verify_proc.cc
index 9c8267de..49a170d 100644
--- a/net/cert/cert_verify_proc.cc
+++ b/net/cert/cert_verify_proc.cc
@@ -26,7 +26,7 @@
 #include "net/cert/x509_certificate.h"
 #include "url/url_canon.h"
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
 #include "net/cert/cert_verify_proc_nss.h"
 #elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID)
 #include "net/cert/cert_verify_proc_openssl.h"
@@ -205,7 +205,7 @@
 
 // static
 CertVerifyProc* CertVerifyProc::CreateDefault() {
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
   return new CertVerifyProcNSS();
 #elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID)
   return new CertVerifyProcOpenSSL();
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc
index 6d01ef6..c7cf84d 100644
--- a/net/cert/cert_verify_proc_unittest.cc
+++ b/net/cert/cert_verify_proc_unittest.cc
@@ -103,7 +103,7 @@
   // the verified certificate chain and detect known roots.
   if (base::android::BuildInfo::GetInstance()->sdk_int() < 17)
     return false;
-#elif defined(OS_IOS) && defined(USE_OPENSSL)
+#elif defined(OS_IOS)
   // iOS does not expose the APIs necessary to get the known system roots.
   return false;
 #endif
@@ -224,7 +224,7 @@
                      NULL,
                      empty_cert_list_,
                      &verify_result);
-#if defined(USE_NSS_VERIFIER) || defined(OS_ANDROID)
+#if defined(USE_NSS_CERTS) || defined(OS_ANDROID)
   EXPECT_EQ(ERR_CERT_COMMON_NAME_INVALID, error);
 #elif defined(OS_IOS) && TARGET_IPHONE_SIMULATOR
   // iOS returns a ERR_CERT_INVALID error on the simulator, while returning
@@ -238,7 +238,7 @@
   // Either the system crypto library should correctly report a certificate
   // name mismatch, or our certificate blacklist should cause us to report an
   // invalid certificate.
-#if defined(USE_NSS_VERIFIER) || defined(OS_WIN)
+#if defined(USE_NSS_CERTS) || defined(OS_WIN)
   EXPECT_TRUE(verify_result.cert_status &
               (CERT_STATUS_COMMON_NAME_INVALID | CERT_STATUS_INVALID));
 #endif
@@ -1133,7 +1133,7 @@
   EXPECT_FALSE(verify_result.is_issued_by_known_root);
 }
 
-#if defined(USE_NSS_VERIFIER) || defined(OS_WIN) || \
+#if defined(USE_NSS_CERTS) || defined(OS_WIN) || \
     (defined(OS_MACOSX) && !defined(OS_IOS))
 // Test that CRLSets are effective in making a certificate appear to be
 // revoked.
diff --git a/net/cert/ct_log_verifier.h b/net/cert/ct_log_verifier.h
index 9f50c142..fa5ba24 100644
--- a/net/cert/ct_log_verifier.h
+++ b/net/cert/ct_log_verifier.h
@@ -16,11 +16,7 @@
 
 // Forward declare the crypto types to avoid having to include the full
 // headers.
-#if defined(USE_OPENSSL)
 typedef struct evp_pkey_st EVP_PKEY;
-#else
-typedef struct SECKEYPublicKeyStr SECKEYPublicKey;
-#endif
 
 namespace net {
 
@@ -98,11 +94,7 @@
   ct::DigitallySigned::HashAlgorithm hash_algorithm_;
   ct::DigitallySigned::SignatureAlgorithm signature_algorithm_;
 
-#if defined(USE_OPENSSL)
   EVP_PKEY* public_key_;
-#else
-  SECKEYPublicKey* public_key_;
-#endif
 };
 
 }  // namespace net
diff --git a/net/cert/ct_log_verifier_nss.cc b/net/cert/ct_log_verifier_nss.cc
deleted file mode 100644
index fec7dc8..0000000
--- a/net/cert/ct_log_verifier_nss.cc
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/cert/ct_log_verifier.h"
-
-#include <cryptohi.h>
-#include <keyhi.h>
-#include <nss.h>
-#include <pk11pub.h>
-#include <secitem.h>
-#include <secoid.h>
-
-#include "base/logging.h"
-#include "crypto/nss_util.h"
-#include "crypto/sha2.h"
-#include "net/cert/signed_tree_head.h"
-
-namespace net {
-
-namespace {
-
-SECOidTag GetNSSSigAlg(ct::DigitallySigned::SignatureAlgorithm alg) {
-  switch (alg) {
-    case ct::DigitallySigned::SIG_ALGO_RSA:
-      return SEC_OID_PKCS1_RSA_ENCRYPTION;
-    case ct::DigitallySigned::SIG_ALGO_DSA:
-      return SEC_OID_ANSIX9_DSA_SIGNATURE;
-    case ct::DigitallySigned::SIG_ALGO_ECDSA:
-      return SEC_OID_ANSIX962_EC_PUBLIC_KEY;
-    case ct::DigitallySigned::SIG_ALGO_ANONYMOUS:
-    default:
-      NOTREACHED();
-      return SEC_OID_UNKNOWN;
-  }
-}
-
-SECOidTag GetNSSHashAlg(ct::DigitallySigned::HashAlgorithm alg) {
-  switch (alg) {
-    case ct::DigitallySigned::HASH_ALGO_MD5:
-      return SEC_OID_MD5;
-    case ct::DigitallySigned::HASH_ALGO_SHA1:
-      return SEC_OID_SHA1;
-    case ct::DigitallySigned::HASH_ALGO_SHA224:
-      return SEC_OID_SHA224;
-    case ct::DigitallySigned::HASH_ALGO_SHA256:
-      return SEC_OID_SHA256;
-    case ct::DigitallySigned::HASH_ALGO_SHA384:
-      return SEC_OID_SHA384;
-    case ct::DigitallySigned::HASH_ALGO_SHA512:
-      return SEC_OID_SHA512;
-    case ct::DigitallySigned::HASH_ALGO_NONE:
-    default:
-      NOTREACHED();
-      return SEC_OID_UNKNOWN;
-  }
-}
-
-}  // namespace
-
-CTLogVerifier::~CTLogVerifier() {
-  if (public_key_)
-    SECKEY_DestroyPublicKey(public_key_);
-}
-
-bool CTLogVerifier::Init(const base::StringPiece& public_key) {
-  SECItem key_data;
-
-  crypto::EnsureNSSInit();
-
-  key_data.data = reinterpret_cast<unsigned char*>(
-      const_cast<char*>(public_key.data()));
-  key_data.len = public_key.size();
-
-  CERTSubjectPublicKeyInfo* public_key_info =
-      SECKEY_DecodeDERSubjectPublicKeyInfo(&key_data);
-  if (!public_key_info) {
-    DVLOG(1) << "Failed decoding public key.";
-    return false;
-  }
-
-  public_key_ = SECKEY_ExtractPublicKey(public_key_info);
-  SECKEY_DestroySubjectPublicKeyInfo(public_key_info);
-
-  if (!public_key_) {
-    DVLOG(1) << "Failed extracting public key.";
-    return false;
-  }
-
-  key_id_ = crypto::SHA256HashString(public_key);
-
-  // Right now, only RSASSA-PKCS1v15 with SHA-256 and ECDSA with SHA-256 are
-  // supported.
-  switch (SECKEY_GetPublicKeyType(public_key_)) {
-    case rsaKey:
-      hash_algorithm_ = ct::DigitallySigned::HASH_ALGO_SHA256;
-      signature_algorithm_ = ct::DigitallySigned::SIG_ALGO_RSA;
-      break;
-    case ecKey:
-      hash_algorithm_ = ct::DigitallySigned::HASH_ALGO_SHA256;
-      signature_algorithm_ = ct::DigitallySigned::SIG_ALGO_ECDSA;
-      break;
-    default:
-      DVLOG(1) << "Unsupported key type: "
-               << SECKEY_GetPublicKeyType(public_key_);
-      return false;
-  }
-
-  // Extra sanity check: Require RSA keys of at least 2048 bits.
-  if (signature_algorithm_ == ct::DigitallySigned::SIG_ALGO_RSA &&
-      SECKEY_PublicKeyStrengthInBits(public_key_) < 2048) {
-    DVLOG(1) << "Too small a public key.";
-    return false;
-  }
-
-  return true;
-}
-
-bool CTLogVerifier::VerifySignature(const base::StringPiece& data_to_sign,
-                                    const base::StringPiece& signature) const {
-  SECItem sig_data;
-  sig_data.data = reinterpret_cast<unsigned char*>(const_cast<char*>(
-      signature.data()));
-  sig_data.len = signature.size();
-
-  SECStatus rv = VFY_VerifyDataDirect(
-      reinterpret_cast<const unsigned char*>(data_to_sign.data()),
-      data_to_sign.size(), public_key_, &sig_data,
-      GetNSSSigAlg(signature_algorithm_), GetNSSHashAlg(hash_algorithm_),
-      NULL, NULL);
-  DVLOG(1) << "Signature verification result: " << (rv == SECSuccess);
-  return rv == SECSuccess;
-}
-
-}  // namespace net
diff --git a/net/cert/ct_objects_extractor_nss.cc b/net/cert/ct_objects_extractor_nss.cc
deleted file mode 100644
index 76a3be51..0000000
--- a/net/cert/ct_objects_extractor_nss.cc
+++ /dev/null
@@ -1,619 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/cert/ct_objects_extractor.h"
-
-#include <cert.h>
-#include <secasn1.h>
-#include <secitem.h>
-#include <secoid.h>
-
-#include "base/lazy_instance.h"
-#include "base/macros.h"
-#include "base/sha1.h"
-#include "crypto/scoped_nss_types.h"
-#include "crypto/sha2.h"
-#include "net/cert/asn1_util.h"
-#include "net/cert/scoped_nss_types.h"
-#include "net/cert/signed_certificate_timestamp.h"
-#include "net/der/input.h"
-#include "net/der/parser.h"
-
-namespace net {
-
-namespace ct {
-
-namespace {
-
-// NSS black magic to get the address of externally defined template at runtime.
-SEC_ASN1_MKSUB(SEC_IntegerTemplate)
-SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
-SEC_ASN1_MKSUB(SEC_GeneralizedTimeTemplate)
-SEC_ASN1_MKSUB(CERT_SequenceOfCertExtensionTemplate)
-
-// Wrapper class to convert a X509Certificate::OSCertHandle directly
-// into a CERTCertificate* usable with other NSS functions. This is used for
-// platforms where X509Certificate::OSCertHandle refers to a different type
-// than a CERTCertificate*.
-struct NSSCertWrapper {
-  explicit NSSCertWrapper(X509Certificate::OSCertHandle cert_handle);
-  ~NSSCertWrapper() {}
-
-  ScopedCERTCertificate cert;
-};
-
-NSSCertWrapper::NSSCertWrapper(X509Certificate::OSCertHandle cert_handle) {
-#if defined(USE_NSS_CERTS)
-  cert.reset(CERT_DupCertificate(cert_handle));
-#else
-  SECItem der_cert;
-  std::string der_data;
-  if (!X509Certificate::GetDEREncoded(cert_handle, &der_data))
-    return;
-  der_cert.data =
-      reinterpret_cast<unsigned char*>(const_cast<char*>(der_data.data()));
-  der_cert.len = der_data.size();
-
-  // Note: CERT_NewTempCertificate may return NULL if the certificate
-  // shares a serial number with another cert issued by the same CA,
-  // which is not supposed to happen.
-  cert.reset(CERT_NewTempCertificate(
-      CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE));
-#endif
-  DCHECK(cert.get() != NULL);
-}
-
-// The wire form of the OID 1.3.6.1.4.1.11129.2.4.2. See Section 3.3 of
-// RFC6962.
-const unsigned char kEmbeddedSCTOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01,
-                                         0xD6, 0x79, 0x02, 0x04, 0x02};
-const char kEmbeddedSCTDescription[] =
-    "X.509v3 Certificate Transparency Embedded Signed Certificate Timestamp "
-    "List";
-
-// The wire form of the OID 1.3.6.1.4.1.11129.2.4.5 - OCSP SingleExtension for
-// X.509v3 Certificate Transparency Signed Certificate Timestamp List, see
-// Section 3.3 of RFC6962.
-const unsigned char kOCSPExtensionOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01,
-                                           0xD6, 0x79, 0x02, 0x04, 0x05};
-
-const SECItem kOCSPExtensionOidItem = {
-  siBuffer, const_cast<unsigned char*>(kOCSPExtensionOid),
-  sizeof(kOCSPExtensionOid)
-};
-
-// id-ad-ocsp: 1.3.6.1.5.5.7.48.1.1
-const unsigned char kBasicOCSPResponseOid[] = {0x2B, 0x06, 0x01, 0x05, 0x05,
-                                               0x07, 0x30, 0x01, 0x01};
-
-const SECItem kBasicOCSPResponseOidItem = {
-  siBuffer, const_cast<unsigned char*>(kBasicOCSPResponseOid),
-  sizeof(kBasicOCSPResponseOid)
-};
-
-
-// Initializes the necessary NSS internals for use with Certificate
-// Transparency.
-class CTInitSingleton {
- public:
-  SECOidTag embedded_oid() const { return embedded_oid_; }
-
- private:
-  friend struct base::DefaultLazyInstanceTraits<CTInitSingleton>;
-
-  CTInitSingleton() : embedded_oid_(SEC_OID_UNKNOWN) {
-    embedded_oid_ = RegisterOid(
-        kEmbeddedSCTOid, sizeof(kEmbeddedSCTOid), kEmbeddedSCTDescription);
-  }
-
-  ~CTInitSingleton() {}
-
-  SECOidTag RegisterOid(const unsigned char* oid,
-                        unsigned int oid_len,
-                        const char* description) {
-    SECOidData oid_data;
-    oid_data.oid.len = oid_len;
-    oid_data.oid.data = const_cast<unsigned char*>(oid);
-    oid_data.offset = SEC_OID_UNKNOWN;
-    oid_data.desc = description;
-    oid_data.mechanism = CKM_INVALID_MECHANISM;
-    // Setting this to SUPPORTED_CERT_EXTENSION ensures that if a certificate
-    // contains this extension with the critical bit set, NSS will not reject
-    // it. However, because verification of this extension happens after NSS,
-    // it is currently left as INVALID_CERT_EXTENSION.
-    oid_data.supportedExtension = INVALID_CERT_EXTENSION;
-
-    SECOidTag result = SECOID_AddEntry(&oid_data);
-    CHECK_NE(SEC_OID_UNKNOWN, result);
-
-    return result;
-  }
-
-  SECOidTag embedded_oid_;
-
-  DISALLOW_COPY_AND_ASSIGN(CTInitSingleton);
-};
-
-base::LazyInstance<CTInitSingleton>::Leaky g_ct_singleton =
-    LAZY_INSTANCE_INITIALIZER;
-
-// Obtains the data for an X.509v3 certificate extension identified by |oid|
-// and encoded as an OCTET STRING. Returns true if the extension was found in
-// the certificate, updating |ext_data| to be the extension data after removing
-// the DER encoding of OCTET STRING.
-bool GetCertOctetStringExtension(CERTCertificate* cert,
-                                 SECOidTag oid,
-                                 std::string* extension_data) {
-  SECItem extension;
-  SECStatus rv = CERT_FindCertExtension(cert, oid, &extension);
-  if (rv != SECSuccess)
-    return false;
-
-  der::Parser parser(der::Input(extension.data, extension.len));
-  der::Input parsed_extension;
-  if (!parser.ReadTag(der::kOctetString, &parsed_extension) ||
-      parser.HasMore()) {  // Decoding failure or raw data left
-    rv = SECFailure;
-  } else {
-    *extension_data = parsed_extension.AsString();
-  }
-
-  SECITEM_FreeItem(&extension, PR_FALSE);
-  return rv == SECSuccess;
-}
-
-// NSS offers CERT_FindCertExtension for certificates, but that only accepts
-// CERTCertificate* inputs, so the method below extracts the SCT extension
-// directly from the CERTCertExtension** of an OCSP response.
-//
-// Obtains the data for an OCSP extension identified by kOCSPExtensionOidItem
-// and encoded as an OCTET STRING. Returns true if the extension was found in
-// |extensions|, updating |extension_data| to be the extension data after
-// removing the DER encoding of OCTET STRING.
-bool GetSCTListFromOCSPExtension(PLArenaPool* arena,
-                                 const CERTCertExtension* const* extensions,
-                                 std::string* extension_data) {
-  if (!extensions)
-    return false;
-
-  const CERTCertExtension* match = NULL;
-
-  for (const CERTCertExtension* const* exts = extensions; *exts; ++exts) {
-    const CERTCertExtension* ext = *exts;
-    if (SECITEM_ItemsAreEqual(&kOCSPExtensionOidItem, &ext->id)) {
-      match = ext;
-      break;
-    }
-  }
-
-  if (!match)
-    return false;
-
-  SECItem contents;
-  // SEC_QuickDERDecodeItem sets |contents| to point to |match|, so it is not
-  // necessary to free the contents of |contents|.
-  SECStatus rv = SEC_QuickDERDecodeItem(arena, &contents,
-                                        SEC_ASN1_GET(SEC_OctetStringTemplate),
-                                        &match->value);
-  if (rv != SECSuccess)
-    return false;
-
-  base::StringPiece parsed_data(reinterpret_cast<char*>(contents.data),
-                                contents.len);
-  parsed_data.CopyToString(extension_data);
-  return true;
-}
-
-// Given a |cert|, extract the TBSCertificate from this certificate, also
-// removing the X.509 extension with OID 1.3.6.1.4.1.11129.2.4.2 (that is,
-// the embedded SCT)
-bool ExtractTBSCertWithoutSCTs(CERTCertificate* cert,
-                               std::string* to_be_signed) {
-  SECOidData* oid = SECOID_FindOIDByTag(g_ct_singleton.Get().embedded_oid());
-  if (!oid)
-    return false;
-
-  // This is a giant hack, due to the fact that NSS does not expose a good API
-  // for simply removing certificate fields from existing certificates.
-  CERTCertificate temp_cert;
-  temp_cert = *cert;
-  temp_cert.extensions = NULL;
-
-  // Strip out the embedded SCT OID from the new certificate by directly
-  // mutating the extensions in place.
-  std::vector<CERTCertExtension*> new_extensions;
-  if (cert->extensions) {
-    for (CERTCertExtension** exts = cert->extensions; *exts; ++exts) {
-      CERTCertExtension* ext = *exts;
-      SECComparison result = SECITEM_CompareItem(&oid->oid, &ext->id);
-      if (result != SECEqual)
-        new_extensions.push_back(ext);
-    }
-  }
-  if (!new_extensions.empty()) {
-    new_extensions.push_back(NULL);
-    temp_cert.extensions = &new_extensions[0];
-  }
-
-  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-
-  SECItem tbs_data;
-  tbs_data.len = 0;
-  tbs_data.data = NULL;
-  void* result = SEC_ASN1EncodeItem(arena.get(),
-                                    &tbs_data,
-                                    &temp_cert,
-                                    SEC_ASN1_GET(CERT_CertificateTemplate));
-  if (!result)
-    return false;
-
-  to_be_signed->assign(reinterpret_cast<char*>(tbs_data.data), tbs_data.len);
-  return true;
-}
-
-// The following code is adapted from the NSS OCSP module, in order to expose
-// the internal structure of an OCSP response.
-
-// ResponseBytes ::=       SEQUENCE {
-//     responseType   OBJECT IDENTIFIER,
-//     response       OCTET STRING }
-struct ResponseBytes {
-  SECItem response_type;
-  SECItem der_response;
-};
-
-const SEC_ASN1Template kResponseBytesTemplate[] = {
-  { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(ResponseBytes) },
-  { SEC_ASN1_OBJECT_ID, offsetof(ResponseBytes, response_type) },
-  { SEC_ASN1_OCTET_STRING, offsetof(ResponseBytes, der_response) },
-  { 0 }
-};
-
-// OCSPResponse ::=     SEQUENCE {
-//      responseStatus          OCSPResponseStatus,
-//      responseBytes           [0] EXPLICIT ResponseBytes OPTIONAL }
-struct OCSPResponse {
-  SECItem response_status;
-  // This indirection is needed because |response_bytes| is an optional
-  // component and we need a way to determine if it is missing.
-  ResponseBytes* response_bytes;
-};
-
-const SEC_ASN1Template kPointerToResponseBytesTemplate[] = {
-  { SEC_ASN1_POINTER, 0, kResponseBytesTemplate }
-};
-
-const SEC_ASN1Template kOCSPResponseTemplate[] = {
-  { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(OCSPResponse) },
-  { SEC_ASN1_ENUMERATED, offsetof(OCSPResponse, response_status) },
-  { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |
-    SEC_ASN1_CONTEXT_SPECIFIC | 0, offsetof(OCSPResponse, response_bytes),
-    kPointerToResponseBytesTemplate },
-  { 0 }
-};
-
-// CertID          ::=     SEQUENCE {
-//   hashAlgorithm       AlgorithmIdentifier,
-//   issuerNameHash      OCTET STRING, -- Hash of Issuer's DN
-//   issuerKeyHash       OCTET STRING, -- Hash of Issuers public key
-//   serialNumber        CertificateSerialNumber }
-struct CertID {
-  SECAlgorithmID hash_algorithm;
-  SECItem issuer_name_hash;
-  SECItem issuer_key_hash;
-  SECItem serial_number;
-};
-
-const SEC_ASN1Template kCertIDTemplate[] = {
-  { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CertID) },
-  { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(CertID, hash_algorithm),
-    SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
-  { SEC_ASN1_OCTET_STRING, offsetof(CertID, issuer_name_hash) },
-  { SEC_ASN1_OCTET_STRING, offsetof(CertID, issuer_key_hash) },
-  { SEC_ASN1_INTEGER, offsetof(CertID, serial_number) },
-  { 0 }
-};
-
-// SingleResponse ::= SEQUENCE {
-//   certID                       CertID,
-//   certStatus                   CertStatus,
-//   thisUpdate                   GeneralizedTime,
-//   nextUpdate           [0]     EXPLICIT GeneralizedTime OPTIONAL,
-//   singleExtensions     [1]     EXPLICIT Extensions OPTIONAL }
-struct SingleResponse {
-  CertID cert_id;
-  // The following three fields are not used.
-  SECItem der_cert_status;
-  SECItem this_update;
-  SECItem next_update;
-  CERTCertExtension** single_extensions;
-};
-
-const SEC_ASN1Template kSingleResponseTemplate[] = {
-  { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SingleResponse) },
-  { SEC_ASN1_INLINE, offsetof(SingleResponse, cert_id), kCertIDTemplate },
-  // Really a CHOICE but we make it an ANY because  we don't care about the
-  // contents of this field.
-  // TODO(ekasper): use SEC_ASN1_CHOICE.
-  { SEC_ASN1_ANY, offsetof(SingleResponse, der_cert_status) },
-  { SEC_ASN1_GENERALIZED_TIME, offsetof(SingleResponse, this_update) },
-  { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
-    SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
-    offsetof(SingleResponse, next_update),
-    SEC_ASN1_SUB(SEC_GeneralizedTimeTemplate) },
-  { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |
-    SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1,
-    offsetof(SingleResponse, single_extensions),
-    SEC_ASN1_SUB(CERT_SequenceOfCertExtensionTemplate) },
-  { 0 }
-};
-
-// ResponseData ::= SEQUENCE {
-//   version              [0] EXPLICIT Version DEFAULT v1,
-//   responderID              ResponderID,
-//   producedAt               GeneralizedTime,
-//   responses                SEQUENCE OF SingleResponse,
-//   responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
-struct ResponseData {
-  // The first three fields are not used.
-  SECItem version;
-  SECItem der_responder_id;
-  SECItem produced_at;
-  SingleResponse** single_responses;
-  // Skip extensions.
-};
-
-const SEC_ASN1Template kResponseDataTemplate[] = {
-  { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(ResponseData) },
-  { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |
-    SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
-    offsetof(ResponseData, version), SEC_ASN1_SUB(SEC_IntegerTemplate) },
-  // Really a CHOICE but we make it an ANY because  we don't care about the
-  // contents of this field.
-  // TODO(ekasper): use SEC_ASN1_CHOICE.
-  { SEC_ASN1_ANY, offsetof(ResponseData, der_responder_id) },
-  { SEC_ASN1_GENERALIZED_TIME, offsetof(ResponseData, produced_at) },
-  { SEC_ASN1_SEQUENCE_OF, offsetof(ResponseData, single_responses),
-    kSingleResponseTemplate },
-  { SEC_ASN1_SKIP_REST },
-  { 0 }
-};
-
-// BasicOCSPResponse       ::= SEQUENCE {
-//   tbsResponseData      ResponseData,
-//   signatureAlgorithm   AlgorithmIdentifier,
-//   signature            BIT STRING,
-//   certs                [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
-struct BasicOCSPResponse {
-  ResponseData tbs_response_data;
-  // We do not care about the rest.
-};
-
-const SEC_ASN1Template kBasicOCSPResponseTemplate[] = {
-  { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(BasicOCSPResponse) },
-  { SEC_ASN1_INLINE, offsetof(BasicOCSPResponse, tbs_response_data),
-    kResponseDataTemplate },
-  { SEC_ASN1_SKIP_REST },
-  { 0 }
-};
-
-bool StringEqualToSECItem(const std::string& value1, const SECItem& value2) {
-  if (value1.size() != value2.len)
-    return false;
-  return memcmp(value1.data(), value2.data, value2.len) == 0;
-}
-
-// TODO(ekasper): also use the issuer name hash in matching.
-bool CertIDMatches(const CertID& cert_id,
-                   const std::string& serial_number,
-                   const std::string& issuer_key_sha1_hash,
-                   const std::string& issuer_key_sha256_hash) {
-  if (!StringEqualToSECItem(serial_number, cert_id.serial_number))
-    return false;
-
-  SECOidTag hash_alg = SECOID_FindOIDTag(&cert_id.hash_algorithm.algorithm);
-  switch (hash_alg) {
-    case SEC_OID_SHA1:
-      return StringEqualToSECItem(issuer_key_sha1_hash,
-                                  cert_id.issuer_key_hash);
-    case SEC_OID_SHA256:
-      return StringEqualToSECItem(issuer_key_sha256_hash,
-                                  cert_id.issuer_key_hash);
-    default:
-      return false;
-  }
-}
-
-}  // namespace
-
-bool ExtractEmbeddedSCTList(X509Certificate::OSCertHandle cert,
-                            std::string* sct_list) {
-  DCHECK(cert);
-
-  NSSCertWrapper leaf_cert(cert);
-  if (!leaf_cert.cert)
-    return false;
-
-  return GetCertOctetStringExtension(leaf_cert.cert.get(),
-                                     g_ct_singleton.Get().embedded_oid(),
-                                     sct_list);
-}
-
-bool GetPrecertLogEntry(X509Certificate::OSCertHandle leaf,
-                        X509Certificate::OSCertHandle issuer,
-                        LogEntry* result) {
-  DCHECK(leaf);
-  DCHECK(issuer);
-
-  NSSCertWrapper leaf_cert(leaf);
-  NSSCertWrapper issuer_cert(issuer);
-
-  result->Reset();
-  // XXX(rsleevi): This check may be overkill, since we should be able to
-  // generate precerts for certs without the extension. For now, just a sanity
-  // check to match the reference implementation.
-  SECItem extension;
-  SECStatus rv = CERT_FindCertExtension(
-      leaf_cert.cert.get(), g_ct_singleton.Get().embedded_oid(), &extension);
-  if (rv != SECSuccess)
-    return false;
-  SECITEM_FreeItem(&extension, PR_FALSE);
-
-  std::string to_be_signed;
-  if (!ExtractTBSCertWithoutSCTs(leaf_cert.cert.get(), &to_be_signed))
-    return false;
-
-  if (!issuer_cert.cert) {
-    // This can happen when the issuer and leaf certs share the same serial
-    // number and are from the same CA, which should never be the case
-    // (but happened with bad test certs).
-    VLOG(1) << "Issuer cert is null, cannot generate Precert entry.";
-    return false;
-  }
-
-  SECKEYPublicKey* issuer_pub_key =
-      SECKEY_ExtractPublicKey(&(issuer_cert.cert->subjectPublicKeyInfo));
-  if (!issuer_pub_key) {
-    VLOG(1) << "Could not extract issuer public key, "
-            << "cannot generate Precert entry.";
-    return false;
-  }
-
-  SECItem* encoded_issuer_pubKey =
-      SECKEY_EncodeDERSubjectPublicKeyInfo(issuer_pub_key);
-  if (!encoded_issuer_pubKey) {
-    SECKEY_DestroyPublicKey(issuer_pub_key);
-    return false;
-  }
-
-  result->type = ct::LogEntry::LOG_ENTRY_TYPE_PRECERT;
-  result->tbs_certificate.swap(to_be_signed);
-
-  crypto::SHA256HashString(
-      base::StringPiece(reinterpret_cast<char*>(encoded_issuer_pubKey->data),
-                        encoded_issuer_pubKey->len),
-      result->issuer_key_hash.data,
-      sizeof(result->issuer_key_hash.data));
-
-  SECITEM_FreeItem(encoded_issuer_pubKey, PR_TRUE);
-  SECKEY_DestroyPublicKey(issuer_pub_key);
-
-  return true;
-}
-
-bool GetX509LogEntry(X509Certificate::OSCertHandle leaf, LogEntry* result) {
-  DCHECK(leaf);
-
-  std::string encoded;
-  if (!X509Certificate::GetDEREncoded(leaf, &encoded))
-    return false;
-
-  result->Reset();
-  result->type = ct::LogEntry::LOG_ENTRY_TYPE_X509;
-  result->leaf_certificate.swap(encoded);
-  return true;
-}
-
-bool ExtractSCTListFromOCSPResponse(X509Certificate::OSCertHandle issuer,
-                                    const std::string& cert_serial_number,
-                                    const std::string& ocsp_response,
-                                    std::string* sct_list) {
-  DCHECK(issuer);
-
-  // Any OCSP response is unlikely to be even close to 2^24 bytes; further, CT
-  // only uses stapled OCSP responses which have this limit imposed by the TLS
-  // protocol.
-  if (ocsp_response.size() > 0xffffff)
-    return false;
-
-  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-
-  OCSPResponse response;
-  memset(&response, 0, sizeof(response));
-
-  SECItem src = { siBuffer,
-                  reinterpret_cast<unsigned char*>(const_cast<char*>(
-                      ocsp_response.data())),
-                  static_cast<unsigned int>(ocsp_response.size()) };
-
-  // |response| will point directly into |src|, so it's not necessary to
-  // free the |response| contents, but they may only be used while |src|
-  // is valid (i.e., in this method).
-  SECStatus rv = SEC_QuickDERDecodeItem(arena.get(), &response,
-                                        kOCSPResponseTemplate, &src);
-  if (rv != SECSuccess)
-    return false;
-
-  if (!response.response_bytes)
-    return false;
-
-  if (!SECITEM_ItemsAreEqual(&kBasicOCSPResponseOidItem,
-                             &response.response_bytes->response_type)) {
-    return false;
-  }
-
-  BasicOCSPResponse basic_response;
-  memset(&basic_response, 0, sizeof(basic_response));
-
-  rv = SEC_QuickDERDecodeItem(arena.get(), &basic_response,
-                              kBasicOCSPResponseTemplate,
-                              &response.response_bytes->der_response);
-  if (rv != SECSuccess)
-    return false;
-
-  SingleResponse** responses =
-      basic_response.tbs_response_data.single_responses;
-  if (!responses)
-    return false;
-
-  std::string issuer_der;
-  if (!X509Certificate::GetDEREncoded(issuer, &issuer_der))
-    return false;
-
-  base::StringPiece issuer_spki;
-  if (!asn1::ExtractSPKIFromDERCert(issuer_der, &issuer_spki))
-    return false;
-
-  // In OCSP, only the key itself is under hash.
-  base::StringPiece issuer_spk;
-  if (!asn1::ExtractSubjectPublicKeyFromSPKI(issuer_spki, &issuer_spk))
-    return false;
-
-  // ExtractSubjectPublicKey... does not remove the initial octet encoding the
-  // number of unused bits in the ASN.1 BIT STRING so we do it here. For public
-  // keys, the bitstring is in practice always byte-aligned.
-  if (issuer_spk.empty() || issuer_spk[0] != 0)
-    return false;
-  issuer_spk.remove_prefix(1);
-
-  // NSS OCSP lib recognizes SHA1, MD5 and MD2; MD5 and MD2 are dead but
-  // https://bugzilla.mozilla.org/show_bug.cgi?id=663315 will add SHA-256
-  // and SHA-384.
-  // TODO(ekasper): add SHA-384 to crypto/sha2.h and here if it proves
-  // necessary.
-  // TODO(ekasper): only compute the hashes on demand.
-  std::string issuer_key_sha256_hash = crypto::SHA256HashString(issuer_spk);
-  std::string issuer_key_sha1_hash = base::SHA1HashString(
-      issuer_spk.as_string());
-
-  const SingleResponse* match = NULL;
-  for (const SingleResponse* const* resps = responses; *resps; ++resps) {
-    const SingleResponse* resp = *resps;
-    if (CertIDMatches(resp->cert_id, cert_serial_number,
-                      issuer_key_sha1_hash, issuer_key_sha256_hash)) {
-      match = resp;
-      break;
-    }
-  }
-
-  if (!match)
-    return false;
-
-  return GetSCTListFromOCSPExtension(arena.get(), match->single_extensions,
-                                     sct_list);
-}
-
-}  // namespace ct
-
-}  // namespace net
diff --git a/net/cert/ev_root_ca_metadata.cc b/net/cert/ev_root_ca_metadata.cc
index a46e50a..dc2cea9 100644
--- a/net/cert/ev_root_ca_metadata.cc
+++ b/net/cert/ev_root_ca_metadata.cc
@@ -4,7 +4,7 @@
 
 #include "net/cert/ev_root_ca_metadata.h"
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
 #include <cert.h>
 #include <pkcs11n.h>
 #include <secerr.h>
@@ -15,13 +15,13 @@
 
 #include "base/lazy_instance.h"
 #include "base/logging.h"
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
 #include "crypto/nss_util.h"
 #endif
 
 namespace net {
 
-#if defined(USE_NSS_VERIFIER) || defined(OS_WIN)
+#if defined(USE_NSS_CERTS) || defined(OS_WIN)
 // Raw metadata.
 struct EVMetadata {
   // kMaxOIDsPerCA is the number of OIDs that we can support per root CA. At
@@ -582,7 +582,7 @@
   return g_ev_root_ca_metadata.Pointer();
 }
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
 bool EVRootCAMetadata::IsEVPolicyOID(PolicyOID policy_oid) const {
   return policy_oids_.find(policy_oid) != policy_oids_.end();
 }
@@ -728,7 +728,7 @@
 
 EVRootCAMetadata::EVRootCAMetadata() {
   // Constructs the object from the raw metadata in ev_root_ca_metadata.
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
   crypto::EnsureNSSInit();
 
   for (size_t i = 0; i < arraysize(ev_root_ca_metadata); i++) {
diff --git a/net/cert/ev_root_ca_metadata.h b/net/cert/ev_root_ca_metadata.h
index 967dcbbd..dfb14bc6 100644
--- a/net/cert/ev_root_ca_metadata.h
+++ b/net/cert/ev_root_ca_metadata.h
@@ -7,7 +7,7 @@
 
 #include "build/build_config.h"
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
 #include <secoidt.h>
 #endif
 
@@ -31,7 +31,7 @@
 // extended-validation (EV) certificates.
 class NET_EXPORT_PRIVATE EVRootCAMetadata {
  public:
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
   typedef SECOidTag PolicyOID;
 #elif defined(OS_WIN)
   typedef const char* PolicyOID;
@@ -39,7 +39,7 @@
 
   static EVRootCAMetadata* GetInstance();
 
-#if defined(USE_NSS_VERIFIER) || defined(OS_WIN)
+#if defined(USE_NSS_CERTS) || defined(OS_WIN)
   // Returns true if policy_oid is an EV policy OID of some root CA.
   bool IsEVPolicyOID(PolicyOID policy_oid) const;
 
@@ -64,7 +64,7 @@
   EVRootCAMetadata();
   ~EVRootCAMetadata();
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
   typedef std::map<SHA1HashValue, std::vector<PolicyOID>,
                    SHA1HashValueLessThan> PolicyOIDMap;
 
diff --git a/net/cert/internal/signature_policy.cc b/net/cert/internal/signature_policy.cc
index 69f22f7..c00212ac 100644
--- a/net/cert/internal/signature_policy.cc
+++ b/net/cert/internal/signature_policy.cc
@@ -6,9 +6,7 @@
 
 #include "base/logging.h"
 
-#if defined(USE_OPENSSL)
 #include <openssl/obj.h>
-#endif
 
 namespace net {
 
@@ -18,14 +16,12 @@
 }
 
 bool SignaturePolicy::IsAcceptableCurveForEcdsa(int curve_nid) const {
-#if defined(USE_OPENSSL)
   switch (curve_nid) {
     case NID_X9_62_prime256v1:
     case NID_secp384r1:
     case NID_secp521r1:
       return true;
   }
-#endif
   return false;
 }
 
diff --git a/net/cert/internal/verify_certificate_chain_pkits_unittest.cc b/net/cert/internal/verify_certificate_chain_pkits_unittest.cc
index 98b0e7b..5993b9c1 100644
--- a/net/cert/internal/verify_certificate_chain_pkits_unittest.cc
+++ b/net/cert/internal/verify_certificate_chain_pkits_unittest.cc
@@ -2,10 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// TODO(eroman): Because VerifySignedData() is only implemented for BoringSSL
-// these tests also depend on BoringSSL.
-#if defined(USE_OPENSSL)
-
 #include "net/cert/internal/verify_certificate_chain.h"
 
 #include "net/cert/internal/parse_certificate.h"
@@ -219,5 +215,3 @@
 // PkitsTest11InhibitPolicyMapping, PkitsTest12InhibitAnyPolicy
 
 }  // namespace net
-
-#endif  // USE_OPENSSL
diff --git a/net/cert/internal/verify_certificate_chain_unittest.cc b/net/cert/internal/verify_certificate_chain_unittest.cc
index c997f538..b172a338 100644
--- a/net/cert/internal/verify_certificate_chain_unittest.cc
+++ b/net/cert/internal/verify_certificate_chain_unittest.cc
@@ -17,10 +17,6 @@
 #include "net/der/input.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-// TODO(eroman): Because VerifySignedData() is only implemented for BoringSSL
-// these tests also depend on BoringSSL.
-#if defined(USE_OPENSSL)
-
 namespace net {
 
 namespace {
@@ -242,5 +238,3 @@
 }  // namespace
 
 }  // namespace net
-
-#endif
diff --git a/net/cert/internal/verify_signed_data.cc b/net/cert/internal/verify_signed_data.cc
index eb0fd3ff..fe6aae8 100644
--- a/net/cert/internal/verify_signed_data.cc
+++ b/net/cert/internal/verify_signed_data.cc
@@ -4,31 +4,6 @@
 
 #include "net/cert/internal/verify_signed_data.h"
 
-#include "base/logging.h"
-#include "net/der/parse_values.h"
-
-// TODO(eroman): There is no intention to implement this for non-OpenSSL. Remove
-// this branch once the migration is complete. This could have been done as a
-// conditional file (_openssl.cc) in the build file instead, but that is likely
-// not worth the effort at this point.
-
-#if !defined(USE_OPENSSL)
-
-namespace net {
-
-bool VerifySignedData(const SignatureAlgorithm& signature_algorithm,
-                      const der::Input& signed_data,
-                      const der::BitString& signature_value,
-                      const der::Input& public_key,
-                      const SignaturePolicy* policy) {
-  NOTIMPLEMENTED();
-  return false;
-}
-
-}  // namespace net
-
-#else
-
 #include <openssl/bytestring.h>
 #include <openssl/digest.h>
 #include <openssl/ec.h>
@@ -37,11 +12,13 @@
 #include <openssl/rsa.h>
 
 #include "base/compiler_specific.h"
+#include "base/logging.h"
 #include "crypto/openssl_util.h"
 #include "crypto/scoped_openssl_types.h"
 #include "net/cert/internal/signature_algorithm.h"
 #include "net/cert/internal/signature_policy.h"
 #include "net/der/input.h"
+#include "net/der/parse_values.h"
 #include "net/der/parser.h"
 
 namespace net {
@@ -312,5 +289,3 @@
 }
 
 }  // namespace net
-
-#endif
diff --git a/net/cert/internal/verify_signed_data_unittest.cc b/net/cert/internal/verify_signed_data_unittest.cc
index 50586a1..ba0fab2 100644
--- a/net/cert/internal/verify_signed_data_unittest.cc
+++ b/net/cert/internal/verify_signed_data_unittest.cc
@@ -15,9 +15,7 @@
 #include "net/der/parser.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(USE_OPENSSL)
 #include <openssl/obj.h>
-#endif
 
 namespace net {
 
@@ -39,11 +37,6 @@
 void RunTestCaseUsingPolicy(VerifyResult expected_result,
                             const char* file_name,
                             const SignaturePolicy* policy) {
-#if !defined(USE_OPENSSL)
-  LOG(INFO) << "Skipping test, only implemented for BoringSSL";
-  return;
-#endif
-
   std::string path =
       std::string("net/data/verify_signed_data_unittest/") + file_name;
 
@@ -223,10 +216,8 @@
 class RejectSecp384r1Policy : public SignaturePolicy {
  public:
   bool IsAcceptableCurveForEcdsa(int curve_nid) const override {
-#if defined(USE_OPENSSL)
     if (curve_nid == NID_secp384r1)
       return false;
-#endif
     return true;
   }
 };
diff --git a/net/cert/jwk_serializer_nss.cc b/net/cert/jwk_serializer_nss.cc
deleted file mode 100644
index 6059453..0000000
--- a/net/cert/jwk_serializer_nss.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <cert.h>
-#include <keyhi.h>
-#include <nss.h>
-
-#include <memory>
-
-#include "base/base64url.h"
-#include "base/values.h"
-#include "crypto/nss_util.h"
-#include "crypto/scoped_nss_types.h"
-#include "net/cert/jwk_serializer.h"
-
-namespace net {
-
-namespace JwkSerializer {
-
-namespace {
-
-bool ConvertEcPrime256v1PublicKeyInfoToJwk(
-    CERTSubjectPublicKeyInfo* spki,
-    base::DictionaryValue* public_key_jwk) {
-  static const int kUncompressedEncodingType = 4;
-  static const int kPrime256v1PublicKeyLength = 64;
-  // The public key value is encoded as 0x04 + 64 bytes of public key.
-  // NSS gives the length as the bit length.
-  if (spki->subjectPublicKey.len != (kPrime256v1PublicKeyLength + 1) * 8 ||
-      spki->subjectPublicKey.data[0] != kUncompressedEncodingType)
-    return false;
-
-  public_key_jwk->SetString("kty", "EC");
-  public_key_jwk->SetString("crv", "P-256");
-
-  base::StringPiece x(
-      reinterpret_cast<char*>(spki->subjectPublicKey.data + 1),
-      kPrime256v1PublicKeyLength / 2);
-  std::string x_b64;
-  base::Base64UrlEncode(x, base::Base64UrlEncodePolicy::OMIT_PADDING, &x_b64);
-  public_key_jwk->SetString("x", x_b64);
-
-  base::StringPiece y(
-      reinterpret_cast<char*>(spki->subjectPublicKey.data + 1 +
-                              kPrime256v1PublicKeyLength / 2),
-      kPrime256v1PublicKeyLength / 2);
-  std::string y_b64;
-  base::Base64UrlEncode(y, base::Base64UrlEncodePolicy::OMIT_PADDING, &y_b64);
-  public_key_jwk->SetString("y", y_b64);
-  return true;
-}
-
-bool ConvertEcPublicKeyInfoToJwk(
-    CERTSubjectPublicKeyInfo* spki,
-    base::DictionaryValue* public_key_jwk) {
-  // 1.2.840.10045.3.1.7
-  // (iso.member-body.us.ansi-x9-62.ellipticCurve.primeCurve.prime256v1)
-  // (This includes the DER-encoded type (OID) and length: parameters can be
-  // anything, so the DER type isn't implied, and NSS includes it.)
-  static const unsigned char kPrime256v1[] = {
-    0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
-  };
-  if (spki->algorithm.parameters.len == sizeof(kPrime256v1) &&
-      !memcmp(spki->algorithm.parameters.data, kPrime256v1,
-              sizeof(kPrime256v1))) {
-    return ConvertEcPrime256v1PublicKeyInfoToJwk(spki, public_key_jwk);
-  }
-  // TODO(juanlang): other curves
-  return false;
-}
-
-typedef std::unique_ptr<
-    CERTSubjectPublicKeyInfo,
-    crypto::NSSDestroyer<CERTSubjectPublicKeyInfo,
-                         SECKEY_DestroySubjectPublicKeyInfo>>
-    ScopedCERTSubjectPublicKeyInfo;
-
-}  // namespace
-
-bool ConvertSpkiFromDerToJwk(
-    const base::StringPiece& spki_der,
-    base::DictionaryValue* public_key_jwk) {
-  public_key_jwk->Clear();
-
-  crypto::EnsureNSSInit();
-
-  if (!NSS_IsInitialized())
-    return false;
-
-  SECItem sec_item;
-  sec_item.data = const_cast<unsigned char*>(
-      reinterpret_cast<const unsigned char*>(spki_der.data()));
-  sec_item.len = spki_der.size();
-  ScopedCERTSubjectPublicKeyInfo spki(
-      SECKEY_DecodeDERSubjectPublicKeyInfo(&sec_item));
-  if (!spki)
-    return false;
-
-  // 1.2.840.10045.2
-  // (iso.member-body.us.ansi-x9-62.id-ecPublicKey)
-  // (This omits the ASN.1 encoding of the type (OID) and length: the fact that
-  // this is an OID is already clear, and NSS omits it here.)
-  static const unsigned char kIdEcPublicKey[] = {
-    0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01
-  };
-  bool rv = false;
-  if (spki->algorithm.algorithm.len == sizeof(kIdEcPublicKey) &&
-      !memcmp(spki->algorithm.algorithm.data, kIdEcPublicKey,
-              sizeof(kIdEcPublicKey))) {
-    rv = ConvertEcPublicKeyInfoToJwk(spki.get(), public_key_jwk);
-  }
-  // TODO(juanlang): other algorithms
-  return rv;
-}
-
-}  // namespace JwkSerializer
-
-}  // namespace net
diff --git a/net/cert/multi_threaded_cert_verifier.cc b/net/cert/multi_threaded_cert_verifier.cc
index d39c705..2d65025 100644
--- a/net/cert/multi_threaded_cert_verifier.cc
+++ b/net/cert/multi_threaded_cert_verifier.cc
@@ -32,7 +32,7 @@
 #include "net/cert/x509_certificate_net_log_param.h"
 #include "net/log/net_log.h"
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
 #include <private/pprthred.h>  // PR_DetachThread
 #endif
 
@@ -241,7 +241,7 @@
   *error = verify_proc->Verify(cert.get(), hostname, ocsp_response, flags,
                                crl_set.get(), additional_trust_anchors, result);
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
   // Detach the thread from NSPR.
   // Calling NSS functions attaches the thread to NSPR, which stores
   // the NSPR thread ID in thread-specific data.
diff --git a/net/cert/test_root_certs.h b/net/cert/test_root_certs.h
index 412bbe8..1775e39 100644
--- a/net/cert/test_root_certs.h
+++ b/net/cert/test_root_certs.h
@@ -11,7 +11,7 @@
 #include "build/build_config.h"
 #include "net/base/net_export.h"
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
 #include <list>
 #elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID)
 #include <vector>
@@ -67,7 +67,7 @@
 
 #if defined(USE_NSS_CERTS)
   bool Contains(CERTCertificate* cert) const;
-#elif defined(OS_MACOSX) && !defined(USE_NSS_VERIFIER)
+#elif defined(OS_MACOSX) && !defined(USE_NSS_CERTS)
   CFArrayRef temporary_roots() const { return temporary_roots_; }
 
   // Modifies the root certificates of |trust_ref| to include the
@@ -102,7 +102,7 @@
   // Performs platform-dependent initialization.
   void Init();
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
   // It is necessary to maintain a cache of the original certificate trust
   // settings, in order to restore them when Clear() is called.
   class TrustEntry;
diff --git a/net/cert/test_root_certs_unittest.cc b/net/cert/test_root_certs_unittest.cc
index 2f449e765..6f8a380 100644
--- a/net/cert/test_root_certs_unittest.cc
+++ b/net/cert/test_root_certs_unittest.cc
@@ -14,7 +14,7 @@
 #include "net/test/cert_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
 #include <nss.h>
 #endif
 
@@ -75,7 +75,6 @@
     return;
   }
 #endif
-
   TestRootCerts* test_roots = TestRootCerts::GetInstance();
   ASSERT_NE(static_cast<TestRootCerts*>(NULL), test_roots);
   EXPECT_TRUE(test_roots->IsEmpty());
diff --git a/net/cert/x509_certificate_ios.cc b/net/cert/x509_certificate_ios.cc
index a69792a9..96ed1de 100644
--- a/net/cert/x509_certificate_ios.cc
+++ b/net/cert/x509_certificate_ios.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,40 +6,29 @@
 
 #include <CommonCrypto/CommonDigest.h>
 #include <Security/Security.h>
-#include <cert.h>
-#include <cryptohi.h>
-#include <keyhi.h>
-#include <nss.h>
-#include <pk11pub.h>
-#include <prerror.h>
-#include <prtime.h>
-#include <prtypes.h>
-#include <secder.h>
-#include <secerr.h>
-#include <sslerr.h>
 
-#include <memory>
-#include <vector>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
 
-#include "base/logging.h"
 #include "base/mac/scoped_cftyperef.h"
-#include "base/numerics/safe_conversions.h"
 #include "base/pickle.h"
-#include "base/time/time.h"
-#include "crypto/nss_util.h"
-#include "crypto/scoped_nss_types.h"
-#include "net/base/net_errors.h"
-#include "net/cert/asn1_util.h"
-#include "net/cert/cert_status_flags.h"
-#include "net/cert/cert_verify_result.h"
-#include "net/cert/ev_root_ca_metadata.h"
-#include "net/cert/x509_util_ios.h"
-#include "net/cert/x509_util_nss.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
+#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
+#include "net/base/ip_address_number.h"
+#include "net/cert/x509_util_openssl.h"
+#include "net/ssl/openssl_ssl_util.h"
 
 using base::ScopedCFTypeRef;
 
 namespace net {
+
 namespace {
+
+using ScopedGENERAL_NAMES =
+    crypto::ScopedOpenSSL<GENERAL_NAMES, GENERAL_NAMES_free>;
+
 // Returns true if a given |cert_handle| is actually a valid X.509 certificate
 // handle.
 //
@@ -52,115 +41,127 @@
 bool IsValidOSCertHandle(SecCertificateRef cert_handle) {
   ScopedCFTypeRef<CFStringRef> sanity_check(
       SecCertificateCopySubjectSummary(cert_handle));
-  return sanity_check != NULL;
-}
-}  // namespace
-
-void X509Certificate::Initialize() {
-  x509_util_ios::NSSCertificate nss_cert(cert_handle_);
-  CERTCertificate* cert_handle = nss_cert.cert_handle();
-  if (cert_handle) {
-    x509_util::ParsePrincipal(&cert_handle->subject, &subject_);
-    x509_util::ParsePrincipal(&cert_handle->issuer, &issuer_);
-    x509_util::ParseDate(&cert_handle->validity.notBefore, &valid_start_);
-    x509_util::ParseDate(&cert_handle->validity.notAfter, &valid_expiry_);
-    serial_number_ = x509_util::ParseSerialNumber(cert_handle);
-  }
-  fingerprint_ = CalculateFingerprint(cert_handle_);
-  ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_);
+  return sanity_check != nullptr;
 }
 
-bool X509Certificate::IsIssuedByEncoded(
-    const std::vector<std::string>& valid_issuers) {
-  x509_util_ios::NSSCertChain nss_chain(this);
-  // Convert to scoped CERTName* list.
-  std::vector<CERTName*> issuers;
-  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-  if (!x509_util::GetIssuersFromEncodedList(valid_issuers,
-                                            arena.get(),
-                                            &issuers)) {
-    return false;
-  }
-  return x509_util::IsCertificateIssuedBy(
-      nss_chain.cert_chain(), issuers);
-}
-
-void X509Certificate::GetSubjectAltName(
-    std::vector<std::string>* dns_names,
-    std::vector<std::string>* ip_addrs) const {
-  x509_util_ios::NSSCertificate nss_cert(cert_handle_);
-  CERTCertificate* cert_handle = nss_cert.cert_handle();
-  if (!cert_handle) {
-    if (dns_names)
-      dns_names->clear();
-    if (ip_addrs)
-      ip_addrs->clear();
-    return;
-  }
-  x509_util::GetSubjectAltName(cert_handle, dns_names, ip_addrs);
-}
-
-// static
-bool X509Certificate::GetDEREncoded(OSCertHandle cert_handle,
-                                    std::string* encoded) {
-  if (!cert_handle)
-    return false;
-  ScopedCFTypeRef<CFDataRef> der_data(SecCertificateCopyData(cert_handle));
-  if (!der_data)
-    return false;
-  encoded->assign(reinterpret_cast<const char*>(CFDataGetBytePtr(der_data)),
-                  CFDataGetLength(der_data));
-  return true;
-}
-
-// static
-bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
-                                   X509Certificate::OSCertHandle b) {
-  DCHECK(a && b);
-  if (a == b)
-    return true;
-  if (CFEqual(a, b))
-    return true;
-  ScopedCFTypeRef<CFDataRef> a_data(SecCertificateCopyData(a));
-  ScopedCFTypeRef<CFDataRef> b_data(SecCertificateCopyData(b));
-  return a_data && b_data &&
-         CFDataGetLength(a_data) == CFDataGetLength(b_data) &&
-         memcmp(CFDataGetBytePtr(a_data), CFDataGetBytePtr(b_data),
-                CFDataGetLength(a_data)) == 0;
-}
-
-// static
-X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
-    const char* data,
-    size_t length) {
-  ScopedCFTypeRef<CFDataRef> cert_data(CFDataCreateWithBytesNoCopy(
-      kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data),
-      base::checked_cast<CFIndex>(length), kCFAllocatorNull));
-  if (!cert_data)
-    return nullptr;
-  OSCertHandle cert_handle = SecCertificateCreateWithData(NULL, cert_data);
-  if (!cert_handle)
-    return nullptr;
-  if (!IsValidOSCertHandle(cert_handle)) {
-    CFRelease(cert_handle);
-    return nullptr;
-  }
-  return cert_handle;
-}
-
-// static
-X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
+void CreateOSCertHandlesFromPKCS7Bytes(
     const char* data,
     size_t length,
-    Format format) {
-  return x509_util::CreateOSCertHandlesFromBytes(data, length, format);
+    X509Certificate::OSCertHandles* handles) {
+  crypto::EnsureOpenSSLInit();
+  crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE);
+
+  CBS der_data;
+  CBS_init(&der_data, reinterpret_cast<const uint8_t*>(data), length);
+  STACK_OF(X509)* certs = sk_X509_new_null();
+
+  if (PKCS7_get_certificates(certs, &der_data)) {
+    for (size_t i = 0; i < sk_X509_num(certs); ++i) {
+      X509* x509_cert = sk_X509_value(certs, i);
+      base::StringPiece der;
+      if (!x509_util::GetDER(x509_cert, &der))
+        return;
+      handles->push_back(X509Certificate::CreateOSCertHandleFromBytes(
+          der.data(), der.length()));
+    }
+  }
+  sk_X509_pop_free(certs, X509_free);
 }
 
+void ParsePrincipalValues(X509_NAME* name,
+                          int nid,
+                          std::vector<std::string>* fields) {
+  for (int index = -1;
+       (index = X509_NAME_get_index_by_NID(name, nid, index)) != -1;) {
+    std::string field;
+    if (!x509_util::ParsePrincipalValueByIndex(name, index, &field))
+      break;
+    fields->push_back(field);
+  }
+}
+
+void ParsePrincipal(X509Certificate::OSCertHandle os_cert,
+                    X509_NAME* x509_name,
+                    CertPrincipal* principal) {
+  if (!x509_name)
+    return;
+
+  ParsePrincipalValues(x509_name, NID_streetAddress,
+                       &principal->street_addresses);
+  ParsePrincipalValues(x509_name, NID_organizationName,
+                       &principal->organization_names);
+  ParsePrincipalValues(x509_name, NID_organizationalUnitName,
+                       &principal->organization_unit_names);
+  ParsePrincipalValues(x509_name, NID_domainComponent,
+                       &principal->domain_components);
+
+  x509_util::ParsePrincipalValueByNID(x509_name, NID_commonName,
+                                      &principal->common_name);
+  x509_util::ParsePrincipalValueByNID(x509_name, NID_localityName,
+                                      &principal->locality_name);
+  x509_util::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName,
+                                      &principal->state_or_province_name);
+  x509_util::ParsePrincipalValueByNID(x509_name, NID_countryName,
+                                      &principal->country_name);
+}
+
+void ParseSubjectAltName(X509Certificate::OSCertHandle os_cert,
+                         std::vector<std::string>* dns_names,
+                         std::vector<std::string>* ip_addresses) {
+  DCHECK(dns_names || ip_addresses);
+  ScopedX509 cert = OSCertHandleToOpenSSL(os_cert);
+  if (!cert.get())
+    return;
+  int index = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1);
+  X509_EXTENSION* alt_name_ext = X509_get_ext(cert.get(), index);
+  if (!alt_name_ext)
+    return;
+
+  ScopedGENERAL_NAMES alt_names(
+      reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext)));
+  if (!alt_names.get())
+    return;
+
+  for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) {
+    const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i);
+    if (name->type == GEN_DNS && dns_names) {
+      const unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName);
+      if (!dns_name)
+        continue;
+      int dns_name_len = ASN1_STRING_length(name->d.dNSName);
+      dns_names->push_back(
+          std::string(reinterpret_cast<const char*>(dns_name), dns_name_len));
+    } else if (name->type == GEN_IPADD && ip_addresses) {
+      const unsigned char* ip_addr = name->d.iPAddress->data;
+      if (!ip_addr)
+        continue;
+      int ip_addr_len = name->d.iPAddress->length;
+      if (ip_addr_len != static_cast<int>(kIPv4AddressSize) &&
+          ip_addr_len != static_cast<int>(kIPv6AddressSize)) {
+        // http://www.ietf.org/rfc/rfc3280.txt requires subjectAltName iPAddress
+        // to have 4 or 16 bytes, whereas in a name constraint it includes a
+        // net mask hence 8 or 32 bytes. Logging to help diagnose any mixup.
+        LOG(WARNING) << "Bad sized IP Address in cert: " << ip_addr_len;
+        continue;
+      }
+      ip_addresses->push_back(
+          std::string(reinterpret_cast<const char*>(ip_addr), ip_addr_len));
+    }
+  }
+}
+
+// Used to free a list of X509_NAMEs and the objects it points to.
+void sk_X509_NAME_free_all(STACK_OF(X509_NAME) * sk) {
+  sk_X509_NAME_pop_free(sk, X509_NAME_free);
+}
+
+}  // namespace
+
 // static
 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
     OSCertHandle handle) {
   if (!handle)
-    return NULL;
+    return nullptr;
   return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle)));
 }
 
@@ -170,9 +171,37 @@
     CFRelease(cert_handle);
 }
 
+void X509Certificate::Initialize() {
+  crypto::EnsureOpenSSLInit();
+  fingerprint_ = CalculateFingerprint(cert_handle_);
+  ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_);
+  ScopedX509 x509_cert = OSCertHandleToOpenSSL(cert_handle_);
+  if (!x509_cert)
+    return;
+  ASN1_INTEGER* serial_num = X509_get_serialNumber(x509_cert.get());
+  if (serial_num) {
+    // ASN1_INTEGERS represent the decoded number, in a format internal to
+    // OpenSSL. Most notably, this may have leading zeroes stripped off for
+    // numbers whose first byte is >= 0x80. Thus, it is necessary to
+    // re-encoded the integer back into DER, which is what the interface
+    // of X509Certificate exposes, to ensure callers get the proper (DER)
+    // value.
+    int bytes_required = i2c_ASN1_INTEGER(serial_num, nullptr);
+    unsigned char* buffer = reinterpret_cast<unsigned char*>(
+        base::WriteInto(&serial_number_, bytes_required + 1));
+    int bytes_written = i2c_ASN1_INTEGER(serial_num, &buffer);
+    DCHECK_EQ(static_cast<size_t>(bytes_written), serial_number_.size());
+  }
+
+  ParsePrincipal(cert_handle_, X509_get_subject_name(x509_cert.get()),
+                 &subject_);
+  ParsePrincipal(cert_handle_, X509_get_issuer_name(x509_cert.get()), &issuer_);
+  x509_util::ParseDate(X509_get_notBefore(x509_cert.get()), &valid_start_);
+  x509_util::ParseDate(X509_get_notAfter(x509_cert.get()), &valid_expiry_);
+}
+
 // static
-SHA1HashValue X509Certificate::CalculateFingerprint(
-    OSCertHandle cert) {
+SHA1HashValue X509Certificate::CalculateFingerprint(OSCertHandle cert) {
   SHA1HashValue sha1;
   memset(sha1.data, 0, sizeof(sha1.data));
 
@@ -196,8 +225,8 @@
     return sha256;
   DCHECK(CFDataGetBytePtr(cert_data));
   DCHECK_NE(0, CFDataGetLength(cert_data));
-  CC_SHA256(
-      CFDataGetBytePtr(cert_data), CFDataGetLength(cert_data), sha256.data);
+  CC_SHA256(CFDataGetBytePtr(cert_data), CFDataGetLength(cert_data),
+            sha256.data);
 
   return sha256;
 }
@@ -208,17 +237,14 @@
   SHA1HashValue sha1;
   memset(sha1.data, 0, sizeof(sha1.data));
 
-  // The CC_SHA(3cc) man page says all CC_SHA1_xxx routines return 1, so
-  // we don't check their return values.
   CC_SHA1_CTX sha1_ctx;
   CC_SHA1_Init(&sha1_ctx);
   for (size_t i = 0; i < intermediates.size(); ++i) {
-    ScopedCFTypeRef<CFDataRef>
-        cert_data(SecCertificateCopyData(intermediates[i]));
+    ScopedCFTypeRef<CFDataRef> cert_data(
+        SecCertificateCopyData(intermediates[i]));
     if (!cert_data)
       return sha1;
-    CC_SHA1_Update(&sha1_ctx,
-                   CFDataGetBytePtr(cert_data),
+    CC_SHA1_Update(&sha1_ctx, CFDataGetBytePtr(cert_data),
                    CFDataGetLength(cert_data));
   }
   CC_SHA1_Final(sha1.data, &sha1_ctx);
@@ -226,9 +252,93 @@
 }
 
 // static
+X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
+    const char* data,
+    size_t length) {
+  ScopedCFTypeRef<CFDataRef> cert_data(CFDataCreateWithBytesNoCopy(
+      kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data),
+      base::checked_cast<CFIndex>(length), kCFAllocatorNull));
+  if (!cert_data)
+    return nullptr;
+  OSCertHandle cert_handle = SecCertificateCreateWithData(nullptr, cert_data);
+  if (!cert_handle)
+    return nullptr;
+  if (!IsValidOSCertHandle(cert_handle)) {
+    CFRelease(cert_handle);
+    return nullptr;
+  }
+  return cert_handle;
+}
+
+// static
+X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
+    const char* data,
+    size_t length,
+    Format format) {
+  OSCertHandles results;
+
+  switch (format) {
+    case FORMAT_SINGLE_CERTIFICATE: {
+      OSCertHandle handle =
+          X509Certificate::CreateOSCertHandleFromBytes(data, length);
+      if (handle)
+        results.push_back(handle);
+      break;
+    }
+    case FORMAT_PKCS7: {
+      CreateOSCertHandlesFromPKCS7Bytes(data, length, &results);
+      break;
+    }
+    default: {
+      NOTREACHED() << "Certificate format " << format << " unimplemented";
+      break;
+    }
+  }
+
+  return results;
+}
+
+void X509Certificate::GetSubjectAltName(
+    std::vector<std::string>* dns_names,
+    std::vector<std::string>* ip_addrs) const {
+  if (dns_names)
+    dns_names->clear();
+  if (ip_addrs)
+    ip_addrs->clear();
+
+  ParseSubjectAltName(cert_handle_, dns_names, ip_addrs);
+}
+
+// static
+bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle,
+                                    std::string* encoded) {
+  base::StringPiece der;
+  if (!cert_handle)
+    return false;
+  ScopedCFTypeRef<CFDataRef> der_data(SecCertificateCopyData(cert_handle));
+  if (!der_data)
+    return false;
+  encoded->assign(reinterpret_cast<const char*>(CFDataGetBytePtr(der_data)),
+                  CFDataGetLength(der_data));
+  return true;
+}
+
+// static
+bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
+                                   X509Certificate::OSCertHandle b) {
+  DCHECK(a && b);
+  return CFEqual(a, b);
+}
+
+// static
 X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle(
     base::PickleIterator* pickle_iter) {
-  return x509_util::ReadOSCertHandleFromPickle(pickle_iter);
+  const char* data;
+  int length;
+  if (!pickle_iter->ReadData(&data, &length))
+    return nullptr;
+
+  return X509Certificate::CreateOSCertHandleFromBytes(data, length);
 }
 
 // static
@@ -244,22 +354,121 @@
 }
 
 // static
-void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle,
+void X509Certificate::GetPublicKeyInfo(OSCertHandle os_cert,
                                        size_t* size_bits,
                                        PublicKeyType* type) {
-  x509_util_ios::NSSCertificate nss_cert(cert_handle);
-  x509_util::GetPublicKeyInfo(nss_cert.cert_handle(), size_bits, type);
+  *type = kPublicKeyTypeUnknown;
+  *size_bits = 0;
+  ScopedX509 cert = OSCertHandleToOpenSSL(os_cert);
+  if (!cert)
+    return;
+  crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert.get()));
+  if (!scoped_key)
+    return;
+
+  EVP_PKEY* key = scoped_key.get();
+
+  switch (key->type) {
+    case EVP_PKEY_RSA:
+      *type = kPublicKeyTypeRSA;
+      break;
+    case EVP_PKEY_DSA:
+      *type = kPublicKeyTypeDSA;
+      break;
+    case EVP_PKEY_EC:
+      *type = kPublicKeyTypeECDSA;
+      break;
+    case EVP_PKEY_DH:
+      *type = kPublicKeyTypeDH;
+      break;
+  }
+  *size_bits = EVP_PKEY_bits(key);
+}
+
+bool X509Certificate::SupportsSSLClientAuth() const {
+  return false;
+}
+
+CFMutableArrayRef X509Certificate::CreateOSCertChainForCert() const {
+  CFMutableArrayRef cert_list =
+      CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
+  if (!cert_list)
+    return nullptr;
+
+  CFArrayAppendValue(cert_list, os_cert_handle());
+  for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i)
+    CFArrayAppendValue(cert_list, intermediate_ca_certs_[i]);
+
+  return cert_list;
+}
+
+bool X509Certificate::IsIssuedByEncoded(
+    const std::vector<std::string>& valid_issuers) {
+  if (valid_issuers.empty())
+    return false;
+
+  // Convert to a temporary list of X509_NAME objects.
+  // It will own the objects it points to.
+  crypto::ScopedOpenSSL<STACK_OF(X509_NAME), sk_X509_NAME_free_all>
+      issuer_names(sk_X509_NAME_new_null());
+  if (!issuer_names)
+    return false;
+
+  for (std::vector<std::string>::const_iterator it = valid_issuers.begin();
+       it != valid_issuers.end(); ++it) {
+    const unsigned char* p = reinterpret_cast<const unsigned char*>(it->data());
+    long len = static_cast<long>(it->length());
+    X509_NAME* ca_name = d2i_X509_NAME(nullptr, &p, len);
+    if (ca_name == nullptr)
+      return false;
+    sk_X509_NAME_push(issuer_names.get(), ca_name);
+  }
+
+  ScopedX509 x509_cert = OSCertHandleToOpenSSL(cert_handle_);
+  if (!x509_cert)
+    return false;
+  X509_NAME* cert_issuer = X509_get_issuer_name(x509_cert.get());
+  if (cert_issuer == nullptr)
+    return false;
+
+  for (size_t m = 0; m < sk_X509_NAME_num(issuer_names.get()); ++m) {
+    X509_NAME* issuer = sk_X509_NAME_value(issuer_names.get(), m);
+    if (X509_NAME_cmp(issuer, cert_issuer) == 0) {
+      return true;
+    }
+  }
+
+  for (OSCertHandles::iterator it = intermediate_ca_certs_.begin();
+       it != intermediate_ca_certs_.end(); ++it) {
+    ScopedX509 intermediate_cert = OSCertHandleToOpenSSL(*it);
+    if (!intermediate_cert)
+      return false;
+    cert_issuer = X509_get_issuer_name(intermediate_cert.get());
+    if (cert_issuer == nullptr)
+      return false;
+
+    for (size_t m = 0; m < sk_X509_NAME_num(issuer_names.get()); ++m) {
+      X509_NAME* issuer = sk_X509_NAME_value(issuer_names.get(), m);
+      if (X509_NAME_cmp(issuer, cert_issuer) == 0) {
+        return true;
+      }
+    }
+  }
+
+  return false;
 }
 
 // static
-bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) {
-  x509_util_ios::NSSCertificate nss_cert(cert_handle);
-  crypto::ScopedSECKEYPublicKey public_key(
-      CERT_ExtractPublicKey(nss_cert.cert_handle()));
-  if (!public_key.get())
+bool X509Certificate::IsSelfSigned(OSCertHandle os_cert) {
+  ScopedX509 cert = OSCertHandleToOpenSSL(os_cert);
+  if (!cert)
     return false;
-  return SECSuccess == CERT_VerifySignedDataWithPublicKey(
-      &nss_cert.cert_handle()->signatureWrap, public_key.get(), NULL);
+  crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert.get()));
+  if (!scoped_key)
+    return false;
+
+  // NOTE: X509_verify() returns 1 in case of success, 0 or -1 on error.
+  return X509_verify(cert.get(), scoped_key.get()) == 1;
 }
 
 }  // namespace net
diff --git a/net/cert/x509_certificate_openssl_ios.cc b/net/cert/x509_certificate_openssl_ios.cc
deleted file mode 100644
index 96ed1de..0000000
--- a/net/cert/x509_certificate_openssl_ios.cc
+++ /dev/null
@@ -1,474 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/cert/x509_certificate.h"
-
-#include <CommonCrypto/CommonDigest.h>
-#include <Security/Security.h>
-
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-
-#include "base/mac/scoped_cftyperef.h"
-#include "base/pickle.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "crypto/openssl_util.h"
-#include "crypto/scoped_openssl_types.h"
-#include "net/base/ip_address_number.h"
-#include "net/cert/x509_util_openssl.h"
-#include "net/ssl/openssl_ssl_util.h"
-
-using base::ScopedCFTypeRef;
-
-namespace net {
-
-namespace {
-
-using ScopedGENERAL_NAMES =
-    crypto::ScopedOpenSSL<GENERAL_NAMES, GENERAL_NAMES_free>;
-
-// Returns true if a given |cert_handle| is actually a valid X.509 certificate
-// handle.
-//
-// SecCertificateCreateFromData() does not always force the immediate parsing of
-// the certificate, and as such, may return a SecCertificateRef for an
-// invalid/unparsable certificate. Force parsing to occur to ensure that the
-// SecCertificateRef is correct. On later versions where
-// SecCertificateCreateFromData() immediately parses, rather than lazily, this
-// call is cheap, as the subject is cached.
-bool IsValidOSCertHandle(SecCertificateRef cert_handle) {
-  ScopedCFTypeRef<CFStringRef> sanity_check(
-      SecCertificateCopySubjectSummary(cert_handle));
-  return sanity_check != nullptr;
-}
-
-void CreateOSCertHandlesFromPKCS7Bytes(
-    const char* data,
-    size_t length,
-    X509Certificate::OSCertHandles* handles) {
-  crypto::EnsureOpenSSLInit();
-  crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE);
-
-  CBS der_data;
-  CBS_init(&der_data, reinterpret_cast<const uint8_t*>(data), length);
-  STACK_OF(X509)* certs = sk_X509_new_null();
-
-  if (PKCS7_get_certificates(certs, &der_data)) {
-    for (size_t i = 0; i < sk_X509_num(certs); ++i) {
-      X509* x509_cert = sk_X509_value(certs, i);
-      base::StringPiece der;
-      if (!x509_util::GetDER(x509_cert, &der))
-        return;
-      handles->push_back(X509Certificate::CreateOSCertHandleFromBytes(
-          der.data(), der.length()));
-    }
-  }
-  sk_X509_pop_free(certs, X509_free);
-}
-
-void ParsePrincipalValues(X509_NAME* name,
-                          int nid,
-                          std::vector<std::string>* fields) {
-  for (int index = -1;
-       (index = X509_NAME_get_index_by_NID(name, nid, index)) != -1;) {
-    std::string field;
-    if (!x509_util::ParsePrincipalValueByIndex(name, index, &field))
-      break;
-    fields->push_back(field);
-  }
-}
-
-void ParsePrincipal(X509Certificate::OSCertHandle os_cert,
-                    X509_NAME* x509_name,
-                    CertPrincipal* principal) {
-  if (!x509_name)
-    return;
-
-  ParsePrincipalValues(x509_name, NID_streetAddress,
-                       &principal->street_addresses);
-  ParsePrincipalValues(x509_name, NID_organizationName,
-                       &principal->organization_names);
-  ParsePrincipalValues(x509_name, NID_organizationalUnitName,
-                       &principal->organization_unit_names);
-  ParsePrincipalValues(x509_name, NID_domainComponent,
-                       &principal->domain_components);
-
-  x509_util::ParsePrincipalValueByNID(x509_name, NID_commonName,
-                                      &principal->common_name);
-  x509_util::ParsePrincipalValueByNID(x509_name, NID_localityName,
-                                      &principal->locality_name);
-  x509_util::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName,
-                                      &principal->state_or_province_name);
-  x509_util::ParsePrincipalValueByNID(x509_name, NID_countryName,
-                                      &principal->country_name);
-}
-
-void ParseSubjectAltName(X509Certificate::OSCertHandle os_cert,
-                         std::vector<std::string>* dns_names,
-                         std::vector<std::string>* ip_addresses) {
-  DCHECK(dns_names || ip_addresses);
-  ScopedX509 cert = OSCertHandleToOpenSSL(os_cert);
-  if (!cert.get())
-    return;
-  int index = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1);
-  X509_EXTENSION* alt_name_ext = X509_get_ext(cert.get(), index);
-  if (!alt_name_ext)
-    return;
-
-  ScopedGENERAL_NAMES alt_names(
-      reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext)));
-  if (!alt_names.get())
-    return;
-
-  for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) {
-    const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i);
-    if (name->type == GEN_DNS && dns_names) {
-      const unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName);
-      if (!dns_name)
-        continue;
-      int dns_name_len = ASN1_STRING_length(name->d.dNSName);
-      dns_names->push_back(
-          std::string(reinterpret_cast<const char*>(dns_name), dns_name_len));
-    } else if (name->type == GEN_IPADD && ip_addresses) {
-      const unsigned char* ip_addr = name->d.iPAddress->data;
-      if (!ip_addr)
-        continue;
-      int ip_addr_len = name->d.iPAddress->length;
-      if (ip_addr_len != static_cast<int>(kIPv4AddressSize) &&
-          ip_addr_len != static_cast<int>(kIPv6AddressSize)) {
-        // http://www.ietf.org/rfc/rfc3280.txt requires subjectAltName iPAddress
-        // to have 4 or 16 bytes, whereas in a name constraint it includes a
-        // net mask hence 8 or 32 bytes. Logging to help diagnose any mixup.
-        LOG(WARNING) << "Bad sized IP Address in cert: " << ip_addr_len;
-        continue;
-      }
-      ip_addresses->push_back(
-          std::string(reinterpret_cast<const char*>(ip_addr), ip_addr_len));
-    }
-  }
-}
-
-// Used to free a list of X509_NAMEs and the objects it points to.
-void sk_X509_NAME_free_all(STACK_OF(X509_NAME) * sk) {
-  sk_X509_NAME_pop_free(sk, X509_NAME_free);
-}
-
-}  // namespace
-
-// static
-X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
-    OSCertHandle handle) {
-  if (!handle)
-    return nullptr;
-  return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle)));
-}
-
-// static
-void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
-  if (cert_handle)
-    CFRelease(cert_handle);
-}
-
-void X509Certificate::Initialize() {
-  crypto::EnsureOpenSSLInit();
-  fingerprint_ = CalculateFingerprint(cert_handle_);
-  ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_);
-  ScopedX509 x509_cert = OSCertHandleToOpenSSL(cert_handle_);
-  if (!x509_cert)
-    return;
-  ASN1_INTEGER* serial_num = X509_get_serialNumber(x509_cert.get());
-  if (serial_num) {
-    // ASN1_INTEGERS represent the decoded number, in a format internal to
-    // OpenSSL. Most notably, this may have leading zeroes stripped off for
-    // numbers whose first byte is >= 0x80. Thus, it is necessary to
-    // re-encoded the integer back into DER, which is what the interface
-    // of X509Certificate exposes, to ensure callers get the proper (DER)
-    // value.
-    int bytes_required = i2c_ASN1_INTEGER(serial_num, nullptr);
-    unsigned char* buffer = reinterpret_cast<unsigned char*>(
-        base::WriteInto(&serial_number_, bytes_required + 1));
-    int bytes_written = i2c_ASN1_INTEGER(serial_num, &buffer);
-    DCHECK_EQ(static_cast<size_t>(bytes_written), serial_number_.size());
-  }
-
-  ParsePrincipal(cert_handle_, X509_get_subject_name(x509_cert.get()),
-                 &subject_);
-  ParsePrincipal(cert_handle_, X509_get_issuer_name(x509_cert.get()), &issuer_);
-  x509_util::ParseDate(X509_get_notBefore(x509_cert.get()), &valid_start_);
-  x509_util::ParseDate(X509_get_notAfter(x509_cert.get()), &valid_expiry_);
-}
-
-// static
-SHA1HashValue X509Certificate::CalculateFingerprint(OSCertHandle cert) {
-  SHA1HashValue sha1;
-  memset(sha1.data, 0, sizeof(sha1.data));
-
-  ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert));
-  if (!cert_data)
-    return sha1;
-  DCHECK(CFDataGetBytePtr(cert_data));
-  DCHECK_NE(0, CFDataGetLength(cert_data));
-  CC_SHA1(CFDataGetBytePtr(cert_data), CFDataGetLength(cert_data), sha1.data);
-
-  return sha1;
-}
-
-// static
-SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) {
-  SHA256HashValue sha256;
-  memset(sha256.data, 0, sizeof(sha256.data));
-
-  ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert));
-  if (!cert_data)
-    return sha256;
-  DCHECK(CFDataGetBytePtr(cert_data));
-  DCHECK_NE(0, CFDataGetLength(cert_data));
-  CC_SHA256(CFDataGetBytePtr(cert_data), CFDataGetLength(cert_data),
-            sha256.data);
-
-  return sha256;
-}
-
-// static
-SHA1HashValue X509Certificate::CalculateCAFingerprint(
-    const OSCertHandles& intermediates) {
-  SHA1HashValue sha1;
-  memset(sha1.data, 0, sizeof(sha1.data));
-
-  CC_SHA1_CTX sha1_ctx;
-  CC_SHA1_Init(&sha1_ctx);
-  for (size_t i = 0; i < intermediates.size(); ++i) {
-    ScopedCFTypeRef<CFDataRef> cert_data(
-        SecCertificateCopyData(intermediates[i]));
-    if (!cert_data)
-      return sha1;
-    CC_SHA1_Update(&sha1_ctx, CFDataGetBytePtr(cert_data),
-                   CFDataGetLength(cert_data));
-  }
-  CC_SHA1_Final(sha1.data, &sha1_ctx);
-  return sha1;
-}
-
-// static
-X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
-    const char* data,
-    size_t length) {
-  ScopedCFTypeRef<CFDataRef> cert_data(CFDataCreateWithBytesNoCopy(
-      kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data),
-      base::checked_cast<CFIndex>(length), kCFAllocatorNull));
-  if (!cert_data)
-    return nullptr;
-  OSCertHandle cert_handle = SecCertificateCreateWithData(nullptr, cert_data);
-  if (!cert_handle)
-    return nullptr;
-  if (!IsValidOSCertHandle(cert_handle)) {
-    CFRelease(cert_handle);
-    return nullptr;
-  }
-  return cert_handle;
-}
-
-// static
-X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
-    const char* data,
-    size_t length,
-    Format format) {
-  OSCertHandles results;
-
-  switch (format) {
-    case FORMAT_SINGLE_CERTIFICATE: {
-      OSCertHandle handle =
-          X509Certificate::CreateOSCertHandleFromBytes(data, length);
-      if (handle)
-        results.push_back(handle);
-      break;
-    }
-    case FORMAT_PKCS7: {
-      CreateOSCertHandlesFromPKCS7Bytes(data, length, &results);
-      break;
-    }
-    default: {
-      NOTREACHED() << "Certificate format " << format << " unimplemented";
-      break;
-    }
-  }
-
-  return results;
-}
-
-void X509Certificate::GetSubjectAltName(
-    std::vector<std::string>* dns_names,
-    std::vector<std::string>* ip_addrs) const {
-  if (dns_names)
-    dns_names->clear();
-  if (ip_addrs)
-    ip_addrs->clear();
-
-  ParseSubjectAltName(cert_handle_, dns_names, ip_addrs);
-}
-
-// static
-bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle,
-                                    std::string* encoded) {
-  base::StringPiece der;
-  if (!cert_handle)
-    return false;
-  ScopedCFTypeRef<CFDataRef> der_data(SecCertificateCopyData(cert_handle));
-  if (!der_data)
-    return false;
-  encoded->assign(reinterpret_cast<const char*>(CFDataGetBytePtr(der_data)),
-                  CFDataGetLength(der_data));
-  return true;
-}
-
-// static
-bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
-                                   X509Certificate::OSCertHandle b) {
-  DCHECK(a && b);
-  return CFEqual(a, b);
-}
-
-// static
-X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle(
-    base::PickleIterator* pickle_iter) {
-  const char* data;
-  int length;
-  if (!pickle_iter->ReadData(&data, &length))
-    return nullptr;
-
-  return X509Certificate::CreateOSCertHandleFromBytes(data, length);
-}
-
-// static
-bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle,
-                                                base::Pickle* pickle) {
-  ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert_handle));
-  if (!cert_data)
-    return false;
-
-  return pickle->WriteData(
-      reinterpret_cast<const char*>(CFDataGetBytePtr(cert_data)),
-      CFDataGetLength(cert_data));
-}
-
-// static
-void X509Certificate::GetPublicKeyInfo(OSCertHandle os_cert,
-                                       size_t* size_bits,
-                                       PublicKeyType* type) {
-  *type = kPublicKeyTypeUnknown;
-  *size_bits = 0;
-  ScopedX509 cert = OSCertHandleToOpenSSL(os_cert);
-  if (!cert)
-    return;
-  crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert.get()));
-  if (!scoped_key)
-    return;
-
-  EVP_PKEY* key = scoped_key.get();
-
-  switch (key->type) {
-    case EVP_PKEY_RSA:
-      *type = kPublicKeyTypeRSA;
-      break;
-    case EVP_PKEY_DSA:
-      *type = kPublicKeyTypeDSA;
-      break;
-    case EVP_PKEY_EC:
-      *type = kPublicKeyTypeECDSA;
-      break;
-    case EVP_PKEY_DH:
-      *type = kPublicKeyTypeDH;
-      break;
-  }
-  *size_bits = EVP_PKEY_bits(key);
-}
-
-bool X509Certificate::SupportsSSLClientAuth() const {
-  return false;
-}
-
-CFMutableArrayRef X509Certificate::CreateOSCertChainForCert() const {
-  CFMutableArrayRef cert_list =
-      CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-  if (!cert_list)
-    return nullptr;
-
-  CFArrayAppendValue(cert_list, os_cert_handle());
-  for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i)
-    CFArrayAppendValue(cert_list, intermediate_ca_certs_[i]);
-
-  return cert_list;
-}
-
-bool X509Certificate::IsIssuedByEncoded(
-    const std::vector<std::string>& valid_issuers) {
-  if (valid_issuers.empty())
-    return false;
-
-  // Convert to a temporary list of X509_NAME objects.
-  // It will own the objects it points to.
-  crypto::ScopedOpenSSL<STACK_OF(X509_NAME), sk_X509_NAME_free_all>
-      issuer_names(sk_X509_NAME_new_null());
-  if (!issuer_names)
-    return false;
-
-  for (std::vector<std::string>::const_iterator it = valid_issuers.begin();
-       it != valid_issuers.end(); ++it) {
-    const unsigned char* p = reinterpret_cast<const unsigned char*>(it->data());
-    long len = static_cast<long>(it->length());
-    X509_NAME* ca_name = d2i_X509_NAME(nullptr, &p, len);
-    if (ca_name == nullptr)
-      return false;
-    sk_X509_NAME_push(issuer_names.get(), ca_name);
-  }
-
-  ScopedX509 x509_cert = OSCertHandleToOpenSSL(cert_handle_);
-  if (!x509_cert)
-    return false;
-  X509_NAME* cert_issuer = X509_get_issuer_name(x509_cert.get());
-  if (cert_issuer == nullptr)
-    return false;
-
-  for (size_t m = 0; m < sk_X509_NAME_num(issuer_names.get()); ++m) {
-    X509_NAME* issuer = sk_X509_NAME_value(issuer_names.get(), m);
-    if (X509_NAME_cmp(issuer, cert_issuer) == 0) {
-      return true;
-    }
-  }
-
-  for (OSCertHandles::iterator it = intermediate_ca_certs_.begin();
-       it != intermediate_ca_certs_.end(); ++it) {
-    ScopedX509 intermediate_cert = OSCertHandleToOpenSSL(*it);
-    if (!intermediate_cert)
-      return false;
-    cert_issuer = X509_get_issuer_name(intermediate_cert.get());
-    if (cert_issuer == nullptr)
-      return false;
-
-    for (size_t m = 0; m < sk_X509_NAME_num(issuer_names.get()); ++m) {
-      X509_NAME* issuer = sk_X509_NAME_value(issuer_names.get(), m);
-      if (X509_NAME_cmp(issuer, cert_issuer) == 0) {
-        return true;
-      }
-    }
-  }
-
-  return false;
-}
-
-// static
-bool X509Certificate::IsSelfSigned(OSCertHandle os_cert) {
-  ScopedX509 cert = OSCertHandleToOpenSSL(os_cert);
-  if (!cert)
-    return false;
-  crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert.get()));
-  if (!scoped_key)
-    return false;
-
-  // NOTE: X509_verify() returns 1 in case of success, 0 or -1 on error.
-  return X509_verify(cert.get(), scoped_key.get()) == 1;
-}
-
-}  // namespace net
diff --git a/net/cert/x509_certificate_win.cc b/net/cert/x509_certificate_win.cc
index 6d1fbe8..7d8e531 100644
--- a/net/cert/x509_certificate_win.cc
+++ b/net/cert/x509_certificate_win.cc
@@ -6,6 +6,8 @@
 
 #include <memory>
 
+#include <openssl/sha.h>
+
 #include "base/logging.h"
 #include "base/memory/free_deleter.h"
 #include "base/numerics/safe_conversions.h"
@@ -18,13 +20,6 @@
 #include "crypto/sha2.h"
 #include "net/base/net_errors.h"
 
-// Implement CalculateChainFingerprint() with our native crypto library.
-#if defined(USE_OPENSSL)
-#include <openssl/sha.h>
-#else
-#include <blapi.h>
-#endif
-
 using base::Time;
 
 namespace net {
@@ -340,7 +335,6 @@
   SHA1HashValue sha1;
   memset(sha1.data, 0, sizeof(sha1.data));
 
-#if defined(USE_OPENSSL)
   SHA_CTX ctx;
   if (!SHA1_Init(&ctx))
     return sha1;
@@ -350,19 +344,6 @@
       return sha1;
   }
   SHA1_Final(sha1.data, &ctx);
-#else  // !USE_OPENSSL
-  SHA1Context* sha1_ctx = SHA1_NewContext();
-  if (!sha1_ctx)
-    return sha1;
-  SHA1_Begin(sha1_ctx);
-  for (size_t i = 0; i < intermediates.size(); ++i) {
-    PCCERT_CONTEXT ca_cert = intermediates[i];
-    SHA1_Update(sha1_ctx, ca_cert->pbCertEncoded, ca_cert->cbCertEncoded);
-  }
-  unsigned int result_len;
-  SHA1_End(sha1_ctx, sha1.data, &result_len, SHA1_LENGTH);
-  SHA1_DestroyContext(sha1_ctx, PR_TRUE);
-#endif  // USE_OPENSSL
 
   return sha1;
 }
diff --git a/net/cert/x509_util_ios.cc b/net/cert/x509_util_ios.cc
deleted file mode 100644
index 0c644a8..0000000
--- a/net/cert/x509_util_ios.cc
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/cert/x509_util_ios.h"
-
-#include <cert.h>
-#include <CommonCrypto/CommonDigest.h>
-#include <nss.h>
-#include <prtypes.h>
-
-#include "base/mac/scoped_cftyperef.h"
-#include "base/memory/ref_counted.h"
-#include "crypto/nss_util.h"
-#include "net/cert/x509_certificate.h"
-#include "net/cert/x509_util_nss.h"
-
-using base::ScopedCFTypeRef;
-
-namespace net {
-namespace x509_util_ios {
-
-namespace {
-
-// Creates an NSS certificate handle from |data|, which is |length| bytes in
-// size.
-CERTCertificate* CreateNSSCertHandleFromBytes(const char* data,
-                                              int length) {
-  if (length < 0)
-    return NULL;
-
-  crypto::EnsureNSSInit();
-
-  if (!NSS_IsInitialized())
-    return NULL;
-
-  SECItem der_cert;
-  der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data));
-  der_cert.len  = length;
-  der_cert.type = siDERCertBuffer;
-
-  // Parse into a certificate structure.
-  return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert, NULL,
-                                 PR_FALSE, PR_TRUE);
-}
-
-}  // namespace
-
-CERTCertificate* CreateNSSCertHandleFromOSHandle(
-    SecCertificateRef cert_handle) {
-  ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert_handle));
-  return CreateNSSCertHandleFromBytes(
-      reinterpret_cast<const char*>(CFDataGetBytePtr(cert_data)),
-      CFDataGetLength(cert_data));
-}
-
-SecCertificateRef CreateOSCertHandleFromNSSHandle(
-    CERTCertificate* nss_cert_handle) {
-  return X509Certificate::CreateOSCertHandleFromBytes(
-      reinterpret_cast<const char*>(nss_cert_handle->derCert.data),
-      nss_cert_handle->derCert.len);
-}
-
-scoped_refptr<X509Certificate> CreateCertFromNSSHandles(
-    CERTCertificate* cert_handle,
-    const std::vector<CERTCertificate*>& intermediates) {
-  ScopedCFTypeRef<SecCertificateRef> os_server_cert(
-      CreateOSCertHandleFromNSSHandle(cert_handle));
-  if (!os_server_cert)
-    return nullptr;
-  std::vector<SecCertificateRef> os_intermediates;
-  for (size_t i = 0; i < intermediates.size(); ++i) {
-    SecCertificateRef intermediate =
-        CreateOSCertHandleFromNSSHandle(intermediates[i]);
-    if (!intermediate)
-      break;
-    os_intermediates.push_back(intermediate);
-  }
-
-  scoped_refptr<X509Certificate> cert = nullptr;
-  if (intermediates.size() == os_intermediates.size()) {
-    cert = X509Certificate::CreateFromHandle(os_server_cert,
-                                             os_intermediates);
-  }
-
-  for (size_t i = 0; i < os_intermediates.size(); ++i)
-    CFRelease(os_intermediates[i]);
-  return cert;
-}
-
-SHA1HashValue CalculateFingerprintNSS(CERTCertificate* cert) {
-  DCHECK(cert->derCert.data);
-  DCHECK_NE(0U, cert->derCert.len);
-  SHA1HashValue sha1;
-  memset(sha1.data, 0, sizeof(sha1.data));
-  CC_SHA1(cert->derCert.data, cert->derCert.len, sha1.data);
-  return sha1;
-}
-
-// NSSCertificate implementation.
-
-NSSCertificate::NSSCertificate(SecCertificateRef cert_handle) {
-  nss_cert_handle_ = CreateNSSCertHandleFromOSHandle(cert_handle);
-  DLOG_IF(ERROR, cert_handle && !nss_cert_handle_)
-      << "Could not convert SecCertificateRef to CERTCertificate*";
-}
-
-NSSCertificate::~NSSCertificate() {
-  CERT_DestroyCertificate(nss_cert_handle_);
-}
-
-CERTCertificate* NSSCertificate::cert_handle() const {
-  return nss_cert_handle_;
-}
-
-// NSSCertChain implementation
-
-NSSCertChain::NSSCertChain(X509Certificate* certificate) {
-  DCHECK(certificate);
-  certs_.push_back(CreateNSSCertHandleFromOSHandle(
-      certificate->os_cert_handle()));
-  const X509Certificate::OSCertHandles& cert_intermediates =
-      certificate->GetIntermediateCertificates();
-  for (size_t i = 0; i < cert_intermediates.size(); ++i)
-    certs_.push_back(CreateNSSCertHandleFromOSHandle(cert_intermediates[i]));
-}
-
-NSSCertChain::~NSSCertChain() {
-  for (size_t i = 0; i < certs_.size(); ++i)
-    CERT_DestroyCertificate(certs_[i]);
-}
-
-CERTCertificate* NSSCertChain::cert_handle() const {
-  return certs_.empty() ? NULL : certs_.front();
-}
-
-const std::vector<CERTCertificate*>& NSSCertChain::cert_chain() const {
-  return certs_;
-}
-
-}  // namespace x509_util_ios
-}  // namespace net
diff --git a/net/cert/x509_util_ios.h b/net/cert/x509_util_ios.h
deleted file mode 100644
index eb937552..0000000
--- a/net/cert/x509_util_ios.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file contains functions for iOS to glue NSS and Security.framework
-// together.
-
-#ifndef NET_CERT_X509_UTIL_IOS_H_
-#define NET_CERT_X509_UTIL_IOS_H_
-
-#include <Security/Security.h>
-#include <vector>
-
-#include "base/memory/ref_counted.h"
-#include "net/cert/x509_cert_types.h"
-
-// Forward declaration; real one in <cert.h>
-typedef struct CERTCertificateStr CERTCertificate;
-
-namespace net {
-
-class X509Certificate;
-
-namespace x509_util_ios {
-
-// Converts a Security.framework certificate handle (SecCertificateRef) into
-// an NSS certificate handle (CERTCertificate*).
-CERTCertificate* CreateNSSCertHandleFromOSHandle(SecCertificateRef cert_handle);
-
-// Converts an NSS certificate handle (CERTCertificate*) into a
-// Security.framework handle (SecCertificateRef)
-SecCertificateRef CreateOSCertHandleFromNSSHandle(
-    CERTCertificate* nss_cert_handle);
-
-// Create a new X509Certificate from the specified NSS server cert and
-// intermediates. This is functionally equivalent to
-// X509Certificate::CreateFromHandle(), except it supports receiving
-// NSS CERTCertificate*s rather than iOS SecCertificateRefs.
-scoped_refptr<X509Certificate> CreateCertFromNSSHandles(
-    CERTCertificate* cert_handle,
-    const std::vector<CERTCertificate*>& intermediates);
-
-SHA1HashValue CalculateFingerprintNSS(CERTCertificate* cert);
-
-// This is a wrapper class around the native NSS certificate handle.
-// The constructor copies the certificate data from |cert_handle| and
-// uses the NSS library to parse it.
-class NSSCertificate {
- public:
-  explicit NSSCertificate(SecCertificateRef cert_handle);
-  ~NSSCertificate();
-  CERTCertificate* cert_handle() const;
- private:
-  CERTCertificate* nss_cert_handle_;
-};
-
-// A wrapper class that loads a certificate and all of its intermediates into
-// NSS. This is necessary for libpkix path building to be able to locate
-// needed intermediates.
-class NSSCertChain {
- public:
-  explicit NSSCertChain(X509Certificate* certificate);
-  ~NSSCertChain();
-  CERTCertificate* cert_handle() const;
-  const std::vector<CERTCertificate*>& cert_chain() const;
- private:
-  std::vector<CERTCertificate*> certs_;
-};
-
-}  // namespace x509_util_ios
-}  // namespace net
-
-#endif  // NET_CERT_X509_UTIL_IOS_H_
diff --git a/net/cert/x509_util_nss.cc b/net/cert/x509_util_nss.cc
index d059eb3..134c085 100644
--- a/net/cert/x509_util_nss.cc
+++ b/net/cert/x509_util_nss.cc
@@ -1,9 +1,7 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/cert/x509_util_nss.h"
-
 #include <cert.h>  // Must be included before certdb.h
 #include <certdb.h>
 #include <cryptohi.h>
@@ -19,6 +17,7 @@
 #include "base/debug/leak_annotations.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/pickle.h"
 #include "base/strings/stringprintf.h"
 #include "crypto/ec_private_key.h"
@@ -29,164 +28,389 @@
 #include "crypto/third_party/nss/chromium-nss.h"
 #include "net/cert/x509_certificate.h"
 #include "net/cert/x509_util.h"
+#include "net/cert/x509_util_nss.h"
 
 namespace net {
 
 namespace {
 
-// Creates a Certificate object that may be passed to the SignCertificate
-// method to generate an X509 certificate.
-// Returns NULL if an error is encountered in the certificate creation
-// process.
-// Caller responsible for freeing returned certificate object.
-CERTCertificate* CreateCertificate(SECKEYPublicKey* public_key,
-                                   const std::string& subject,
-                                   uint32_t serial_number,
-                                   base::Time not_valid_before,
-                                   base::Time not_valid_after) {
-  // Create info about public key.
-  CERTSubjectPublicKeyInfo* spki =
-      SECKEY_CreateSubjectPublicKeyInfo(public_key);
-  if (!spki)
-    return NULL;
+// Microsoft User Principal Name: 1.3.6.1.4.1.311.20.2.3
+const uint8_t kUpnOid[] = {0x2b, 0x6,  0x1,  0x4, 0x1,
+                           0x82, 0x37, 0x14, 0x2, 0x3};
 
-  // Create the certificate request.
-  CERTName* subject_name =
-      CERT_AsciiToName(const_cast<char*>(subject.c_str()));
-  CERTCertificateRequest* cert_request =
-      CERT_CreateCertificateRequest(subject_name, spki, NULL);
-  SECKEY_DestroySubjectPublicKeyInfo(spki);
+// Callback for CERT_DecodeCertPackage(), used in
+// CreateOSCertHandlesFromBytes().
+SECStatus PR_CALLBACK CollectCertsCallback(void* arg,
+                                           SECItem** certs,
+                                           int num_certs) {
+  X509Certificate::OSCertHandles* results =
+      reinterpret_cast<X509Certificate::OSCertHandles*>(arg);
 
-  if (!cert_request) {
-    PRErrorCode prerr = PR_GetError();
-    LOG(ERROR) << "Failed to create certificate request: " << prerr;
-    CERT_DestroyName(subject_name);
-    return NULL;
+  for (int i = 0; i < num_certs; ++i) {
+    X509Certificate::OSCertHandle handle =
+        X509Certificate::CreateOSCertHandleFromBytes(
+            reinterpret_cast<char*>(certs[i]->data), certs[i]->len);
+    if (handle)
+      results->push_back(handle);
   }
 
-  CERTValidity* validity = CERT_CreateValidity(
-      crypto::BaseTimeToPRTime(not_valid_before),
-      crypto::BaseTimeToPRTime(not_valid_after));
-  if (!validity) {
-    PRErrorCode prerr = PR_GetError();
-    LOG(ERROR) << "Failed to create certificate validity object: " << prerr;
-    CERT_DestroyName(subject_name);
-    CERT_DestroyCertificateRequest(cert_request);
-    return NULL;
-  }
-  CERTCertificate* cert = CERT_CreateCertificate(serial_number, subject_name,
-                                                 validity, cert_request);
-  if (!cert) {
-    PRErrorCode prerr = PR_GetError();
-    LOG(ERROR) << "Failed to create certificate: " << prerr;
-  }
-
-  // Cleanup for resources used to generate the cert.
-  CERT_DestroyName(subject_name);
-  CERT_DestroyValidity(validity);
-  CERT_DestroyCertificateRequest(cert_request);
-
-  return cert;
+  return SECSuccess;
 }
 
-SECOidTag ToSECOid(x509_util::DigestAlgorithm alg) {
-  switch (alg) {
-    case x509_util::DIGEST_SHA1:
-      return SEC_OID_SHA1;
-    case x509_util::DIGEST_SHA256:
-      return SEC_OID_SHA256;
-  }
-  return SEC_OID_UNKNOWN;
-}
+typedef std::unique_ptr<CERTName,
+                        crypto::NSSDestroyer<CERTName, CERT_DestroyName>>
+    ScopedCERTName;
 
-// Signs a certificate object, with |key| generating a new X509Certificate
-// and destroying the passed certificate object (even when NULL is returned).
-// The logic of this method references SignCert() in NSS utility certutil:
-// http://mxr.mozilla.org/security/ident?i=SignCert.
-// Returns true on success or false if an error is encountered in the
-// certificate signing process.
-bool SignCertificate(
-    CERTCertificate* cert,
-    SECKEYPrivateKey* key,
-    SECOidTag hash_algorithm) {
-  // |arena| is used to encode the cert.
-  PLArenaPool* arena = cert->arena;
-  SECOidTag algo_id = SEC_GetSignatureAlgorithmOidTag(key->keyType,
-                                                      hash_algorithm);
-  if (algo_id == SEC_OID_UNKNOWN)
-    return false;
+// Create a new CERTName object from its encoded representation.
+// |arena| is the allocation pool to use.
+// |data| points to a DER-encoded X.509 DistinguishedName.
+// Return a new CERTName pointer on success, or NULL.
+CERTName* CreateCertNameFromEncoded(PLArenaPool* arena,
+                                    const base::StringPiece& data) {
+  if (!arena)
+    return NULL;
 
-  SECStatus rv = SECOID_SetAlgorithmID(arena, &cert->signature, algo_id, 0);
+  ScopedCERTName name(PORT_ArenaZNew(arena, CERTName));
+  if (!name.get())
+    return NULL;
+
+  SECItem item;
+  item.len = static_cast<unsigned int>(data.length());
+  item.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data.data()));
+
+  SECStatus rv = SEC_ASN1DecodeItem(arena, name.get(),
+                                    SEC_ASN1_GET(CERT_NameTemplate), &item);
   if (rv != SECSuccess)
-    return false;
+    return NULL;
 
-  // Generate a cert of version 3.
-  *(cert->version.data) = 2;
-  cert->version.len = 1;
-
-  SECItem der = { siBuffer, NULL, 0 };
-
-  // Use ASN1 DER to encode the cert.
-  void* encode_result = SEC_ASN1EncodeItem(
-      NULL, &der, cert, SEC_ASN1_GET(CERT_CertificateTemplate));
-  if (!encode_result)
-    return false;
-
-  // Allocate space to contain the signed cert.
-  SECItem result = { siBuffer, NULL, 0 };
-
-  // Sign the ASN1 encoded cert and save it to |result|.
-  rv = DerSignData(arena, &result, &der, key, algo_id);
-  PORT_Free(der.data);
-  if (rv != SECSuccess) {
-    DLOG(ERROR) << "DerSignData: " << PORT_GetError();
-    return false;
-  }
-
-  // Save the signed result to the cert.
-  cert->derCert = result;
-
-  return true;
+  return name.release();
 }
 
 }  // namespace
 
 namespace x509_util {
 
-bool CreateSelfSignedCert(crypto::RSAPrivateKey* key,
-                          DigestAlgorithm alg,
-                          const std::string& subject,
-                          uint32_t serial_number,
-                          base::Time not_valid_before,
-                          base::Time not_valid_after,
-                          std::string* der_cert) {
-  DCHECK(key);
-  DCHECK(!strncmp(subject.c_str(), "CN=", 3U));
-  CERTCertificate* cert = CreateCertificate(key->public_key(),
-                                            subject,
-                                            serial_number,
-                                            not_valid_before,
-                                            not_valid_after);
-  if (!cert)
-    return false;
+void ParsePrincipal(CERTName* name, CertPrincipal* principal) {
+// Starting in NSS 3.15, CERTGetNameFunc takes a const CERTName* argument.
+#if NSS_VMINOR >= 15
+  typedef char* (*CERTGetNameFunc)(const CERTName* name);
+#else
+  typedef char* (*CERTGetNameFunc)(CERTName * name);
+#endif
 
-  if (!SignCertificate(cert, key->key(), ToSECOid(alg))) {
-    CERT_DestroyCertificate(cert);
-    return false;
+  // TODO(jcampan): add business_category and serial_number.
+  // TODO(wtc): NSS has the CERT_GetOrgName, CERT_GetOrgUnitName, and
+  // CERT_GetDomainComponentName functions, but they return only the most
+  // general (the first) RDN.  NSS doesn't have a function for the street
+  // address.
+  static const SECOidTag kOIDs[] = {
+      SEC_OID_AVA_STREET_ADDRESS, SEC_OID_AVA_ORGANIZATION_NAME,
+      SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME, SEC_OID_AVA_DC};
+
+  std::vector<std::string>* values[] = {
+      &principal->street_addresses, &principal->organization_names,
+      &principal->organization_unit_names, &principal->domain_components};
+  DCHECK_EQ(arraysize(kOIDs), arraysize(values));
+
+  CERTRDN** rdns = name->rdns;
+  for (size_t rdn = 0; rdns[rdn]; ++rdn) {
+    CERTAVA** avas = rdns[rdn]->avas;
+    for (size_t pair = 0; avas[pair] != 0; ++pair) {
+      SECOidTag tag = CERT_GetAVATag(avas[pair]);
+      for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
+        if (kOIDs[oid] == tag) {
+          SECItem* decode_item = CERT_DecodeAVAValue(&avas[pair]->value);
+          if (!decode_item)
+            break;
+          // TODO(wtc): Pass decode_item to CERT_RFC1485_EscapeAndQuote.
+          std::string value(reinterpret_cast<char*>(decode_item->data),
+                            decode_item->len);
+          values[oid]->push_back(value);
+          SECITEM_FreeItem(decode_item, PR_TRUE);
+          break;
+        }
+      }
+    }
   }
 
-  der_cert->assign(reinterpret_cast<char*>(cert->derCert.data),
-                   cert->derCert.len);
-  CERT_DestroyCertificate(cert);
-  return true;
+  // Get CN, L, S, and C.
+  CERTGetNameFunc get_name_funcs[4] = {CERT_GetCommonName, CERT_GetLocalityName,
+                                       CERT_GetStateName, CERT_GetCountryName};
+  std::string* single_values[4] = {
+      &principal->common_name, &principal->locality_name,
+      &principal->state_or_province_name, &principal->country_name};
+  for (size_t i = 0; i < arraysize(get_name_funcs); ++i) {
+    char* value = get_name_funcs[i](name);
+    if (value) {
+      single_values[i]->assign(value);
+      PORT_Free(value);
+    }
+  }
 }
 
-bool GetTLSServerEndPointChannelBinding(const X509Certificate& certificate,
-                                        std::string* token) {
-  NOTIMPLEMENTED();
+void ParseDate(const SECItem* der_date, base::Time* result) {
+  PRTime prtime;
+  SECStatus rv = DER_DecodeTimeChoice(&prtime, der_date);
+  DCHECK_EQ(SECSuccess, rv);
+  *result = crypto::PRTimeToBaseTime(prtime);
+}
+
+std::string ParseSerialNumber(const CERTCertificate* certificate) {
+  return std::string(reinterpret_cast<char*>(certificate->serialNumber.data),
+                     certificate->serialNumber.len);
+}
+
+void GetSubjectAltName(CERTCertificate* cert_handle,
+                       std::vector<std::string>* dns_names,
+                       std::vector<std::string>* ip_addrs) {
+  if (dns_names)
+    dns_names->clear();
+  if (ip_addrs)
+    ip_addrs->clear();
+
+  SECItem alt_name;
+  SECStatus rv = CERT_FindCertExtension(
+      cert_handle, SEC_OID_X509_SUBJECT_ALT_NAME, &alt_name);
+  if (rv != SECSuccess)
+    return;
+
+  PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+  DCHECK(arena != NULL);
+
+  CERTGeneralName* alt_name_list;
+  alt_name_list = CERT_DecodeAltNameExtension(arena, &alt_name);
+  SECITEM_FreeItem(&alt_name, PR_FALSE);
+
+  CERTGeneralName* name = alt_name_list;
+  while (name) {
+    // DNSName and IPAddress are encoded as IA5String and OCTET STRINGs
+    // respectively, both of which can be byte copied from
+    // SECItemType::data into the appropriate output vector.
+    if (dns_names && name->type == certDNSName) {
+      dns_names->push_back(
+          std::string(reinterpret_cast<char*>(name->name.other.data),
+                      name->name.other.len));
+    } else if (ip_addrs && name->type == certIPAddress) {
+      ip_addrs->push_back(
+          std::string(reinterpret_cast<char*>(name->name.other.data),
+                      name->name.other.len));
+    }
+    name = CERT_GetNextGeneralName(name);
+    if (name == alt_name_list)
+      break;
+  }
+  PORT_FreeArena(arena, PR_FALSE);
+}
+
+void GetRFC822SubjectAltNames(CERTCertificate* cert_handle,
+                              std::vector<std::string>* names) {
+  crypto::ScopedSECItem alt_name(SECITEM_AllocItem(NULL, NULL, 0));
+  DCHECK(alt_name.get());
+
+  names->clear();
+  SECStatus rv = CERT_FindCertExtension(
+      cert_handle, SEC_OID_X509_SUBJECT_ALT_NAME, alt_name.get());
+  if (rv != SECSuccess)
+    return;
+
+  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
+  DCHECK(arena.get());
+
+  CERTGeneralName* alt_name_list;
+  alt_name_list = CERT_DecodeAltNameExtension(arena.get(), alt_name.get());
+
+  CERTGeneralName* name = alt_name_list;
+  while (name) {
+    if (name->type == certRFC822Name) {
+      names->push_back(
+          std::string(reinterpret_cast<char*>(name->name.other.data),
+                      name->name.other.len));
+    }
+    name = CERT_GetNextGeneralName(name);
+    if (name == alt_name_list)
+      break;
+  }
+}
+
+void GetUPNSubjectAltNames(CERTCertificate* cert_handle,
+                           std::vector<std::string>* names) {
+  crypto::ScopedSECItem alt_name(SECITEM_AllocItem(NULL, NULL, 0));
+  DCHECK(alt_name.get());
+
+  names->clear();
+  SECStatus rv = CERT_FindCertExtension(
+      cert_handle, SEC_OID_X509_SUBJECT_ALT_NAME, alt_name.get());
+  if (rv != SECSuccess)
+    return;
+
+  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
+  DCHECK(arena.get());
+
+  CERTGeneralName* alt_name_list;
+  alt_name_list = CERT_DecodeAltNameExtension(arena.get(), alt_name.get());
+
+  CERTGeneralName* name = alt_name_list;
+  while (name) {
+    if (name->type == certOtherName) {
+      OtherName* on = &name->name.OthName;
+      if (on->oid.len == sizeof(kUpnOid) &&
+          memcmp(on->oid.data, kUpnOid, sizeof(kUpnOid)) == 0) {
+        SECItem decoded;
+        if (SEC_QuickDERDecodeItem(arena.get(), &decoded,
+                                   SEC_ASN1_GET(SEC_UTF8StringTemplate),
+                                   &name->name.OthName.name) == SECSuccess) {
+          names->push_back(
+              std::string(reinterpret_cast<char*>(decoded.data), decoded.len));
+        }
+      }
+    }
+    name = CERT_GetNextGeneralName(name);
+    if (name == alt_name_list)
+      break;
+  }
+}
+
+X509Certificate::OSCertHandles CreateOSCertHandlesFromBytes(
+    const char* data,
+    size_t length,
+    X509Certificate::Format format) {
+  X509Certificate::OSCertHandles results;
+
+  crypto::EnsureNSSInit();
+
+  if (!NSS_IsInitialized())
+    return results;
+
+  switch (format) {
+    case X509Certificate::FORMAT_SINGLE_CERTIFICATE: {
+      X509Certificate::OSCertHandle handle =
+          X509Certificate::CreateOSCertHandleFromBytes(data, length);
+      if (handle)
+        results.push_back(handle);
+      break;
+    }
+    case X509Certificate::FORMAT_PKCS7: {
+      // Make a copy since CERT_DecodeCertPackage may modify it
+      std::vector<char> data_copy(data, data + length);
+
+      SECStatus result = CERT_DecodeCertPackage(
+          data_copy.data(), base::checked_cast<int>(data_copy.size()),
+          CollectCertsCallback, &results);
+      if (result != SECSuccess)
+        results.clear();
+      break;
+    }
+    default:
+      NOTREACHED() << "Certificate format " << format << " unimplemented";
+      break;
+  }
+
+  return results;
+}
+
+X509Certificate::OSCertHandle ReadOSCertHandleFromPickle(
+    base::PickleIterator* pickle_iter) {
+  const char* data;
+  int length;
+  if (!pickle_iter->ReadData(&data, &length))
+    return NULL;
+
+  return X509Certificate::CreateOSCertHandleFromBytes(data, length);
+}
+
+void GetPublicKeyInfo(CERTCertificate* handle,
+                      size_t* size_bits,
+                      X509Certificate::PublicKeyType* type) {
+  // Since we might fail, set the output parameters to default values first.
+  *type = X509Certificate::kPublicKeyTypeUnknown;
+  *size_bits = 0;
+
+  crypto::ScopedSECKEYPublicKey key(CERT_ExtractPublicKey(handle));
+  if (!key.get())
+    return;
+
+  *size_bits = SECKEY_PublicKeyStrengthInBits(key.get());
+
+  switch (key->keyType) {
+    case rsaKey:
+      *type = X509Certificate::kPublicKeyTypeRSA;
+      break;
+    case dsaKey:
+      *type = X509Certificate::kPublicKeyTypeDSA;
+      break;
+    case dhKey:
+      *type = X509Certificate::kPublicKeyTypeDH;
+      break;
+    case ecKey:
+      *type = X509Certificate::kPublicKeyTypeECDSA;
+      break;
+    default:
+      *type = X509Certificate::kPublicKeyTypeUnknown;
+      *size_bits = 0;
+      break;
+  }
+}
+
+bool GetIssuersFromEncodedList(const std::vector<std::string>& encoded_issuers,
+                               PLArenaPool* arena,
+                               std::vector<CERTName*>* out) {
+  std::vector<CERTName*> result;
+  for (size_t n = 0; n < encoded_issuers.size(); ++n) {
+    CERTName* name = CreateCertNameFromEncoded(arena, encoded_issuers[n]);
+    if (name != NULL)
+      result.push_back(name);
+  }
+
+  if (result.size() == encoded_issuers.size()) {
+    out->swap(result);
+    return true;
+  }
+
+  for (size_t n = 0; n < result.size(); ++n)
+    CERT_DestroyName(result[n]);
   return false;
 }
 
-} // namespace x509_util
+bool IsCertificateIssuedBy(const std::vector<CERTCertificate*>& cert_chain,
+                           const std::vector<CERTName*>& valid_issuers) {
+  for (size_t n = 0; n < cert_chain.size(); ++n) {
+    CERTName* cert_issuer = &cert_chain[n]->issuer;
+    for (size_t i = 0; i < valid_issuers.size(); ++i) {
+      if (CERT_CompareName(valid_issuers[i], cert_issuer) == SECEqual)
+        return true;
+    }
+  }
+  return false;
+}
 
-} // namespace net
+std::string GetUniqueNicknameForSlot(const std::string& nickname,
+                                     const SECItem* subject,
+                                     PK11SlotInfo* slot) {
+  int index = 2;
+  std::string new_name = nickname;
+  std::string temp_nickname = new_name;
+  std::string token_name;
+
+  if (!slot)
+    return new_name;
+
+  if (!PK11_IsInternalKeySlot(slot)) {
+    token_name.assign(PK11_GetTokenName(slot));
+    token_name.append(":");
+
+    temp_nickname = token_name + new_name;
+  }
+
+  while (SEC_CertNicknameConflict(temp_nickname.c_str(),
+                                  const_cast<SECItem*>(subject),
+                                  CERT_GetDefaultCertDB())) {
+    base::SStringPrintf(&new_name, "%s #%d", nickname.c_str(), index++);
+    temp_nickname = token_name + new_name;
+  }
+
+  return new_name;
+}
+
+}  // namespace x509_util
+
+}  // namespace net
diff --git a/net/cert/x509_util_nss.h b/net/cert/x509_util_nss.h
index c656264..b0ba592 100644
--- a/net/cert/x509_util_nss.h
+++ b/net/cert/x509_util_nss.h
@@ -28,7 +28,7 @@
 
 namespace x509_util {
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
 // Parses the Principal attribute from |name| and outputs the result in
 // |principal|.
 void ParsePrincipal(CERTName* name,
@@ -127,7 +127,7 @@
 std::string GetUniqueNicknameForSlot(const std::string& nickname,
                                      const SECItem* subject,
                                      PK11SlotInfo* slot);
-#endif  // defined(USE_NSS_VERIFIER)
+#endif  // defined(USE_NSS_CERTS)
 
 } // namespace x509_util
 
diff --git a/net/cert/x509_util_nss_certs.cc b/net/cert/x509_util_nss_certs.cc
deleted file mode 100644
index a94a5d47..0000000
--- a/net/cert/x509_util_nss_certs.cc
+++ /dev/null
@@ -1,420 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <cert.h>  // Must be included before certdb.h
-#include <certdb.h>
-#include <cryptohi.h>
-#include <nss.h>
-#include <pk11pub.h>
-#include <prerror.h>
-#include <secder.h>
-#include <secmod.h>
-#include <secport.h>
-
-#include <memory>
-
-#include "base/debug/leak_annotations.h"
-#include "base/logging.h"
-#include "base/memory/singleton.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/pickle.h"
-#include "base/strings/stringprintf.h"
-#include "crypto/ec_private_key.h"
-#include "crypto/nss_util.h"
-#include "crypto/nss_util_internal.h"
-#include "crypto/rsa_private_key.h"
-#include "crypto/scoped_nss_types.h"
-#include "crypto/third_party/nss/chromium-nss.h"
-#include "net/cert/x509_certificate.h"
-#include "net/cert/x509_util.h"
-#include "net/cert/x509_util_nss.h"
-
-namespace net {
-
-namespace {
-
-// Microsoft User Principal Name: 1.3.6.1.4.1.311.20.2.3
-const uint8_t kUpnOid[] = {0x2b, 0x6,  0x1,  0x4, 0x1,
-                           0x82, 0x37, 0x14, 0x2, 0x3};
-
-// Callback for CERT_DecodeCertPackage(), used in
-// CreateOSCertHandlesFromBytes().
-SECStatus PR_CALLBACK
-CollectCertsCallback(void* arg, SECItem** certs, int num_certs) {
-  X509Certificate::OSCertHandles* results =
-      reinterpret_cast<X509Certificate::OSCertHandles*>(arg);
-
-  for (int i = 0; i < num_certs; ++i) {
-    X509Certificate::OSCertHandle handle =
-        X509Certificate::CreateOSCertHandleFromBytes(
-            reinterpret_cast<char*>(certs[i]->data), certs[i]->len);
-    if (handle)
-      results->push_back(handle);
-  }
-
-  return SECSuccess;
-}
-
-typedef std::unique_ptr<CERTName,
-                        crypto::NSSDestroyer<CERTName, CERT_DestroyName>>
-    ScopedCERTName;
-
-// Create a new CERTName object from its encoded representation.
-// |arena| is the allocation pool to use.
-// |data| points to a DER-encoded X.509 DistinguishedName.
-// Return a new CERTName pointer on success, or NULL.
-CERTName* CreateCertNameFromEncoded(PLArenaPool* arena,
-                                    const base::StringPiece& data) {
-  if (!arena)
-    return NULL;
-
-  ScopedCERTName name(PORT_ArenaZNew(arena, CERTName));
-  if (!name.get())
-    return NULL;
-
-  SECItem item;
-  item.len = static_cast<unsigned int>(data.length());
-  item.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data.data()));
-
-  SECStatus rv = SEC_ASN1DecodeItem(arena, name.get(),
-                                    SEC_ASN1_GET(CERT_NameTemplate), &item);
-  if (rv != SECSuccess)
-    return NULL;
-
-  return name.release();
-}
-
-}  // namespace
-
-namespace x509_util {
-
-void ParsePrincipal(CERTName* name, CertPrincipal* principal) {
-// Starting in NSS 3.15, CERTGetNameFunc takes a const CERTName* argument.
-#if NSS_VMINOR >= 15
-  typedef char* (*CERTGetNameFunc)(const CERTName* name);
-#else
-  typedef char* (*CERTGetNameFunc)(CERTName* name);
-#endif
-
-  // TODO(jcampan): add business_category and serial_number.
-  // TODO(wtc): NSS has the CERT_GetOrgName, CERT_GetOrgUnitName, and
-  // CERT_GetDomainComponentName functions, but they return only the most
-  // general (the first) RDN.  NSS doesn't have a function for the street
-  // address.
-  static const SECOidTag kOIDs[] = {SEC_OID_AVA_STREET_ADDRESS,
-                                    SEC_OID_AVA_ORGANIZATION_NAME,
-                                    SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME,
-                                    SEC_OID_AVA_DC};
-
-  std::vector<std::string>* values[] = {&principal->street_addresses,
-                                        &principal->organization_names,
-                                        &principal->organization_unit_names,
-                                        &principal->domain_components};
-  DCHECK_EQ(arraysize(kOIDs), arraysize(values));
-
-  CERTRDN** rdns = name->rdns;
-  for (size_t rdn = 0; rdns[rdn]; ++rdn) {
-    CERTAVA** avas = rdns[rdn]->avas;
-    for (size_t pair = 0; avas[pair] != 0; ++pair) {
-      SECOidTag tag = CERT_GetAVATag(avas[pair]);
-      for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
-        if (kOIDs[oid] == tag) {
-          SECItem* decode_item = CERT_DecodeAVAValue(&avas[pair]->value);
-          if (!decode_item)
-            break;
-          // TODO(wtc): Pass decode_item to CERT_RFC1485_EscapeAndQuote.
-          std::string value(reinterpret_cast<char*>(decode_item->data),
-                            decode_item->len);
-          values[oid]->push_back(value);
-          SECITEM_FreeItem(decode_item, PR_TRUE);
-          break;
-        }
-      }
-    }
-  }
-
-  // Get CN, L, S, and C.
-  CERTGetNameFunc get_name_funcs[4] = {CERT_GetCommonName,
-                                       CERT_GetLocalityName,
-                                       CERT_GetStateName,
-                                       CERT_GetCountryName};
-  std::string* single_values[4] = {&principal->common_name,
-                                   &principal->locality_name,
-                                   &principal->state_or_province_name,
-                                   &principal->country_name};
-  for (size_t i = 0; i < arraysize(get_name_funcs); ++i) {
-    char* value = get_name_funcs[i](name);
-    if (value) {
-      single_values[i]->assign(value);
-      PORT_Free(value);
-    }
-  }
-}
-
-void ParseDate(const SECItem* der_date, base::Time* result) {
-  PRTime prtime;
-  SECStatus rv = DER_DecodeTimeChoice(&prtime, der_date);
-  DCHECK_EQ(SECSuccess, rv);
-  *result = crypto::PRTimeToBaseTime(prtime);
-}
-
-std::string ParseSerialNumber(const CERTCertificate* certificate) {
-  return std::string(reinterpret_cast<char*>(certificate->serialNumber.data),
-                     certificate->serialNumber.len);
-}
-
-void GetSubjectAltName(CERTCertificate* cert_handle,
-                       std::vector<std::string>* dns_names,
-                       std::vector<std::string>* ip_addrs) {
-  if (dns_names)
-    dns_names->clear();
-  if (ip_addrs)
-    ip_addrs->clear();
-
-  SECItem alt_name;
-  SECStatus rv = CERT_FindCertExtension(
-      cert_handle, SEC_OID_X509_SUBJECT_ALT_NAME, &alt_name);
-  if (rv != SECSuccess)
-    return;
-
-  PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-  DCHECK(arena != NULL);
-
-  CERTGeneralName* alt_name_list;
-  alt_name_list = CERT_DecodeAltNameExtension(arena, &alt_name);
-  SECITEM_FreeItem(&alt_name, PR_FALSE);
-
-  CERTGeneralName* name = alt_name_list;
-  while (name) {
-    // DNSName and IPAddress are encoded as IA5String and OCTET STRINGs
-    // respectively, both of which can be byte copied from
-    // SECItemType::data into the appropriate output vector.
-    if (dns_names && name->type == certDNSName) {
-      dns_names->push_back(
-          std::string(reinterpret_cast<char*>(name->name.other.data),
-                      name->name.other.len));
-    } else if (ip_addrs && name->type == certIPAddress) {
-      ip_addrs->push_back(
-          std::string(reinterpret_cast<char*>(name->name.other.data),
-                      name->name.other.len));
-    }
-    name = CERT_GetNextGeneralName(name);
-    if (name == alt_name_list)
-      break;
-  }
-  PORT_FreeArena(arena, PR_FALSE);
-}
-
-void GetRFC822SubjectAltNames(CERTCertificate* cert_handle,
-                              std::vector<std::string>* names) {
-  crypto::ScopedSECItem alt_name(SECITEM_AllocItem(NULL, NULL, 0));
-  DCHECK(alt_name.get());
-
-  names->clear();
-  SECStatus rv = CERT_FindCertExtension(
-      cert_handle, SEC_OID_X509_SUBJECT_ALT_NAME, alt_name.get());
-  if (rv != SECSuccess)
-    return;
-
-  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-  DCHECK(arena.get());
-
-  CERTGeneralName* alt_name_list;
-  alt_name_list = CERT_DecodeAltNameExtension(arena.get(), alt_name.get());
-
-  CERTGeneralName* name = alt_name_list;
-  while (name) {
-    if (name->type == certRFC822Name) {
-      names->push_back(
-          std::string(reinterpret_cast<char*>(name->name.other.data),
-                      name->name.other.len));
-    }
-    name = CERT_GetNextGeneralName(name);
-    if (name == alt_name_list)
-      break;
-  }
-}
-
-void GetUPNSubjectAltNames(CERTCertificate* cert_handle,
-                           std::vector<std::string>* names) {
-  crypto::ScopedSECItem alt_name(SECITEM_AllocItem(NULL, NULL, 0));
-  DCHECK(alt_name.get());
-
-  names->clear();
-  SECStatus rv = CERT_FindCertExtension(
-      cert_handle, SEC_OID_X509_SUBJECT_ALT_NAME, alt_name.get());
-  if (rv != SECSuccess)
-    return;
-
-  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-  DCHECK(arena.get());
-
-  CERTGeneralName* alt_name_list;
-  alt_name_list = CERT_DecodeAltNameExtension(arena.get(), alt_name.get());
-
-  CERTGeneralName* name = alt_name_list;
-  while (name) {
-    if (name->type == certOtherName) {
-      OtherName* on = &name->name.OthName;
-      if (on->oid.len == sizeof(kUpnOid) &&
-          memcmp(on->oid.data, kUpnOid, sizeof(kUpnOid)) == 0) {
-        SECItem decoded;
-        if (SEC_QuickDERDecodeItem(arena.get(), &decoded,
-                                   SEC_ASN1_GET(SEC_UTF8StringTemplate),
-                                   &name->name.OthName.name) == SECSuccess) {
-          names->push_back(
-              std::string(reinterpret_cast<char*>(decoded.data), decoded.len));
-        }
-      }
-    }
-    name = CERT_GetNextGeneralName(name);
-    if (name == alt_name_list)
-      break;
-  }
-}
-
-X509Certificate::OSCertHandles CreateOSCertHandlesFromBytes(
-    const char* data,
-    size_t length,
-    X509Certificate::Format format) {
-  X509Certificate::OSCertHandles results;
-
-  crypto::EnsureNSSInit();
-
-  if (!NSS_IsInitialized())
-    return results;
-
-  switch (format) {
-    case X509Certificate::FORMAT_SINGLE_CERTIFICATE: {
-      X509Certificate::OSCertHandle handle =
-          X509Certificate::CreateOSCertHandleFromBytes(data, length);
-      if (handle)
-        results.push_back(handle);
-      break;
-    }
-    case X509Certificate::FORMAT_PKCS7: {
-      // Make a copy since CERT_DecodeCertPackage may modify it
-      std::vector<char> data_copy(data, data + length);
-
-      SECStatus result = CERT_DecodeCertPackage(
-          data_copy.data(), base::checked_cast<int>(data_copy.size()),
-          CollectCertsCallback, &results);
-      if (result != SECSuccess)
-        results.clear();
-      break;
-    }
-    default:
-      NOTREACHED() << "Certificate format " << format << " unimplemented";
-      break;
-  }
-
-  return results;
-}
-
-X509Certificate::OSCertHandle ReadOSCertHandleFromPickle(
-    base::PickleIterator* pickle_iter) {
-  const char* data;
-  int length;
-  if (!pickle_iter->ReadData(&data, &length))
-    return NULL;
-
-  return X509Certificate::CreateOSCertHandleFromBytes(data, length);
-}
-
-void GetPublicKeyInfo(CERTCertificate* handle,
-                      size_t* size_bits,
-                      X509Certificate::PublicKeyType* type) {
-  // Since we might fail, set the output parameters to default values first.
-  *type = X509Certificate::kPublicKeyTypeUnknown;
-  *size_bits = 0;
-
-  crypto::ScopedSECKEYPublicKey key(CERT_ExtractPublicKey(handle));
-  if (!key.get())
-    return;
-
-  *size_bits = SECKEY_PublicKeyStrengthInBits(key.get());
-
-  switch (key->keyType) {
-    case rsaKey:
-      *type = X509Certificate::kPublicKeyTypeRSA;
-      break;
-    case dsaKey:
-      *type = X509Certificate::kPublicKeyTypeDSA;
-      break;
-    case dhKey:
-      *type = X509Certificate::kPublicKeyTypeDH;
-      break;
-    case ecKey:
-      *type = X509Certificate::kPublicKeyTypeECDSA;
-      break;
-    default:
-      *type = X509Certificate::kPublicKeyTypeUnknown;
-      *size_bits = 0;
-      break;
-  }
-}
-
-bool GetIssuersFromEncodedList(const std::vector<std::string>& encoded_issuers,
-                               PLArenaPool* arena,
-                               std::vector<CERTName*>* out) {
-  std::vector<CERTName*> result;
-  for (size_t n = 0; n < encoded_issuers.size(); ++n) {
-    CERTName* name = CreateCertNameFromEncoded(arena, encoded_issuers[n]);
-    if (name != NULL)
-      result.push_back(name);
-  }
-
-  if (result.size() == encoded_issuers.size()) {
-    out->swap(result);
-    return true;
-  }
-
-  for (size_t n = 0; n < result.size(); ++n)
-    CERT_DestroyName(result[n]);
-  return false;
-}
-
-bool IsCertificateIssuedBy(const std::vector<CERTCertificate*>& cert_chain,
-                           const std::vector<CERTName*>& valid_issuers) {
-  for (size_t n = 0; n < cert_chain.size(); ++n) {
-    CERTName* cert_issuer = &cert_chain[n]->issuer;
-    for (size_t i = 0; i < valid_issuers.size(); ++i) {
-      if (CERT_CompareName(valid_issuers[i], cert_issuer) == SECEqual)
-        return true;
-    }
-  }
-  return false;
-}
-
-std::string GetUniqueNicknameForSlot(const std::string& nickname,
-                                     const SECItem* subject,
-                                     PK11SlotInfo* slot) {
-  int index = 2;
-  std::string new_name = nickname;
-  std::string temp_nickname = new_name;
-  std::string token_name;
-
-  if (!slot)
-    return new_name;
-
-  if (!PK11_IsInternalKeySlot(slot)) {
-    token_name.assign(PK11_GetTokenName(slot));
-    token_name.append(":");
-
-    temp_nickname = token_name + new_name;
-  }
-
-  while (SEC_CertNicknameConflict(temp_nickname.c_str(),
-                                  const_cast<SECItem*>(subject),
-                                  CERT_GetDefaultCertDB())) {
-    base::SStringPrintf(&new_name, "%s #%d", nickname.c_str(), index++);
-    temp_nickname = token_name + new_name;
-  }
-
-  return new_name;
-}
-
-}  // namespace x509_util
-
-}  // namespace net
diff --git a/net/cert/x509_util_unittest.cc b/net/cert/x509_util_unittest.cc
index 665fe15..2da48d80 100644
--- a/net/cert/x509_util_unittest.cc
+++ b/net/cert/x509_util_unittest.cc
@@ -188,7 +188,6 @@
   EXPECT_FALSE(cert->HasExpired());
 }
 
-#if defined(USE_OPENSSL)
 // This is a test case based on
 // http://blogs.msdn.com/b/openspecification/archive/2013/03/26/ntlm-and-channel-binding-hash-aka-exteneded-protection-for-authentication.aspx
 // There doesn't seem to be too many public test vectors for channel bindings.
@@ -698,7 +697,6 @@
       x509_util::GetTLSServerEndPointChannelBinding(*cert, &channel_bindings));
   EXPECT_TRUE(channel_bindings.empty());
 }
-#endif
 
 }  // namespace x509_util
 
diff --git a/net/http/des.cc b/net/http/des.cc
index 4fce9ccd..4f05022 100644
--- a/net/http/des.cc
+++ b/net/http/des.cc
@@ -4,16 +4,10 @@
 
 #include "net/http/des.h"
 
-#include "base/logging.h"
-
-#if defined(USE_OPENSSL)
 #include <openssl/des.h>
+
+#include "base/logging.h"
 #include "crypto/openssl_util.h"
-#elif defined(OS_IOS)
-#include <CommonCrypto/CommonCryptor.h>
-#else
-#error "Unknown platform"
-#endif
 
 // The iOS version of DESEncrypt is our own code.
 // DESSetKeyParity and DESMakeKey are based on
@@ -80,8 +74,6 @@
   key[7] = DESSetKeyParity((raw[6] << 1));
 }
 
-#if defined(USE_OPENSSL)
-
 void DESEncrypt(const uint8_t* key, const uint8_t* src, uint8_t* hash) {
   crypto::EnsureOpenSSLInit();
 
@@ -93,17 +85,4 @@
                   reinterpret_cast<DES_cblock*>(hash), &ks, DES_ENCRYPT);
 }
 
-#elif defined(OS_IOS)
-
-void DESEncrypt(const uint8_t* key, const uint8_t* src, uint8_t* hash) {
-  CCCryptorStatus status;
-  size_t data_out_moved = 0;
-  status = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionECBMode,
-                   key, 8, NULL, src, 8, hash, 8, &data_out_moved);
-  DCHECK(status == kCCSuccess);
-  DCHECK(data_out_moved == 8);
-}
-
-#endif
-
 }  // namespace net
diff --git a/net/http/http_stream_factory_impl.cc b/net/http/http_stream_factory_impl.cc
index d160c31..ee64179c 100644
--- a/net/http/http_stream_factory_impl.cc
+++ b/net/http/http_stream_factory_impl.cc
@@ -263,8 +263,8 @@
     std::string origin_host =
         ApplyHostMappingRules(request_info.url, &destination).host();
     QuicServerId server_id(destination, request_info.privacy_mode);
-    if (session_->quic_stream_factory()->CanUseExistingSession(
-            server_id, request_info.privacy_mode, origin_host))
+    if (session_->quic_stream_factory()->CanUseExistingSession(server_id,
+                                                               origin_host))
       return alternative_service;
 
     // Cache this entry if we don't have a non-broken Alt-Svc yet.
diff --git a/net/http/transport_security_state_unittest.cc b/net/http/transport_security_state_unittest.cc
index 3eac0303..2140209 100644
--- a/net/http/transport_security_state_unittest.cc
+++ b/net/http/transport_security_state_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/strings/string_piece.h"
 #include "base/test/histogram_tester.h"
 #include "base/values.h"
+#include "crypto/openssl_util.h"
 #include "crypto/sha2.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/net_errors.h"
@@ -34,12 +35,6 @@
 #include "net/test/cert_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(USE_OPENSSL)
-#include "crypto/openssl_util.h"
-#else
-#include "crypto/nss_util.h"
-#endif
-
 namespace net {
 
 namespace {
@@ -236,11 +231,7 @@
 class TransportSecurityStateTest : public testing::Test {
  public:
   void SetUp() override {
-#if defined(USE_OPENSSL)
     crypto::EnsureOpenSSLInit();
-#else
-    crypto::EnsureNSSInit();
-#endif
   }
 
   static void DisableStaticPins(TransportSecurityState* state) {
diff --git a/net/net.gyp b/net/net.gyp
index e59ce18..7a4ef6b 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -170,6 +170,7 @@
         '../crypto/crypto.gyp:crypto_test_support',
         '../testing/gmock.gyp:gmock',
         '../testing/gtest.gyp:gtest',
+        '../third_party/boringssl/boringssl.gyp:boringssl',
         '../third_party/zlib/zlib.gyp:zlib',
         '../url/url.gyp:url_url_features',
         '../url/url.gyp:url_lib',
@@ -223,13 +224,7 @@
             'ssl/client_cert_store_nss_unittest.cc',
           ],
         }],
-        [ 'use_openssl == 1', {
-          # Avoid compiling/linking with the system library.
-          'dependencies': [
-            '../third_party/boringssl/boringssl.gyp:boringssl',
-          ],
-        }],
-        [ 'use_nss_verifier == 1', {
+        [ 'use_nss_certs == 1', {
           'conditions': [
             [ 'desktop_linux == 1 or chromeos == 1', {
               'dependencies': [
@@ -263,13 +258,13 @@
             'http/http_auth_handler_negotiate_unittest.cc',
           ],
         }],
-        [ 'use_nss_verifier == 0', {
+        [ 'use_nss_certs == 0', {
           # Only include this test when using NSS for cert verification.
           'sources!': [
             'cert_net/nss_ocsp_unittest.cc',
           ],
         }],
-        [ 'use_nss_verifier == 0 and OS == "ios"', {
+        [ 'OS == "ios"', {
           # Only include these files on iOS when using NSS for cert 
           # verification.
           'sources!': [
@@ -277,24 +272,6 @@
            'cert/x509_util_ios.h',
           ],
         }],
-        [ 'use_nss_verifier == 1 and OS == "ios"', {
-          'sources!': [
-            'cert/cert_verify_proc_ios.cc',
-            'cert/cert_verify_proc_ios.h',
-            'cert/x509_certificate_openssl_ios.cc',
-          ],
-        }],
-        [ 'use_openssl==1', {
-            'sources!': [
-              'quic/test_tools/crypto_test_utils_nss.cc',
-            ],
-          }, {  # else !use_openssl: remove the unneeded files and pull in NSS.
-            'sources!': [
-              'quic/test_tools/crypto_test_utils_openssl.cc',
-              'ssl/ssl_client_session_cache_openssl_unittest.cc',
-            ],
-          },
-        ],
         [ 'use_openssl_certs == 0', {
             'sources!': [
               'ssl/openssl_client_key_store_unittest.cc',
@@ -692,7 +669,7 @@
             'test/spawned_test_server/spawned_test_server.h',
           ],
         }],
-        ['use_nss_verifier == 1', {
+        ['use_nss_certs == 1', {
           'conditions': [
             [ 'desktop_linux == 1 or chromeos == 1', {
               'dependencies': [
diff --git a/net/net.gypi b/net/net.gypi
index 003e7d56f..80df25b 100644
--- a/net/net.gypi
+++ b/net/net.gypi
@@ -519,8 +519,6 @@
       'base/network_interfaces_win.cc',
       'base/network_quality_estimator.cc',
       'base/network_quality_estimator.h',
-      'base/nss_memio.c',
-      'base/nss_memio.h',
       'base/platform_mime_util.h',
       'base/platform_mime_util_linux.cc',
       'base/platform_mime_util_mac.mm',
@@ -588,12 +586,10 @@
       'cert/ct_log_response_parser.h',
       'cert/ct_log_verifier.cc',
       'cert/ct_log_verifier.h',
-      'cert/ct_log_verifier_nss.cc',
       'cert/ct_log_verifier_openssl.cc',
       'cert/ct_log_verifier_util.cc',
       'cert/ct_log_verifier_util.h',
       'cert/ct_objects_extractor.h',
-      'cert/ct_objects_extractor_nss.cc',
       'cert/ct_objects_extractor_openssl.cc',
       'cert/ct_serialization.cc',
       'cert/ct_serialization.h',
@@ -602,7 +598,6 @@
       'cert/ev_root_ca_metadata.cc',
       'cert/ev_root_ca_metadata.h',
       'cert/jwk_serializer.h',
-      'cert/jwk_serializer_nss.cc',
       'cert/jwk_serializer_openssl.cc',
       'cert/merkle_consistency_proof.cc',
       'cert/merkle_consistency_proof.h',
@@ -616,7 +611,6 @@
       'cert/nss_cert_database_chromeos.h',
       'cert/nss_profile_filter_chromeos.cc',
       'cert/nss_profile_filter_chromeos.h',
-      'cert/scoped_nss_types.h',
       'cert/sct_status_flags.h',
       'cert/test_root_certs.cc',
       'cert/test_root_certs.h',
@@ -630,17 +624,13 @@
       'cert/x509_certificate_ios.cc',
       'cert/x509_certificate_mac.cc',
       'cert/x509_certificate_nss.cc',
-      'cert/x509_certificate_openssl_ios.cc',
       'cert/x509_certificate_win.cc',
       'cert/x509_util_android.cc',
       'cert/x509_util_android.h',
-      'cert/x509_util_ios.cc',
-      'cert/x509_util_ios.h',
       'cert/x509_util_mac.cc',
       'cert/x509_util_mac.h',
-      'cert/x509_util_nss.cc',
       'cert/x509_util_nss.h',
-      'cert/x509_util_nss_certs.cc',
+      'cert/x509_util_nss.cc',
       'cert_net/cert_net_fetcher_impl.cc',
       'cert_net/cert_net_fetcher_impl.h',
       'cookies/canonical_cookie.cc',
@@ -1003,18 +993,9 @@
       'proxy/proxy_service.h',
       'quic/bidirectional_stream_quic_impl.cc',
       'quic/bidirectional_stream_quic_impl.h',
-      'quic/crypto/aead_base_decrypter_nss.cc',
-      'quic/crypto/aead_base_encrypter_nss.cc',
-      'quic/crypto/aes_128_gcm_12_decrypter_nss.cc',
-      'quic/crypto/aes_128_gcm_12_encrypter_nss.cc',
       'quic/crypto/cert_compressor.cc',
       'quic/crypto/cert_compressor.h',
-      'quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc',
-      'quic/crypto/chacha20_poly1305_rfc7539_encrypter_nss.cc',
-      'quic/crypto/channel_id_nss.cc',
-      'quic/crypto/p256_key_exchange_nss.cc',
       'quic/crypto/proof_source_chromium.h',
-      'quic/crypto/proof_source_chromium_nss.cc',
       'quic/crypto/proof_source_chromium_openssl.cc',
       'quic/crypto/quic_compressed_certs_cache.cc',
       'quic/crypto/quic_compressed_certs_cache.h',
@@ -1068,8 +1049,6 @@
       'socket/client_socket_pool_manager.h',
       'socket/client_socket_pool_manager_impl.cc',
       'socket/client_socket_pool_manager_impl.h',
-      'socket/nss_ssl_util.cc',
-      'socket/nss_ssl_util.h',
       'socket/server_socket.cc',
       'socket/server_socket.h',
       'socket/socket_descriptor.cc',
@@ -1084,13 +1063,9 @@
       'socket/socks_client_socket.h',
       'socket/socks_client_socket_pool.cc',
       'socket/socks_client_socket_pool.h',
-      'socket/ssl_client_socket_nss.cc',
-      'socket/ssl_client_socket_nss.h',
       'socket/ssl_client_socket_pool.cc',
       'socket/ssl_client_socket_pool.h',
       'socket/ssl_server_socket.h',
-      'socket/ssl_server_socket_nss.cc',
-      'socket/ssl_server_socket_nss.h',
       'socket/ssl_server_socket_openssl.cc',
       'socket/ssl_server_socket_openssl.h',
       'socket/stream_socket.cc',
@@ -1213,7 +1188,6 @@
       'ssl/test_ssl_private_key.h',
       'ssl/threaded_ssl_private_key.cc',
       'ssl/threaded_ssl_private_key.h',
-      'ssl/token_binding_nss.cc',
       'third_party/mozilla_security_manager/nsKeygenHandler.cpp',
       'third_party/mozilla_security_manager/nsKeygenHandler.h',
       'third_party/mozilla_security_manager/nsNSSCertificateDB.cpp',
@@ -1665,7 +1639,6 @@
       'quic/test_tools/crypto_test_utils.cc',
       'quic/test_tools/crypto_test_utils.h',
       'quic/test_tools/crypto_test_utils_chromium.cc',
-      'quic/test_tools/crypto_test_utils_nss.cc',
       'quic/test_tools/crypto_test_utils_openssl.cc',
       'quic/test_tools/delayed_verify_strike_register_client.cc',
       'quic/test_tools/delayed_verify_strike_register_client.h',
diff --git a/net/net_common.gypi b/net/net_common.gypi
index bc67032..54bd346 100644
--- a/net/net_common.gypi
+++ b/net/net_common.gypi
@@ -11,6 +11,7 @@
     '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
     '../crypto/crypto.gyp:crypto',
     '../sdch/sdch.gyp:sdch',
+    '../third_party/boringssl/boringssl.gyp:boringssl',
     '../third_party/protobuf/protobuf.gyp:protobuf_lite',
     '../third_party/zlib/zlib.gyp:zlib',
     '../url/url.gyp:url_url_features',
@@ -106,110 +107,24 @@
         'dns/dns_client.cc',
       ],
     }],
-    ['use_openssl==1', {
-        'sources!': [
-          'base/nss_memio.c',
-          'base/nss_memio.h',
-          'cert/ct_log_verifier_nss.cc',
-          'cert/ct_objects_extractor_nss.cc',
-          'cert/jwk_serializer_nss.cc',
-          'cert/scoped_nss_types.h',
-          'cert/x509_certificate_ios.cc',
-          'cert/x509_util_nss.cc',
-          'quic/crypto/aead_base_decrypter_nss.cc',
-          'quic/crypto/aead_base_encrypter_nss.cc',
-          'quic/crypto/aes_128_gcm_12_decrypter_nss.cc',
-          'quic/crypto/aes_128_gcm_12_encrypter_nss.cc',
-          'quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc',
-          'quic/crypto/chacha20_poly1305_rfc7539_encrypter_nss.cc',
-          'quic/crypto/channel_id_nss.cc',
-          'quic/crypto/p256_key_exchange_nss.cc',
-          'quic/crypto/proof_source_chromium_nss.cc',
-          'socket/nss_ssl_util.cc',
-          'socket/nss_ssl_util.h',
-          'socket/ssl_client_socket_nss.cc',
-          'socket/ssl_client_socket_nss.h',
-          'socket/ssl_server_socket_nss.cc',
-          'socket/ssl_server_socket_nss.h',
-          'ssl/token_binding_nss.cc',
-        ],
+    [ 'use_nss_certs == 1', {
         'dependencies': [
-          '../third_party/boringssl/boringssl.gyp:boringssl',
-        ],
-        'conditions': [
-          ['chromecast==1 and use_nss_certs==1', {
-            'sources': [
-              'ssl/ssl_platform_key_chromecast.cc',
-            ],
-            'sources!': [
-              'ssl/ssl_platform_key_nss.cc',
-            ],
-          }],
-        ],
-      },
-      {  # else !use_openssl: remove the unneeded files and depend on NSS.
-        'sources!': [
-          'cert/ct_log_verifier_openssl.cc',
-          'cert/ct_objects_extractor_openssl.cc',
-          'cert/jwk_serializer_openssl.cc',
-          'cert/x509_util_openssl.cc',
-          'cert/x509_util_openssl.h',
-          'quic/crypto/aead_base_decrypter_openssl.cc',
-          'quic/crypto/aead_base_encrypter_openssl.cc',
-          'quic/crypto/aes_128_gcm_12_decrypter_openssl.cc',
-          'quic/crypto/aes_128_gcm_12_encrypter_openssl.cc',
-          'quic/crypto/chacha20_poly1305_rfc7539_decrypter_openssl.cc',
-          'quic/crypto/chacha20_poly1305_rfc7539_encrypter_openssl.cc',
-          'quic/crypto/channel_id_openssl.cc',
-          'quic/crypto/p256_key_exchange_openssl.cc',
-          'quic/crypto/proof_source_chromium_openssl.cc',
-          'quic/crypto/scoped_evp_aead_ctx.cc',
-          'quic/crypto/scoped_evp_aead_ctx.h',
-          'socket/ssl_client_socket_openssl.cc',
-          'socket/ssl_client_socket_openssl.h',
-          'socket/ssl_server_socket_openssl.cc',
-          'socket/ssl_server_socket_openssl.h',
-          'ssl/client_key_store.cc',
-          'ssl/client_key_store.h',
-          'ssl/openssl_ssl_util.cc',
-          'ssl/openssl_ssl_util.h',
-          'ssl/ssl_client_session_cache_openssl.cc',
-          'ssl/ssl_client_session_cache_openssl.h',
-          'ssl/ssl_key_logger.cc',
-          'ssl/ssl_key_logger.h',
-          'ssl/ssl_platform_key.h',
-          'ssl/ssl_platform_key_nss.cc',
-          'ssl/ssl_platform_key_task_runner.cc',
-          'ssl/ssl_platform_key_task_runner.h',
-          'ssl/test_ssl_private_key.cc',
-          'ssl/test_ssl_private_key.h',
-          'ssl/threaded_ssl_private_key.cc',
-          'ssl/threaded_ssl_private_key.h',
-          'ssl/token_binding_openssl.cc',
-        ],
-      },
-    ],
-    [ 'use_nss_verifier == 1', {
-        'conditions': [
-          # Pull in the bundled or system NSS as appropriate.
-          [ 'desktop_linux == 1 or chromeos == 1', {
-            'dependencies': [
-              '../build/linux/system.gyp:ssl',
-            ],
-          }, {
-            'dependencies': [
-              '../third_party/nss/nss.gyp:nspr',
-              '../third_party/nss/nss.gyp:nss',
-              'third_party/nss/ssl.gyp:libssl',
-            ],
-          }]
+          '../build/linux/system.gyp:ssl',
         ],
       }, {
         'sources!': [
           'cert/x509_util_nss.h',
-        ],
-      },
+        ]
+      }
     ],
+    ['chromecast==1 and use_nss_certs==1', {
+      'sources': [
+        'ssl/ssl_platform_key_chromecast.cc',
+      ],
+      'sources!': [
+        'ssl/ssl_platform_key_nss.cc',
+      ],
+    }],
     [ 'use_openssl_certs == 0', {
         'sources!': [
           'base/crypto_module_openssl.cc',
@@ -260,13 +175,19 @@
           'base/crypto_module_nss.cc',
           'base/keygen_handler_nss.cc',
           'cert/cert_database_nss.cc',
+          'cert/cert_verify_proc_nss.cc',
+          'cert/cert_verify_proc_nss.h',
           'cert/nss_cert_database.cc',
           'cert/nss_cert_database.h',
           'cert/nss_cert_database_chromeos.cc',
           'cert/nss_cert_database_chromeos.h',
           'cert/nss_profile_filter_chromeos.cc',
           'cert/nss_profile_filter_chromeos.h',
+          'cert/test_root_certs_nss.cc',
           'cert/x509_certificate_nss.cc',
+          'cert/x509_util_nss.cc',
+          'cert_net/nss_ocsp.cc',
+          'cert_net/nss_ocsp.h',
           'ssl/client_cert_store_nss.cc',
           'ssl/client_cert_store_nss.h',
           'ssl/client_key_store.cc',
@@ -281,38 +202,14 @@
         ],
       },
     ],
-    [ 'use_nss_verifier != 1', {
-        'sources!': [
-          'cert/cert_verify_proc_nss.cc',
-          'cert/cert_verify_proc_nss.h',
-          'cert/test_root_certs_nss.cc',
-          'cert/x509_util_nss_certs.cc',
-          'cert_net/nss_ocsp.cc',
-          'cert_net/nss_ocsp.h',
-        ],
-      },
-    ],
     # client_cert_store_nss.c requires NSS_CmpCertChainWCANames from NSS's
     # libssl, but our bundled copy is not built in OpenSSL ports. Pull that
     # file in directly.
-    [ 'use_nss_certs == 1 and use_openssl == 1', {
+    [ 'use_nss_certs == 1', {
         'sources': [
           'third_party/nss/ssl/cmpcert.c',
         ],
     }],
-    [ 'OS == "ios" and use_nss_verifier == 0', {
-        'sources!': [
-          'cert/x509_util_ios.cc',
-          'cert/x509_util_ios.h',
-        ],
-    }],
-    [ 'OS == "ios" and use_nss_verifier == 1', {
-        'sources!': [
-          'cert/cert_verify_proc_ios.cc',
-          'cert/cert_verify_proc_ios.h',
-          'cert/x509_certificate_openssl_ios.cc',
-        ],
-    }],
     [ 'enable_websockets == 1', {
         'sources': ['<@(net_websockets_sources)']
     }],
@@ -458,7 +355,7 @@
         ['include', '^proxy/proxy_server_mac\\.cc$'],
       ],
     }],
-    ['OS == "ios" and <(use_nss_verifier) == 0', {
+    ['OS == "ios"', {
       'sources/': [
         ['include', '^cert/test_root_certs_mac\\.cc$'],
       ],
diff --git a/net/quic/crypto/aead_base_decrypter.h b/net/quic/crypto/aead_base_decrypter.h
index c76f11f..715961a 100644
--- a/net/quic/crypto/aead_base_decrypter.h
+++ b/net/quic/crypto/aead_base_decrypter.h
@@ -10,29 +10,17 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "net/quic/crypto/quic_decrypter.h"
-
-#if defined(USE_OPENSSL)
 #include "net/quic/crypto/scoped_evp_aead_ctx.h"
-#else
-#include <pkcs11t.h>
-#endif
 
 namespace net {
 
 // AeadBaseDecrypter is the base class of AEAD QuicDecrypter subclasses.
 class NET_EXPORT_PRIVATE AeadBaseDecrypter : public QuicDecrypter {
  public:
-#if defined(USE_OPENSSL)
   AeadBaseDecrypter(const EVP_AEAD* aead_alg,
                     size_t key_size,
                     size_t auth_tag_size,
                     size_t nonce_prefix_size);
-#else
-  AeadBaseDecrypter(CK_MECHANISM_TYPE aead_mechanism,
-                    size_t key_size,
-                    size_t auth_tag_size,
-                    size_t nonce_prefix_size);
-#endif
   ~AeadBaseDecrypter() override;
 
   // QuicDecrypter implementation
@@ -55,27 +43,8 @@
   static const size_t kMaxKeySize = 32;
   static const size_t kMaxNoncePrefixSize = 4;
 
-#if !defined(USE_OPENSSL)
-  struct AeadParams {
-    unsigned int len;
-    union {
-      CK_GCM_PARAMS gcm_params;
-      CK_NSS_AEAD_PARAMS nss_aead_params;
-    } data;
-  };
-
-  virtual void FillAeadParams(base::StringPiece nonce,
-                              base::StringPiece associated_data,
-                              size_t auth_tag_size,
-                              AeadParams* aead_params) const = 0;
-#endif  // !defined(USE_OPENSSL)
-
  private:
-#if defined(USE_OPENSSL)
   const EVP_AEAD* const aead_alg_;
-#else
-  const CK_MECHANISM_TYPE aead_mechanism_;
-#endif
   const size_t key_size_;
   const size_t auth_tag_size_;
   const size_t nonce_prefix_size_;
@@ -85,9 +54,7 @@
   // The nonce prefix.
   unsigned char nonce_prefix_[kMaxNoncePrefixSize];
 
-#if defined(USE_OPENSSL)
   ScopedEVPAEADCtx ctx_;
-#endif
 
   DISALLOW_COPY_AND_ASSIGN(AeadBaseDecrypter);
 };
diff --git a/net/quic/crypto/aead_base_decrypter_nss.cc b/net/quic/crypto/aead_base_decrypter_nss.cc
deleted file mode 100644
index 30865e4..0000000
--- a/net/quic/crypto/aead_base_decrypter_nss.cc
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <pk11pub.h>
-
-#include <memory>
-
-#include "crypto/scoped_nss_types.h"
-#include "net/quic/crypto/aead_base_decrypter.h"
-#include "net/quic/quic_flags.h"
-#include "net/quic/quic_utils.h"
-
-using base::StringPiece;
-
-namespace net {
-
-AeadBaseDecrypter::AeadBaseDecrypter(CK_MECHANISM_TYPE aead_mechanism,
-                                     size_t key_size,
-                                     size_t auth_tag_size,
-                                     size_t nonce_prefix_size)
-    : aead_mechanism_(aead_mechanism),
-      key_size_(key_size),
-      auth_tag_size_(auth_tag_size),
-      nonce_prefix_size_(nonce_prefix_size) {
-  DCHECK_LE(key_size_, sizeof(key_));
-  DCHECK_LE(nonce_prefix_size_, sizeof(nonce_prefix_));
-}
-
-AeadBaseDecrypter::~AeadBaseDecrypter() {}
-
-bool AeadBaseDecrypter::SetKey(StringPiece key) {
-  DCHECK_EQ(key.size(), key_size_);
-  if (key.size() != key_size_) {
-    return false;
-  }
-  memcpy(key_, key.data(), key.size());
-  return true;
-}
-
-bool AeadBaseDecrypter::SetNoncePrefix(StringPiece nonce_prefix) {
-  DCHECK_EQ(nonce_prefix.size(), nonce_prefix_size_);
-  if (nonce_prefix.size() != nonce_prefix_size_) {
-    return false;
-  }
-  memcpy(nonce_prefix_, nonce_prefix.data(), nonce_prefix.size());
-  return true;
-}
-
-bool AeadBaseDecrypter::DecryptPacket(QuicPathId path_id,
-                                      QuicPacketNumber packet_number,
-                                      StringPiece associated_data,
-                                      StringPiece ciphertext,
-                                      char* output,
-                                      size_t* output_length,
-                                      size_t max_output_length) {
-  if (ciphertext.length() < auth_tag_size_) {
-    return false;
-  }
-
-  uint8_t nonce[sizeof(nonce_prefix_) + sizeof(packet_number)];
-  const size_t nonce_size = nonce_prefix_size_ + sizeof(packet_number);
-  DCHECK_LE(nonce_size, sizeof(nonce));
-  memcpy(nonce, nonce_prefix_, nonce_prefix_size_);
-  uint64_t path_id_packet_number =
-      QuicUtils::PackPathIdAndPacketNumber(path_id, packet_number);
-  memcpy(nonce + nonce_prefix_size_, &path_id_packet_number,
-         sizeof(path_id_packet_number));
-
-  // NSS 3.14.x incorrectly requires an output buffer at least as long as
-  // the ciphertext (NSS bug
-  // https://bugzilla.mozilla.org/show_bug.cgi?id= 853674). Fortunately
-  // QuicDecrypter::Decrypt() specifies that |output| must be as long as
-  // |ciphertext| on entry.
-  size_t plaintext_size = ciphertext.length() - auth_tag_size_;
-
-  // Import key_ into NSS.
-  SECItem key_item;
-  key_item.type = siBuffer;
-  key_item.data = key_;
-  key_item.len = key_size_;
-  PK11SlotInfo* slot = PK11_GetInternalSlot();
-
-  // The exact value of the |origin| argument doesn't matter to NSS as long as
-  // it's not PK11_OriginFortezzaHack, so pass PK11_OriginUnwrap as a
-  // placeholder.
-  crypto::ScopedPK11SymKey aead_key(
-      PK11_ImportSymKey(slot, aead_mechanism_, PK11_OriginUnwrap, CKA_DECRYPT,
-                        &key_item, nullptr));
-  PK11_FreeSlot(slot);
-  slot = nullptr;
-  if (!aead_key) {
-    DVLOG(1) << "PK11_ImportSymKey failed";
-    return false;
-  }
-
-  AeadParams aead_params = {0};
-  FillAeadParams(StringPiece(reinterpret_cast<char*>(nonce), nonce_size),
-                 associated_data, auth_tag_size_, &aead_params);
-
-  SECItem param;
-  param.type = siBuffer;
-  param.data = reinterpret_cast<unsigned char*>(&aead_params.data);
-  param.len = aead_params.len;
-
-  unsigned int output_len;
-  if (PK11_Decrypt(aead_key.get(), aead_mechanism_, &param,
-                   reinterpret_cast<uint8_t*>(output), &output_len,
-                   max_output_length,
-                   reinterpret_cast<const unsigned char*>(ciphertext.data()),
-                   ciphertext.length()) != SECSuccess) {
-    return false;
-  }
-
-  if (output_len != plaintext_size) {
-    DVLOG(1) << "Wrong output length";
-    return false;
-  }
-  *output_length = output_len;
-  return true;
-}
-
-StringPiece AeadBaseDecrypter::GetKey() const {
-  return StringPiece(reinterpret_cast<const char*>(key_), key_size_);
-}
-
-StringPiece AeadBaseDecrypter::GetNoncePrefix() const {
-  if (nonce_prefix_size_ == 0) {
-    return StringPiece();
-  }
-  return StringPiece(reinterpret_cast<const char*>(nonce_prefix_),
-                     nonce_prefix_size_);
-}
-
-}  // namespace net
diff --git a/net/quic/crypto/aead_base_encrypter.h b/net/quic/crypto/aead_base_encrypter.h
index 3330189..05d996f 100644
--- a/net/quic/crypto/aead_base_encrypter.h
+++ b/net/quic/crypto/aead_base_encrypter.h
@@ -10,29 +10,17 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "net/quic/crypto/quic_encrypter.h"
-
-#if defined(USE_OPENSSL)
 #include "net/quic/crypto/scoped_evp_aead_ctx.h"
-#else
-#include <pkcs11t.h>
-#endif
 
 namespace net {
 
 // AeadBaseEncrypter is the base class of AEAD QuicEncrypter subclasses.
 class NET_EXPORT_PRIVATE AeadBaseEncrypter : public QuicEncrypter {
  public:
-#if defined(USE_OPENSSL)
   AeadBaseEncrypter(const EVP_AEAD* aead_alg,
                     size_t key_size,
                     size_t auth_tag_size,
                     size_t nonce_prefix_size);
-#else
-  AeadBaseEncrypter(CK_MECHANISM_TYPE aead_mechanism,
-                    size_t key_size,
-                    size_t auth_tag_size,
-                    size_t nonce_prefix_size);
-#endif
   ~AeadBaseEncrypter() override;
 
   // QuicEncrypter implementation
@@ -66,27 +54,8 @@
   static const size_t kMaxKeySize = 32;
   static const size_t kMaxNoncePrefixSize = 4;
 
-#if !defined(USE_OPENSSL)
-  struct AeadParams {
-    unsigned int len;
-    union {
-      CK_GCM_PARAMS gcm_params;
-      CK_NSS_AEAD_PARAMS nss_aead_params;
-    } data;
-  };
-
-  virtual void FillAeadParams(base::StringPiece nonce,
-                              base::StringPiece associated_data,
-                              size_t auth_tag_size,
-                              AeadParams* aead_params) const = 0;
-#endif
-
  private:
-#if defined(USE_OPENSSL)
   const EVP_AEAD* const aead_alg_;
-#else
-  const CK_MECHANISM_TYPE aead_mechanism_;
-#endif
   const size_t key_size_;
   const size_t auth_tag_size_;
   const size_t nonce_prefix_size_;
@@ -96,9 +65,7 @@
   // The nonce prefix.
   unsigned char nonce_prefix_[kMaxNoncePrefixSize];
 
-#if defined(USE_OPENSSL)
   ScopedEVPAEADCtx ctx_;
-#endif
 
   DISALLOW_COPY_AND_ASSIGN(AeadBaseEncrypter);
 };
diff --git a/net/quic/crypto/aead_base_encrypter_nss.cc b/net/quic/crypto/aead_base_encrypter_nss.cc
deleted file mode 100644
index cfb6e79e..0000000
--- a/net/quic/crypto/aead_base_encrypter_nss.cc
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <pk11pub.h>
-
-#include <memory>
-
-#include "crypto/scoped_nss_types.h"
-#include "net/quic/crypto/aead_base_encrypter.h"
-#include "net/quic/quic_flags.h"
-#include "net/quic/quic_utils.h"
-
-using base::StringPiece;
-
-namespace net {
-
-namespace {
-
-// The maximum size in bytes of the nonce, including 8 bytes of sequence number.
-// ChaCha20 uses only the 8 byte sequence number and AES-GCM uses 12 bytes.
-const size_t kMaxNonceSize = 12;
-
-}  // namespace
-
-AeadBaseEncrypter::AeadBaseEncrypter(CK_MECHANISM_TYPE aead_mechanism,
-                                     size_t key_size,
-                                     size_t auth_tag_size,
-                                     size_t nonce_prefix_size)
-    : aead_mechanism_(aead_mechanism),
-      key_size_(key_size),
-      auth_tag_size_(auth_tag_size),
-      nonce_prefix_size_(nonce_prefix_size) {
-  DCHECK_LE(key_size_, sizeof(key_));
-  DCHECK_LE(nonce_prefix_size_, sizeof(nonce_prefix_));
-  DCHECK_GE(kMaxNonceSize, nonce_prefix_size_);
-}
-
-AeadBaseEncrypter::~AeadBaseEncrypter() {}
-
-bool AeadBaseEncrypter::SetKey(StringPiece key) {
-  DCHECK_EQ(key.size(), key_size_);
-  if (key.size() != key_size_) {
-    return false;
-  }
-  memcpy(key_, key.data(), key.size());
-  return true;
-}
-
-bool AeadBaseEncrypter::SetNoncePrefix(StringPiece nonce_prefix) {
-  DCHECK_EQ(nonce_prefix.size(), nonce_prefix_size_);
-  if (nonce_prefix.size() != nonce_prefix_size_) {
-    return false;
-  }
-  memcpy(nonce_prefix_, nonce_prefix.data(), nonce_prefix.size());
-  return true;
-}
-
-bool AeadBaseEncrypter::Encrypt(StringPiece nonce,
-                                StringPiece associated_data,
-                                StringPiece plaintext,
-                                unsigned char* output) {
-  if (nonce.size() != nonce_prefix_size_ + sizeof(QuicPacketNumber)) {
-    return false;
-  }
-
-  size_t ciphertext_size = GetCiphertextSize(plaintext.length());
-
-  // Import key_ into NSS.
-  SECItem key_item;
-  key_item.type = siBuffer;
-  key_item.data = key_;
-  key_item.len = key_size_;
-  PK11SlotInfo* slot = PK11_GetInternalSlot();
-
-  // The exact value of the |origin| argument doesn't matter to NSS as long as
-  // it's not PK11_OriginFortezzaHack, so we pass PK11_OriginUnwrap as a
-  // placeholder.
-  crypto::ScopedPK11SymKey aead_key(
-      PK11_ImportSymKey(slot, aead_mechanism_, PK11_OriginUnwrap, CKA_ENCRYPT,
-                        &key_item, nullptr));
-  PK11_FreeSlot(slot);
-  slot = nullptr;
-  if (!aead_key) {
-    DVLOG(1) << "PK11_ImportSymKey failed";
-    return false;
-  }
-
-  AeadParams aead_params = {0};
-  FillAeadParams(nonce, associated_data, auth_tag_size_, &aead_params);
-
-  SECItem param;
-  param.type = siBuffer;
-  param.data = reinterpret_cast<unsigned char*>(&aead_params.data);
-  param.len = aead_params.len;
-
-  if (plaintext.size() > kMaxPacketSize) {
-    DLOG(FATAL) << "Plaintext too large";
-    return false;
-  }
-  // NSS doesn't support inplace encryption, so copy plaintext to a temporary
-  // buffer.
-  unsigned char temp_plaintext[kMaxPacketSize];
-  memcpy(temp_plaintext, plaintext.data(), plaintext.size());
-
-  unsigned int output_len;
-  if (PK11_Encrypt(aead_key.get(), aead_mechanism_, &param, output, &output_len,
-                   ciphertext_size, temp_plaintext,
-                   plaintext.size()) != SECSuccess) {
-    DVLOG(1) << "PK11_Encrypt failed";
-    return false;
-  }
-
-  if (output_len != ciphertext_size) {
-    DVLOG(1) << "Wrong output length";
-    return false;
-  }
-
-  return true;
-}
-
-bool AeadBaseEncrypter::EncryptPacket(QuicPathId path_id,
-                                      QuicPacketNumber packet_number,
-                                      StringPiece associated_data,
-                                      StringPiece plaintext,
-                                      char* output,
-                                      size_t* output_length,
-                                      size_t max_output_length) {
-  size_t ciphertext_size = GetCiphertextSize(plaintext.length());
-  if (max_output_length < ciphertext_size) {
-    return false;
-  }
-  // TODO(ianswett): Introduce a check to ensure that we don't encrypt with the
-  // same packet number twice.
-  const size_t nonce_size = nonce_prefix_size_ + sizeof(packet_number);
-  ALIGNAS(4) char nonce_buffer[kMaxNonceSize];
-  memcpy(nonce_buffer, nonce_prefix_, nonce_prefix_size_);
-  uint64_t path_id_packet_number =
-      QuicUtils::PackPathIdAndPacketNumber(path_id, packet_number);
-  memcpy(nonce_buffer + nonce_prefix_size_, &path_id_packet_number,
-         sizeof(path_id_packet_number));
-  if (!Encrypt(StringPiece(nonce_buffer, nonce_size), associated_data,
-               plaintext, reinterpret_cast<unsigned char*>(output))) {
-    return false;
-  }
-  *output_length = ciphertext_size;
-  return true;
-}
-
-size_t AeadBaseEncrypter::GetKeySize() const {
-  return key_size_;
-}
-
-size_t AeadBaseEncrypter::GetNoncePrefixSize() const {
-  return nonce_prefix_size_;
-}
-
-size_t AeadBaseEncrypter::GetMaxPlaintextSize(size_t ciphertext_size) const {
-  return ciphertext_size - auth_tag_size_;
-}
-
-size_t AeadBaseEncrypter::GetCiphertextSize(size_t plaintext_size) const {
-  return plaintext_size + auth_tag_size_;
-}
-
-StringPiece AeadBaseEncrypter::GetKey() const {
-  return StringPiece(reinterpret_cast<const char*>(key_), key_size_);
-}
-
-StringPiece AeadBaseEncrypter::GetNoncePrefix() const {
-  if (nonce_prefix_size_ == 0) {
-    return StringPiece();
-  }
-  return StringPiece(reinterpret_cast<const char*>(nonce_prefix_),
-                     nonce_prefix_size_);
-}
-
-}  // namespace net
diff --git a/net/quic/crypto/aes_128_gcm_12_decrypter.h b/net/quic/crypto/aes_128_gcm_12_decrypter.h
index f8b1196..5883c76f 100644
--- a/net/quic/crypto/aes_128_gcm_12_decrypter.h
+++ b/net/quic/crypto/aes_128_gcm_12_decrypter.h
@@ -29,15 +29,6 @@
   Aes128Gcm12Decrypter();
   ~Aes128Gcm12Decrypter() override;
 
-#if !defined(USE_OPENSSL)
- protected:
-  // AeadBaseDecrypter methods:
-  void FillAeadParams(base::StringPiece nonce,
-                      base::StringPiece associated_data,
-                      size_t auth_tag_size,
-                      AeadParams* aead_params) const override;
-#endif
-
   const char* cipher_name() const override;
   uint32_t cipher_id() const override;
 
diff --git a/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc b/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc
deleted file mode 100644
index d4480f4..0000000
--- a/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/crypto/aes_128_gcm_12_decrypter.h"
-
-#include <pk11pub.h>
-#include <secerr.h>
-
-using base::StringPiece;
-
-namespace net {
-
-namespace {
-
-const size_t kKeySize = 16;
-const size_t kNoncePrefixSize = 4;
-
-}  // namespace
-
-Aes128Gcm12Decrypter::Aes128Gcm12Decrypter()
-    : AeadBaseDecrypter(CKM_AES_GCM, kKeySize, kAuthTagSize, kNoncePrefixSize) {
-  static_assert(kKeySize <= kMaxKeySize, "key size too big");
-  static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
-                "nonce prefix size too big");
-}
-
-Aes128Gcm12Decrypter::~Aes128Gcm12Decrypter() {}
-
-void Aes128Gcm12Decrypter::FillAeadParams(StringPiece nonce,
-                                          StringPiece associated_data,
-                                          size_t auth_tag_size,
-                                          AeadParams* aead_params) const {
-  aead_params->len = sizeof(aead_params->data.gcm_params);
-  CK_GCM_PARAMS* gcm_params = &aead_params->data.gcm_params;
-  gcm_params->pIv = reinterpret_cast<CK_BYTE*>(const_cast<char*>(nonce.data()));
-  gcm_params->ulIvLen = nonce.size();
-  gcm_params->pAAD =
-      reinterpret_cast<CK_BYTE*>(const_cast<char*>(associated_data.data()));
-  gcm_params->ulAADLen = associated_data.size();
-  gcm_params->ulTagBits = auth_tag_size * 8;
-}
-
-const char* Aes128Gcm12Decrypter::cipher_name() const {
-  // TODO(rtenneti): Use TLS1_TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 instead
-  // of hard coded string.
-  // return TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
-  return "ECDHE-RSA-AES128-GCM-SHA256";
-}
-
-uint32_t Aes128Gcm12Decrypter::cipher_id() const {
-  // TODO(rtenneti): when Chromium requires NSS 3.15.2 or later, use
-  // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 instead of 0xC02F.
-  // Or'ed with 0x03000000 to match OpenSSL/BoringSSL implementations.
-  return 0x03000000 | 0xC02F;
-}
-
-}  // namespace net
diff --git a/net/quic/crypto/aes_128_gcm_12_encrypter.h b/net/quic/crypto/aes_128_gcm_12_encrypter.h
index f2f7b41..3af151e1 100644
--- a/net/quic/crypto/aes_128_gcm_12_encrypter.h
+++ b/net/quic/crypto/aes_128_gcm_12_encrypter.h
@@ -28,15 +28,6 @@
   Aes128Gcm12Encrypter();
   ~Aes128Gcm12Encrypter() override;
 
-#if !defined(USE_OPENSSL)
- protected:
-  // AeadBaseEncrypter methods:
-  void FillAeadParams(base::StringPiece nonce,
-                      base::StringPiece associated_data,
-                      size_t auth_tag_size,
-                      AeadParams* aead_params) const override;
-#endif
-
  private:
   DISALLOW_COPY_AND_ASSIGN(Aes128Gcm12Encrypter);
 };
diff --git a/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc b/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc
deleted file mode 100644
index 78c1d3dc..0000000
--- a/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
-
-#include <pk11pub.h>
-#include <secerr.h>
-
-using base::StringPiece;
-
-namespace net {
-
-namespace {
-
-const size_t kKeySize = 16;
-const size_t kNoncePrefixSize = 4;
-
-}  // namespace
-
-Aes128Gcm12Encrypter::Aes128Gcm12Encrypter()
-    : AeadBaseEncrypter(CKM_AES_GCM, kKeySize, kAuthTagSize, kNoncePrefixSize) {
-  static_assert(kKeySize <= kMaxKeySize, "key size too big");
-  static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
-                "nonce prefix size too big");
-}
-
-Aes128Gcm12Encrypter::~Aes128Gcm12Encrypter() {}
-
-void Aes128Gcm12Encrypter::FillAeadParams(StringPiece nonce,
-                                          StringPiece associated_data,
-                                          size_t auth_tag_size,
-                                          AeadParams* aead_params) const {
-  aead_params->len = sizeof(aead_params->data.gcm_params);
-  CK_GCM_PARAMS* gcm_params = &aead_params->data.gcm_params;
-  gcm_params->pIv = reinterpret_cast<CK_BYTE*>(const_cast<char*>(nonce.data()));
-  gcm_params->ulIvLen = nonce.size();
-  gcm_params->pAAD =
-      reinterpret_cast<CK_BYTE*>(const_cast<char*>(associated_data.data()));
-  gcm_params->ulAADLen = associated_data.size();
-  gcm_params->ulTagBits = auth_tag_size * 8;
-}
-
-}  // namespace net
diff --git a/net/quic/crypto/chacha20_poly1305_decrypter.h b/net/quic/crypto/chacha20_poly1305_decrypter.h
index 1e0fd05f..a75556e 100644
--- a/net/quic/crypto/chacha20_poly1305_decrypter.h
+++ b/net/quic/crypto/chacha20_poly1305_decrypter.h
@@ -30,15 +30,6 @@
   ChaCha20Poly1305Decrypter();
   ~ChaCha20Poly1305Decrypter() override;
 
-#if !defined(USE_OPENSSL)
- protected:
-  // AeadBaseDecrypter methods:
-  void FillAeadParams(base::StringPiece nonce,
-                      base::StringPiece associated_data,
-                      size_t auth_tag_size,
-                      AeadParams* aead_params) const override;
-#endif
-
   const char* cipher_name() const override;
   uint32_t cipher_id() const override;
 
diff --git a/net/quic/crypto/chacha20_poly1305_encrypter.h b/net/quic/crypto/chacha20_poly1305_encrypter.h
index dfdfffe..eb4afdde 100644
--- a/net/quic/crypto/chacha20_poly1305_encrypter.h
+++ b/net/quic/crypto/chacha20_poly1305_encrypter.h
@@ -29,15 +29,6 @@
   ChaCha20Poly1305Encrypter();
   ~ChaCha20Poly1305Encrypter() override;
 
-#if !defined(USE_OPENSSL)
- protected:
-  // AeadBaseEncrypter methods:
-  void FillAeadParams(base::StringPiece nonce,
-                      base::StringPiece associated_data,
-                      size_t auth_tag_size,
-                      AeadParams* aead_params) const override;
-#endif
-
  private:
   DISALLOW_COPY_AND_ASSIGN(ChaCha20Poly1305Encrypter);
 };
diff --git a/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h b/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h
index 57609d0..dc30bed0 100644
--- a/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h
+++ b/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h
@@ -38,15 +38,6 @@
   const char* cipher_name() const override;
   uint32_t cipher_id() const override;
 
-#if !defined(USE_OPENSSL)
- protected:
-  // AeadBaseDecrypter methods:
-  void FillAeadParams(base::StringPiece nonce,
-                      base::StringPiece associated_data,
-                      size_t auth_tag_size,
-                      AeadParams* aead_params) const override;
-#endif
-
  private:
   DISALLOW_COPY_AND_ASSIGN(ChaCha20Poly1305Rfc7539Decrypter);
 };
diff --git a/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc b/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc
deleted file mode 100644
index 799a2c5a..0000000
--- a/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h"
-
-#include <pk11pub.h>
-
-using base::StringPiece;
-
-namespace net {
-
-namespace {
-
-const size_t kKeySize = 32;
-const size_t kNoncePrefixSize = 4;
-
-}  // namespace
-
-ChaCha20Poly1305Rfc7539Decrypter::ChaCha20Poly1305Rfc7539Decrypter()
-    : AeadBaseDecrypter(CKM_NSS_CHACHA20_POLY1305,
-                        kKeySize,
-                        kAuthTagSize,
-                        kNoncePrefixSize) {
-  static_assert(kKeySize <= kMaxKeySize, "key size too big");
-  static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
-                "nonce prefix size too big");
-}
-
-ChaCha20Poly1305Rfc7539Decrypter::~ChaCha20Poly1305Rfc7539Decrypter() {}
-
-bool ChaCha20Poly1305Rfc7539Decrypter::IsSupported() {
-  return false;
-}
-
-const char* ChaCha20Poly1305Rfc7539Decrypter::cipher_name() const {
-  return "";
-}
-
-uint32_t ChaCha20Poly1305Rfc7539Decrypter::cipher_id() const {
-  return 0;
-}
-
-void ChaCha20Poly1305Rfc7539Decrypter::FillAeadParams(
-    base::StringPiece nonce,
-    base::StringPiece associated_data,
-    size_t auth_tag_size,
-    AeadParams* aead_params) const {}
-
-}  // namespace net
diff --git a/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter.h b/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter.h
index 7b6e0b4..36b1a62 100644
--- a/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter.h
+++ b/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter.h
@@ -33,15 +33,6 @@
   // variant of ChaCha20+Poly1305.
   static bool IsSupported();
 
-#if !defined(USE_OPENSSL)
- protected:
-  // AeadBaseEncrypter methods:
-  void FillAeadParams(base::StringPiece nonce,
-                      base::StringPiece associated_data,
-                      size_t auth_tag_size,
-                      AeadParams* aead_params) const override;
-#endif
-
  private:
   DISALLOW_COPY_AND_ASSIGN(ChaCha20Poly1305Rfc7539Encrypter);
 };
diff --git a/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_nss.cc b/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_nss.cc
deleted file mode 100644
index 34b404ef..0000000
--- a/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_nss.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/crypto/chacha20_poly1305_rfc7539_encrypter.h"
-
-#include <pk11pub.h>
-
-using base::StringPiece;
-
-namespace net {
-
-namespace {
-
-const size_t kKeySize = 32;
-const size_t kNoncePrefixSize = 4;
-
-}  // namespace
-
-ChaCha20Poly1305Rfc7539Encrypter::ChaCha20Poly1305Rfc7539Encrypter()
-    : AeadBaseEncrypter(CKM_NSS_CHACHA20_POLY1305,
-                        kKeySize,
-                        kAuthTagSize,
-                        kNoncePrefixSize) {
-  static_assert(kKeySize <= kMaxKeySize, "key size too big");
-  static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
-                "nonce prefix size too big");
-}
-
-ChaCha20Poly1305Rfc7539Encrypter::~ChaCha20Poly1305Rfc7539Encrypter() {}
-
-bool ChaCha20Poly1305Rfc7539Encrypter::IsSupported() {
-  return false;
-}
-
-void ChaCha20Poly1305Rfc7539Encrypter::FillAeadParams(
-    StringPiece nonce,
-    StringPiece associated_data,
-    size_t auth_tag_size,
-    AeadParams* aead_params) const {}
-
-}  // namespace net
diff --git a/net/quic/crypto/channel_id_nss.cc b/net/quic/crypto/channel_id_nss.cc
deleted file mode 100644
index 522b2f6..0000000
--- a/net/quic/crypto/channel_id_nss.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/crypto/channel_id.h"
-
-#include <keythi.h>
-#include <pk11pub.h>
-#include <sechash.h>
-
-using base::StringPiece;
-
-namespace net {
-
-// static
-bool ChannelIDVerifier::Verify(StringPiece key,
-                               StringPiece signed_data,
-                               StringPiece signature) {
-  return VerifyRaw(key, signed_data, signature, true);
-}
-
-// static
-bool ChannelIDVerifier::VerifyRaw(StringPiece key,
-                                  StringPiece signed_data,
-                                  StringPiece signature,
-                                  bool is_channel_id_signature) {
-  if (key.size() != 32 * 2 || signature.size() != 32 * 2) {
-    return false;
-  }
-
-  SECKEYPublicKey public_key;
-  memset(&public_key, 0, sizeof(public_key));
-
-  // DER encoding of the object identifier (OID) of the named curve P-256
-  // (1.2.840.10045.3.1.7). See RFC 6637 Section 11.
-  static const unsigned char p256_oid[] = {0x06, 0x08, 0x2a, 0x86, 0x48,
-                                           0xce, 0x3d, 0x03, 0x01, 0x07};
-  public_key.keyType = ecKey;
-  public_key.u.ec.DEREncodedParams.type = siBuffer;
-  public_key.u.ec.DEREncodedParams.data = const_cast<unsigned char*>(p256_oid);
-  public_key.u.ec.DEREncodedParams.len = sizeof(p256_oid);
-
-  unsigned char key_buf[65];
-  key_buf[0] = 0x04;
-  memcpy(&key_buf[1], key.data(), key.size());
-  public_key.u.ec.publicValue.type = siBuffer;
-  public_key.u.ec.publicValue.data = key_buf;
-  public_key.u.ec.publicValue.len = sizeof(key_buf);
-
-  SECItem signature_item = {siBuffer, reinterpret_cast<unsigned char*>(
-                                          const_cast<char*>(signature.data())),
-                            static_cast<unsigned int>(signature.size())};
-
-  unsigned char hash_buf[SHA256_LENGTH];
-  SECItem hash_item = {siBuffer, hash_buf, sizeof(hash_buf)};
-
-  HASHContext* sha256 = HASH_Create(HASH_AlgSHA256);
-  if (!sha256) {
-    return false;
-  }
-  HASH_Begin(sha256);
-  if (is_channel_id_signature) {
-    HASH_Update(sha256, reinterpret_cast<const unsigned char*>(kContextStr),
-                strlen(kContextStr) + 1);
-    HASH_Update(sha256,
-                reinterpret_cast<const unsigned char*>(kClientToServerStr),
-                strlen(kClientToServerStr) + 1);
-  }
-  HASH_Update(sha256,
-              reinterpret_cast<const unsigned char*>(signed_data.data()),
-              signed_data.size());
-  HASH_End(sha256, hash_buf, &hash_item.len, sizeof(hash_buf));
-  HASH_Destroy(sha256);
-
-  return PK11_Verify(&public_key, &signature_item, &hash_item, nullptr) ==
-         SECSuccess;
-}
-
-}  // namespace net
diff --git a/net/quic/crypto/p256_key_exchange.h b/net/quic/crypto/p256_key_exchange.h
index fcdc19dd..db3e404e 100644
--- a/net/quic/crypto/p256_key_exchange.h
+++ b/net/quic/crypto/p256_key_exchange.h
@@ -12,16 +12,11 @@
 
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
+#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
 #include "net/base/net_export.h"
 #include "net/quic/crypto/key_exchange.h"
 
-#if defined(USE_OPENSSL)
-#include "crypto/openssl_util.h"
-#include "crypto/scoped_openssl_types.h"
-#else
-#include "crypto/ec_private_key.h"
-#include "crypto/scoped_nss_types.h"
-#endif
 
 namespace net {
 
@@ -59,19 +54,11 @@
     kUncompressedECPointForm = 0x04,
   };
 
-#if defined(USE_OPENSSL)
   // P256KeyExchange takes ownership of |private_key|, and expects
   // |public_key| consists of |kUncompressedP256PointBytes| bytes.
   P256KeyExchange(EC_KEY* private_key, const uint8_t* public_key);
 
   crypto::ScopedEC_KEY private_key_;
-#else
-  // P256KeyExchange takes ownership of |key_pair|, and expects
-  // |public_key| consists of |kUncompressedP256PointBytes| bytes.
-  P256KeyExchange(crypto::ECPrivateKey* key_pair, const uint8_t* public_key);
-
-  std::unique_ptr<crypto::ECPrivateKey> key_pair_;
-#endif
   // The public key stored as an uncompressed P-256 point.
   uint8_t public_key_[kUncompressedP256PointBytes];
 
diff --git a/net/quic/crypto/p256_key_exchange_nss.cc b/net/quic/crypto/p256_key_exchange_nss.cc
deleted file mode 100644
index 8c28e53..0000000
--- a/net/quic/crypto/p256_key_exchange_nss.cc
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/crypto/p256_key_exchange.h"
-
-#include "base/logging.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/sys_byteorder.h"
-
-using base::StringPiece;
-using std::string;
-using std::vector;
-
-namespace net {
-
-namespace {
-
-// Password used by |NewPrivateKey| to encrypt exported EC private keys.
-// This is not used to provide any security, but to workaround NSS being
-// unwilling to export unencrypted EC keys. Note that SPDY and ChannelID
-// use the same approach.
-const char kExportPassword[] = "";
-
-// Convert StringPiece to vector of uint8_t.
-static vector<uint8_t> StringPieceToVector(StringPiece piece) {
-  return vector<uint8_t>(piece.data(), piece.data() + piece.length());
-}
-
-}  // namespace
-
-P256KeyExchange::P256KeyExchange(crypto::ECPrivateKey* key_pair,
-                                 const uint8_t* public_key)
-    : key_pair_(key_pair) {
-  memcpy(public_key_, public_key, sizeof(public_key_));
-}
-
-P256KeyExchange::~P256KeyExchange() {}
-
-// static
-P256KeyExchange* P256KeyExchange::New(StringPiece key) {
-  if (key.size() < 2) {
-    DVLOG(1) << "Key pair is too small.";
-    return nullptr;
-  }
-
-  const uint8_t* data = reinterpret_cast<const uint8_t*>(key.data());
-  size_t size =
-      static_cast<size_t>(data[0]) | (static_cast<size_t>(data[1]) << 8);
-  key.remove_prefix(2);
-  if (key.size() < size) {
-    DVLOG(1) << "Key pair does not contain key material.";
-    return nullptr;
-  }
-
-  StringPiece private_piece(key.data(), size);
-  key.remove_prefix(size);
-  if (key.empty()) {
-    DVLOG(1) << "Key pair does not contain public key.";
-    return nullptr;
-  }
-
-  StringPiece public_piece(key);
-
-  std::unique_ptr<crypto::ECPrivateKey> key_pair(
-      crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
-          kExportPassword,
-          // TODO(thaidn): fix this interface to avoid copying secrets.
-          StringPieceToVector(private_piece),
-          StringPieceToVector(public_piece)));
-
-  if (!key_pair.get()) {
-    DVLOG(1) << "Can't decrypt private key.";
-    return nullptr;
-  }
-
-  // Perform some sanity checks on the public key.
-  SECKEYPublicKey* public_key = key_pair->public_key();
-  if (public_key->keyType != ecKey ||
-      public_key->u.ec.publicValue.len != kUncompressedP256PointBytes ||
-      !public_key->u.ec.publicValue.data ||
-      public_key->u.ec.publicValue.data[0] != kUncompressedECPointForm) {
-    DVLOG(1) << "Key is invalid.";
-    return nullptr;
-  }
-
-  // Ensure that the key is using the correct curve, i.e., NIST P-256.
-  const SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1);
-  if (!oid_data) {
-    DVLOG(1) << "Can't get P-256's OID.";
-    return nullptr;
-  }
-
-  if (public_key->u.ec.DEREncodedParams.len != oid_data->oid.len + 2 ||
-      !public_key->u.ec.DEREncodedParams.data ||
-      public_key->u.ec.DEREncodedParams.data[0] != SEC_ASN1_OBJECT_ID ||
-      public_key->u.ec.DEREncodedParams.data[1] != oid_data->oid.len ||
-      memcmp(public_key->u.ec.DEREncodedParams.data + 2, oid_data->oid.data,
-             oid_data->oid.len) != 0) {
-    DVLOG(1) << "Key is invalid.";
-  }
-
-  return new P256KeyExchange(key_pair.release(),
-                             public_key->u.ec.publicValue.data);
-}
-
-// static
-string P256KeyExchange::NewPrivateKey() {
-  std::unique_ptr<crypto::ECPrivateKey> key_pair(
-      crypto::ECPrivateKey::Create());
-
-  if (!key_pair.get()) {
-    DVLOG(1) << "Can't generate new key pair.";
-    return string();
-  }
-
-  vector<uint8_t> private_key;
-  if (!key_pair->ExportEncryptedPrivateKey(kExportPassword, 1 /* iteration */,
-                                           &private_key)) {
-    DVLOG(1) << "Can't export private key.";
-    return string();
-  }
-
-  // NSS lacks the ability to import an ECC private key without
-  // also importing the public key, so it is necessary to also
-  // store the public key.
-  vector<uint8_t> public_key;
-  if (!key_pair->ExportPublicKey(&public_key)) {
-    DVLOG(1) << "Can't export public key.";
-    return string();
-  }
-
-  // TODO(thaidn): determine how large encrypted private key can be
-  uint16_t private_key_size = base::checked_cast<uint16_t>(private_key.size());
-  const size_t result_size =
-      sizeof(private_key_size) + private_key_size + public_key.size();
-  vector<char> result(result_size);
-  char* resultp = &result[0];
-  // Export the key string.
-  // The first two bytes are the private key's size in little endian.
-  private_key_size = base::ByteSwapToLE16(private_key_size);
-  memcpy(resultp, &private_key_size, sizeof(private_key_size));
-  resultp += sizeof(private_key_size);
-  memcpy(resultp, &private_key[0], private_key.size());
-  resultp += private_key.size();
-  memcpy(resultp, &public_key[0], public_key.size());
-
-  return string(&result[0], result_size);
-}
-
-KeyExchange* P256KeyExchange::NewKeyPair(QuicRandom* /*rand*/) const {
-  // TODO(agl): avoid the serialisation/deserialisation in this function.
-  const string private_value = NewPrivateKey();
-  return P256KeyExchange::New(private_value);
-}
-
-bool P256KeyExchange::CalculateSharedKey(StringPiece peer_public_value,
-                                         string* out_result) const {
-  if (peer_public_value.size() != kUncompressedP256PointBytes ||
-      peer_public_value[0] != kUncompressedECPointForm) {
-    DVLOG(1) << "Peer public value is invalid.";
-    return false;
-  }
-
-  DCHECK(key_pair_.get());
-  DCHECK(key_pair_->public_key());
-
-  SECKEYPublicKey peer_public_key;
-  memset(&peer_public_key, 0, sizeof(peer_public_key));
-
-  peer_public_key.keyType = ecKey;
-  // Both sides of a ECDH key exchange need to use the same EC params.
-  peer_public_key.u.ec.DEREncodedParams.len =
-      key_pair_->public_key()->u.ec.DEREncodedParams.len;
-  peer_public_key.u.ec.DEREncodedParams.data =
-      key_pair_->public_key()->u.ec.DEREncodedParams.data;
-
-  peer_public_key.u.ec.publicValue.type = siBuffer;
-  peer_public_key.u.ec.publicValue.data =
-      reinterpret_cast<uint8_t*>(const_cast<char*>(peer_public_value.data()));
-  peer_public_key.u.ec.publicValue.len = peer_public_value.size();
-
-  // The NSS function performing ECDH key exchange is PK11_PubDeriveWithKDF.
-  // As this function is used for SSL/TLS's ECDH key exchanges it has many
-  // arguments, most of which are not required in QUIC.
-  // Key derivation function CKD_NULL is used because the return value of
-  // |CalculateSharedKey| is the actual ECDH shared key, not any derived keys
-  // from it.
-  crypto::ScopedPK11SymKey premaster_secret(
-      PK11_PubDeriveWithKDF(key_pair_->key(), &peer_public_key, PR_FALSE,
-                            nullptr, nullptr, CKM_ECDH1_DERIVE, /* mechanism */
-                            CKM_GENERIC_SECRET_KEY_GEN,         /* target */
-                            CKA_DERIVE, 0, CKD_NULL,            /* kdf */
-                            nullptr, nullptr));
-
-  if (!premaster_secret.get()) {
-    DVLOG(1) << "Can't derive ECDH shared key.";
-    return false;
-  }
-
-  if (PK11_ExtractKeyValue(premaster_secret.get()) != SECSuccess) {
-    DVLOG(1) << "Can't extract raw ECDH shared key.";
-    return false;
-  }
-
-  SECItem* key_data = PK11_GetKeyData(premaster_secret.get());
-  if (!key_data || !key_data->data || key_data->len != kP256FieldBytes) {
-    DVLOG(1) << "ECDH shared key is invalid.";
-    return false;
-  }
-
-  out_result->assign(reinterpret_cast<char*>(key_data->data), key_data->len);
-  return true;
-}
-
-StringPiece P256KeyExchange::public_value() const {
-  return StringPiece(reinterpret_cast<const char*>(public_key_),
-                     sizeof(public_key_));
-}
-
-QuicTag P256KeyExchange::tag() const {
-  return kP256;
-}
-
-}  // namespace net
diff --git a/net/quic/crypto/proof_source_chromium_nss.cc b/net/quic/crypto/proof_source_chromium_nss.cc
deleted file mode 100644
index 8ab7cc3..0000000
--- a/net/quic/crypto/proof_source_chromium_nss.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/crypto/proof_source_chromium.h"
-
-using std::string;
-using std::vector;
-
-namespace net {
-
-ProofSourceChromium::ProofSourceChromium() {}
-
-ProofSourceChromium::~ProofSourceChromium() {}
-
-bool ProofSourceChromium::Initialize(const base::FilePath& cert_path,
-                                     const base::FilePath& key_path,
-                                     const base::FilePath& sct_path) {
-  return false;
-}
-
-bool ProofSourceChromium::GetProof(const IPAddress& server_ip,
-                                   const string& hostname,
-                                   const string& server_config,
-                                   QuicVersion quic_version,
-                                   base::StringPiece chlo_hash,
-                                   bool ecdsa_ok,
-                                   scoped_refptr<ProofSource::Chain>* out_chain,
-                                   string* out_signature,
-                                   string* out_leaf_cert_sct) {
-  return false;
-}
-
-}  // namespace net
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index f937857..effc787 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 #include <memory>
+#include <string>
+#include <utility>
 #include <vector>
 
 #include "base/compiler_specific.h"
@@ -287,7 +289,7 @@
       QuicPacketNumber largest_received,
       QuicPacketNumber least_unacked,
       QuicErrorCode quic_error,
-      std::string& quic_error_details) {
+      const std::string& quic_error_details) {
     return maker_.MakeAckAndConnectionClosePacket(
         num, false, delta_time_largest_observed, largest_received,
         least_unacked, quic_error, quic_error_details);
@@ -305,15 +307,15 @@
   SpdyHeaderBlock GetRequestHeaders(const std::string& method,
                                     const std::string& scheme,
                                     const std::string& path) {
-    return GetRequestHeaders(method, scheme, path, maker_);
+    return GetRequestHeaders(method, scheme, path, &maker_);
   }
 
   // Uses customized QuicTestPacketMaker.
   SpdyHeaderBlock GetRequestHeaders(const std::string& method,
                                     const std::string& scheme,
                                     const std::string& path,
-                                    QuicTestPacketMaker& maker) {
-    return maker.GetRequestHeaders(method, scheme, path);
+                                    QuicTestPacketMaker* maker) {
+    return maker->GetRequestHeaders(method, scheme, path);
   }
 
   SpdyHeaderBlock GetResponseHeaders(const std::string& status) {
@@ -434,13 +436,11 @@
         packet_number, stream_id, should_include_version, fin, headers, offset);
   }
 
-  void CreateSession() { CreateSessionWithFactory(&socket_factory_); }
-
-  void CreateSessionWithFactory(ClientSocketFactory* socket_factory) {
+  void CreateSession() {
     params_.enable_quic = true;
     params_.quic_clock = clock_;
     params_.quic_random = &random_generator_;
-    params_.client_socket_factory = socket_factory;
+    params_.client_socket_factory = &socket_factory_;
     params_.quic_crypto_client_stream_factory = &crypto_client_stream_factory_;
     params_.host_resolver = &host_resolver_;
     params_.cert_verifier = &cert_verifier_;
@@ -1269,7 +1269,7 @@
   // Second QUIC request data.
   mock_quic_data.AddWrite(ConstructRequestHeadersPacket(
       3, kClientDataStreamId2, false, true,
-      GetRequestHeaders("GET", "https", "/", maker), &request_header_offset,
+      GetRequestHeaders("GET", "https", "/", &maker), &request_header_offset,
       &maker));
   mock_quic_data.AddRead(ConstructResponseHeadersPacket(
       3, kClientDataStreamId2, false, false, GetResponseHeaders("200 OK"),
@@ -1363,7 +1363,7 @@
   // First QUIC request data.
   mock_quic_data2.AddWrite(ConstructRequestHeadersPacket(
       1, kClientDataStreamId1, true, true,
-      GetRequestHeaders("GET", "https", "/", maker), &maker));
+      GetRequestHeaders("GET", "https", "/", &maker), &maker));
   mock_quic_data2.AddRead(
       ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false,
                                      GetResponseHeaders("200 OK"), &maker));
@@ -1804,12 +1804,10 @@
       MockRead(SYNCHRONOUS, 4, kQuicAlternateProtocolHeader),
       MockRead(SYNCHRONOUS, 5, "hello world"), MockRead(SYNCHRONOUS, OK, 6)};
 
-  MockClientSocketFactory socket_factory;
-
   SequencedSocketData http_data(http_reads, arraysize(http_reads), http_writes,
                                 arraysize(http_writes));
-  socket_factory.AddSocketDataProvider(&http_data);
-  socket_factory.AddSSLSocketDataProvider(&ssl_data_);
+  socket_factory_.AddSocketDataProvider(&http_data);
+  socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   // The QUIC transaction will not be allowed to complete.
   MockWrite quic_writes[] = {MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 1)};
@@ -1818,15 +1816,15 @@
   };
   SequencedSocketData quic_data(quic_reads, arraysize(quic_reads), quic_writes,
                                 arraysize(quic_writes));
-  socket_factory.AddSocketDataProvider(&quic_data);
+  socket_factory_.AddSocketDataProvider(&quic_data);
 
   // The HTTP transaction will complete.
   SequencedSocketData http_data2(http_reads, arraysize(http_reads), http_writes,
                                  arraysize(http_writes));
-  socket_factory.AddSocketDataProvider(&http_data2);
-  socket_factory.AddSSLSocketDataProvider(&ssl_data_);
+  socket_factory_.AddSocketDataProvider(&http_data2);
+  socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
-  CreateSessionWithFactory(&socket_factory);
+  CreateSession();
 
   // Run the first request.
   SendRequestAndExpectHttpResponse("hello world");
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index ee04541e..ba1750e 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -5,9 +5,10 @@
 #include "net/quic/quic_stream_factory.h"
 
 #include <algorithm>
-#include <set>
 #include <utility>
 
+#include <openssl/aead.h>
+
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
@@ -22,6 +23,7 @@
 #include "base/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
 #include "base/values.h"
+#include "crypto/openssl_util.h"
 #include "net/base/ip_address.h"
 #include "net/base/net_errors.h"
 #include "net/base/socket_performance_watcher.h"
@@ -58,13 +60,6 @@
 #include "base/win/windows_version.h"
 #endif
 
-#if defined(USE_OPENSSL)
-#include <openssl/aead.h>
-#include "crypto/openssl_util.h"
-#else
-#include "base/cpu.h"
-#endif
-
 using std::min;
 using std::vector;
 using NetworkHandle = net::NetworkChangeNotifier::NetworkHandle;
@@ -384,12 +379,12 @@
     const int kMaxLoadServerInfoTimeoutMs = 50;
     // Wait for DiskCache a maximum of 50ms.
     int64_t load_server_info_timeout_ms =
-        min(static_cast<int>(
-                (factory_->load_server_info_timeout_srtt_multiplier_ *
-                 factory_->GetServerNetworkStatsSmoothedRttInMicroseconds(
-                     server_id_)) /
-                1000),
-            kMaxLoadServerInfoTimeoutMs);
+        std::min(static_cast<int>(
+                     (factory_->load_server_info_timeout_srtt_multiplier_ *
+                      factory_->GetServerNetworkStatsSmoothedRttInMicroseconds(
+                          server_id_)) /
+                     1000),
+                 kMaxLoadServerInfoTimeoutMs);
     if (load_server_info_timeout_ms > 0) {
       factory_->task_runner_->PostDelayedTask(
           FROM_HERE,
@@ -681,13 +676,8 @@
   }
   if (enable_token_binding && channel_id_service && IsTokenBindingSupported())
     crypto_config_.tb_key_params.push_back(kP256);
-#if defined(USE_OPENSSL)
   crypto::EnsureOpenSSLInit();
   bool has_aes_hardware_support = !!EVP_has_aes_hardware();
-#else
-  base::CPU cpu;
-  bool has_aes_hardware_support = cpu.has_aesni() && cpu.has_avx();
-#endif
   UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.PreferAesGcm",
                         has_aes_hardware_support);
   if (has_aes_hardware_support || prefer_aes_)
@@ -766,8 +756,7 @@
   quic_server_info_factory_.reset(quic_server_info_factory);
 }
 
-bool QuicStreamFactory::CanUseExistingSession(QuicServerId server_id,
-                                              PrivacyMode privacy_mode,
+bool QuicStreamFactory::CanUseExistingSession(const QuicServerId& server_id,
                                               StringPiece origin_host) {
   // TODO(zhongyi): delete active_sessions_.empty() checks once the
   // android crash issue(crbug.com/498823) is resolved.
@@ -777,7 +766,7 @@
   if (it == active_sessions_.end())
     return false;
   QuicChromiumClientSession* session = it->second;
-  return session->CanPool(origin_host.as_string(), privacy_mode);
+  return session->CanPool(origin_host.as_string(), server_id.privacy_mode());
 }
 
 int QuicStreamFactory::Create(const HostPortPair& host_port_pair,
@@ -1722,7 +1711,7 @@
   // touches quic_server_info_map.
   const QuicServerInfoMap& quic_server_info_map =
       http_server_properties_->quic_server_info_map();
-  vector<QuicServerId> server_list(quic_server_info_map.size());
+  std::vector<QuicServerId> server_list(quic_server_info_map.size());
   for (const auto& key_value : quic_server_info_map)
     server_list.push_back(key_value.first);
   for (auto it = server_list.rbegin(); it != server_list.rend(); ++it) {
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h
index c7f10d1..1500d4a 100644
--- a/net/quic/quic_stream_factory.h
+++ b/net/quic/quic_stream_factory.h
@@ -36,6 +36,7 @@
 #include "net/quic/quic_crypto_stream.h"
 #include "net/quic/quic_http_stream.h"
 #include "net/quic/quic_protocol.h"
+#include "net/quic/quic_server_id.h"
 #include "net/ssl/ssl_config_service.h"
 
 namespace net {
@@ -52,7 +53,6 @@
 class QuicChromiumConnectionHelper;
 class QuicCryptoClientStreamFactory;
 class QuicRandom;
-class QuicServerId;
 class QuicServerInfo;
 class QuicServerInfoFactory;
 class QuicStreamFactory;
@@ -108,7 +108,6 @@
   QuicStreamFactory* factory_;
   HostPortPair host_port_pair_;
   std::string origin_host_;
-  std::string url_;
   PrivacyMode privacy_mode_;
   BoundNetLog net_log_;
   CompletionCallback callback_;
@@ -168,8 +167,7 @@
 
   // Returns true if there is an existing session to |server_id| which can be
   // used for request to |origin_host|.
-  bool CanUseExistingSession(QuicServerId server_id,
-                             PrivacyMode privacy_mode,
+  bool CanUseExistingSession(const QuicServerId& server_id,
                              StringPiece origin_host);
 
   // Creates a new QuicHttpStream to |host_port_pair| which will be
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index 794e40af21..c08de4aa 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -90,11 +90,11 @@
   return params;
 }
 
-}  // namespace anonymous
+}  // namespace
 
 class MockQuicServerInfo : public QuicServerInfo {
  public:
-  MockQuicServerInfo(const QuicServerId& server_id)
+  explicit MockQuicServerInfo(const QuicServerId& server_id)
       : QuicServerInfo(server_id) {}
   ~MockQuicServerInfo() override {}
 
@@ -280,10 +280,15 @@
                                                    host_port_pair);
   }
 
+  QuicChromiumClientSession* GetActiveSession(
+      const HostPortPair& host_port_pair) {
+    return QuicStreamFactoryPeer::GetActiveSession(factory_.get(),
+                                                   host_port_pair);
+  }
+
   std::unique_ptr<QuicHttpStream> CreateFromSession(
       const HostPortPair& host_port_pair) {
-    QuicChromiumClientSession* session =
-        QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair);
+    QuicChromiumClientSession* session = GetActiveSession(host_port_pair);
     return QuicStreamFactoryPeer::CreateFromSession(factory_.get(), session);
   }
 
@@ -317,8 +322,7 @@
     EXPECT_TRUE(stream.get());
     stream.reset();
 
-    QuicChromiumClientSession* session =
-        QuicStreamFactoryPeer::GetActiveSession(factory_.get(), destination);
+    QuicChromiumClientSession* session = GetActiveSession(destination);
 
     if (socket_count + 1 != socket_factory_.udp_client_socket_ports().size()) {
       ADD_FAILURE();
@@ -592,13 +596,11 @@
   std::unique_ptr<QuicHttpStream> stream = request.CreateStream();
   EXPECT_TRUE(stream.get());
 
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
 
   session->OnGoAway(QuicGoAwayFrame());
 
-  EXPECT_FALSE(
-      QuicStreamFactoryPeer::HasActiveSession(factory_.get(), host_port_pair_));
+  EXPECT_FALSE(HasActiveSession(host_port_pair_));
 
   EXPECT_TRUE(socket_data.AllReadDataConsumed());
   EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -623,8 +625,7 @@
   std::unique_ptr<QuicHttpStream> stream = request.CreateStream();
   EXPECT_TRUE(stream.get());
 
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
 
   session->OnGoAway(
       QuicGoAwayFrame(QUIC_ERROR_MIGRATING_PORT, 0,
@@ -637,8 +638,7 @@
   stream->PopulateNetErrorDetails(&details);
   EXPECT_TRUE(details.quic_port_migration_detected);
 
-  EXPECT_FALSE(
-      QuicStreamFactoryPeer::HasActiveSession(factory_.get(), host_port_pair_));
+  EXPECT_FALSE(HasActiveSession(host_port_pair_));
 
   EXPECT_TRUE(socket_data.AllReadDataConsumed());
   EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -674,9 +674,7 @@
   std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream();
   EXPECT_TRUE(stream2.get());
 
-  EXPECT_EQ(
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_),
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2));
+  EXPECT_EQ(GetActiveSession(host_port_pair_), GetActiveSession(server2));
 
   EXPECT_TRUE(socket_data.AllReadDataConsumed());
   EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -716,9 +714,7 @@
   std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream();
   EXPECT_TRUE(stream2.get());
 
-  EXPECT_NE(
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_),
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2));
+  EXPECT_NE(GetActiveSession(host_port_pair_), GetActiveSession(server2));
 
   EXPECT_TRUE(socket_data1.AllReadDataConsumed());
   EXPECT_TRUE(socket_data1.AllWriteDataConsumed());
@@ -759,12 +755,9 @@
   std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream();
   EXPECT_TRUE(stream2.get());
 
-  factory_->OnSessionGoingAway(
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_));
-  EXPECT_FALSE(
-      QuicStreamFactoryPeer::HasActiveSession(factory_.get(), host_port_pair_));
-  EXPECT_FALSE(
-      QuicStreamFactoryPeer::HasActiveSession(factory_.get(), server2));
+  factory_->OnSessionGoingAway(GetActiveSession(host_port_pair_));
+  EXPECT_FALSE(HasActiveSession(host_port_pair_));
+  EXPECT_FALSE(HasActiveSession(server2));
 
   TestCompletionCallback callback3;
   QuicStreamRequest request3(factory_.get());
@@ -774,7 +767,7 @@
   std::unique_ptr<QuicHttpStream> stream3 = request3.CreateStream();
   EXPECT_TRUE(stream3.get());
 
-  EXPECT_TRUE(QuicStreamFactoryPeer::HasActiveSession(factory_.get(), server2));
+  EXPECT_TRUE(HasActiveSession(server2));
 
   EXPECT_TRUE(socket_data1.AllReadDataConsumed());
   EXPECT_TRUE(socket_data1.AllWriteDataConsumed());
@@ -814,8 +807,7 @@
   std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream();
   EXPECT_TRUE(stream2.get());
 
-  EXPECT_EQ(QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server1),
-            QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2));
+  EXPECT_EQ(GetActiveSession(server1), GetActiveSession(server2));
 
   EXPECT_TRUE(socket_data.AllReadDataConsumed());
   EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -857,8 +849,7 @@
   std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream();
   EXPECT_TRUE(stream2.get());
 
-  EXPECT_NE(QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server1),
-            QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2));
+  EXPECT_NE(GetActiveSession(server1), GetActiveSession(server2));
 
   EXPECT_TRUE(socket_data1.AllReadDataConsumed());
   EXPECT_TRUE(socket_data1.AllWriteDataConsumed());
@@ -974,8 +965,7 @@
   std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream();
   EXPECT_TRUE(stream2.get());
 
-  EXPECT_EQ(QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server1),
-            QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2));
+  EXPECT_EQ(GetActiveSession(server1), GetActiveSession(server2));
 
   EXPECT_TRUE(socket_data.AllReadDataConsumed());
   EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -1023,8 +1013,7 @@
   std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream();
   EXPECT_TRUE(stream2.get());
 
-  EXPECT_NE(QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server1),
-            QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2));
+  EXPECT_NE(GetActiveSession(server1), GetActiveSession(server2));
 
   EXPECT_TRUE(socket_data1.AllReadDataConsumed());
   EXPECT_TRUE(socket_data1.AllWriteDataConsumed());
@@ -1077,8 +1066,7 @@
   std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream();
   EXPECT_TRUE(stream2.get());
 
-  EXPECT_NE(QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server1),
-            QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2));
+  EXPECT_NE(GetActiveSession(server1), GetActiveSession(server2));
 
   EXPECT_TRUE(socket_data1.AllReadDataConsumed());
   EXPECT_TRUE(socket_data1.AllWriteDataConsumed());
@@ -1110,13 +1098,11 @@
 
   // Mark the session as going away.  Ensure that while it is still alive
   // that it is no longer active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   factory_->OnSessionGoingAway(session);
   EXPECT_EQ(true,
             QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
-  EXPECT_FALSE(
-      QuicStreamFactoryPeer::HasActiveSession(factory_.get(), host_port_pair_));
+  EXPECT_FALSE(HasActiveSession(host_port_pair_));
   EXPECT_FALSE(HasActiveSession(host_port_pair_));
 
   // Create a new request for the same destination and verify that a
@@ -1130,10 +1116,8 @@
   std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream();
   EXPECT_TRUE(stream2.get());
 
-  EXPECT_TRUE(
-      QuicStreamFactoryPeer::HasActiveSession(factory_.get(), host_port_pair_));
-  EXPECT_NE(session, QuicStreamFactoryPeer::GetActiveSession(factory_.get(),
-                                                             host_port_pair_));
+  EXPECT_TRUE(HasActiveSession(host_port_pair_));
+  EXPECT_NE(session, GetActiveSession(host_port_pair_));
   EXPECT_EQ(true,
             QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
 
@@ -1210,8 +1194,7 @@
   // Force close of the connection to suppress the generation of RST
   // packets when streams are torn down, which wouldn't be relevant to
   // this test anyway.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   session->connection()->CloseConnection(QUIC_PUBLIC_RESET, "test",
                                          ConnectionCloseBehavior::SILENT_CLOSE);
 
@@ -1460,8 +1443,7 @@
                                          net_log_, CompletionCallback()));
 
   // Ensure that session is alive and active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
 
@@ -1517,10 +1499,8 @@
   std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream();
   EXPECT_TRUE(stream2.get());
 
-  EXPECT_TRUE(
-      QuicStreamFactoryPeer::HasActiveSession(factory_.get(), host_port_pair_));
-  QuicChromiumClientSession* new_session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  EXPECT_TRUE(HasActiveSession(host_port_pair_));
+  QuicChromiumClientSession* new_session = GetActiveSession(host_port_pair_);
   EXPECT_NE(session, new_session);
 
   // On a DISCONNECTED notification, nothing happens to the migrated
@@ -1575,8 +1555,7 @@
                                          net_log_, CompletionCallback()));
 
   // Ensure that session is alive and active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
 
@@ -1628,10 +1607,8 @@
   std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream();
   EXPECT_TRUE(stream2.get());
 
-  EXPECT_TRUE(
-      QuicStreamFactoryPeer::HasActiveSession(factory_.get(), host_port_pair_));
-  EXPECT_NE(session, QuicStreamFactoryPeer::GetActiveSession(factory_.get(),
-                                                             host_port_pair_));
+  EXPECT_TRUE(HasActiveSession(host_port_pair_));
+  EXPECT_NE(session, GetActiveSession(host_port_pair_));
   EXPECT_EQ(true,
             QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
 
@@ -1675,8 +1652,7 @@
                                          net_log_, CompletionCallback()));
 
   // Ensure that session is alive and active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
   EXPECT_EQ(1u, session->GetNumActiveStreams());
@@ -1729,8 +1705,7 @@
                                          net_log_, CompletionCallback()));
 
   // Ensure that session is alive and active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
 
@@ -1778,8 +1753,7 @@
                                          net_log_, CompletionCallback()));
 
   // Ensure that session is alive and active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
 
@@ -1830,8 +1804,7 @@
                                          net_log_, CompletionCallback()));
 
   // Ensure that session is alive and active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
 
@@ -1882,8 +1855,7 @@
                                          net_log_, CompletionCallback()));
 
   // Ensure that session is alive and active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
 
@@ -1935,8 +1907,7 @@
                                          net_log_, CompletionCallback()));
 
   // Ensure that session is alive and active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
 
@@ -1992,8 +1963,7 @@
                                          net_log_, CompletionCallback()));
 
   // Ensure that session is alive and active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
 
@@ -2043,8 +2013,7 @@
                                          net_log_, CompletionCallback()));
 
   // Ensure that session is alive and active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
 
@@ -2086,8 +2055,7 @@
   EXPECT_TRUE(stream.get());
 
   // Ensure that session is alive and active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
 
@@ -2124,8 +2092,7 @@
   EXPECT_TRUE(stream.get());
 
   // Ensure that session is alive and active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
 
@@ -2175,8 +2142,7 @@
                                          net_log_, CompletionCallback()));
 
   // Ensure that session is alive and active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
 
@@ -2235,10 +2201,8 @@
   std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream();
   EXPECT_TRUE(stream2.get());
 
-  EXPECT_TRUE(
-      QuicStreamFactoryPeer::HasActiveSession(factory_.get(), host_port_pair_));
-  QuicChromiumClientSession* new_session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  EXPECT_TRUE(HasActiveSession(host_port_pair_));
+  QuicChromiumClientSession* new_session = GetActiveSession(host_port_pair_);
   EXPECT_NE(session, new_session);
 
   // On a SOON_TO_DISCONNECT notification, nothing happens to the
@@ -2296,8 +2260,7 @@
                                          net_log_, CompletionCallback()));
 
   // Ensure that session is alive and active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
 
@@ -2353,8 +2316,7 @@
                                          net_log_, CompletionCallback()));
 
   // Ensure that session is alive and active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
 
@@ -2408,8 +2370,7 @@
                                          net_log_, CompletionCallback()));
 
   // Ensure that session is alive and active.
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
 
@@ -2809,8 +2770,7 @@
                                 /*cert_verify_flags=*/0, url_, "GET", net_log_,
                                 callback_.callback()));
 
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
 
   DVLOG(1) << "Create 1st session and test packet loss";
 
@@ -2818,8 +2778,7 @@
   EXPECT_FALSE(
       factory_->OnHandshakeConfirmed(session, /*packet_loss_rate=*/0.9f));
   EXPECT_TRUE(session->connection()->connected());
-  EXPECT_TRUE(
-      QuicStreamFactoryPeer::HasActiveSession(factory_.get(), host_port_pair_));
+  EXPECT_TRUE(HasActiveSession(host_port_pair_));
   EXPECT_FALSE(QuicStreamFactoryPeer::IsQuicDisabled(factory_.get(),
                                                      host_port_pair_.port()));
   EXPECT_EQ(0, QuicStreamFactoryPeer::GetNumberOfLossyConnections(
@@ -2834,8 +2793,7 @@
   EXPECT_TRUE(session->connection()->connected());
   EXPECT_FALSE(QuicStreamFactoryPeer::IsQuicDisabled(factory_.get(),
                                                      host_port_pair_.port()));
-  EXPECT_TRUE(
-      QuicStreamFactoryPeer::HasActiveSession(factory_.get(), host_port_pair_));
+  EXPECT_TRUE(HasActiveSession(host_port_pair_));
 
   // Test N-in-a-row high packet loss connections.
 
@@ -2846,8 +2804,7 @@
   EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
                                  /*cert_verify_flags=*/0, url_, "GET", net_log_,
                                  callback2.callback()));
-  QuicChromiumClientSession* session2 =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2);
+  QuicChromiumClientSession* session2 = GetActiveSession(server2);
 
   // If there is no packet loss during handshake confirmation, number of lossy
   // connections for the port should be 0.
@@ -2869,7 +2826,7 @@
   EXPECT_TRUE(session2->connection()->connected());
   EXPECT_FALSE(
       QuicStreamFactoryPeer::IsQuicDisabled(factory_.get(), server2.port()));
-  EXPECT_TRUE(QuicStreamFactoryPeer::HasActiveSession(factory_.get(), server2));
+  EXPECT_TRUE(HasActiveSession(server2));
 
   DVLOG(1) << "Create 3rd session which also has packet loss";
 
@@ -2878,8 +2835,7 @@
   EXPECT_EQ(OK, request3.Request(server3, privacy_mode_,
                                  /*cert_verify_flags=*/0, url3_, "GET",
                                  net_log_, callback3.callback()));
-  QuicChromiumClientSession* session3 =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server3);
+  QuicChromiumClientSession* session3 = GetActiveSession(server3);
 
   DVLOG(1) << "Create 4th session with packet loss and test IsQuicDisabled()";
   TestCompletionCallback callback4;
@@ -2887,8 +2843,7 @@
   EXPECT_EQ(OK, request4.Request(server4, privacy_mode_,
                                  /*cert_verify_flags=*/0, url4_, "GET",
                                  net_log_, callback4.callback()));
-  QuicChromiumClientSession* session4 =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server4);
+  QuicChromiumClientSession* session4 = GetActiveSession(server4);
 
   // Set packet_loss_rate to higher value than packet_loss_threshold 2nd time in
   // a row and that should close the session and disable QUIC.
@@ -2899,8 +2854,7 @@
   EXPECT_FALSE(session3->connection()->connected());
   EXPECT_TRUE(
       QuicStreamFactoryPeer::IsQuicDisabled(factory_.get(), server3.port()));
-  EXPECT_FALSE(
-      QuicStreamFactoryPeer::HasActiveSession(factory_.get(), server3));
+  EXPECT_FALSE(HasActiveSession(server3));
   EXPECT_FALSE(HasActiveSession(server3));
 
   // Set packet_loss_rate to higher value than packet_loss_threshold 3rd time in
@@ -2912,8 +2866,7 @@
   EXPECT_FALSE(session4->connection()->connected());
   EXPECT_TRUE(
       QuicStreamFactoryPeer::IsQuicDisabled(factory_.get(), server4.port()));
-  EXPECT_FALSE(
-      QuicStreamFactoryPeer::HasActiveSession(factory_.get(), server4));
+  EXPECT_FALSE(HasActiveSession(server4));
   EXPECT_FALSE(HasActiveSession(server4));
 
   std::unique_ptr<QuicHttpStream> stream = request.CreateStream();
@@ -2969,8 +2922,7 @@
                                 /*cert_verify_flags=*/0, url_, "GET", net_log_,
                                 callback_.callback()));
 
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
 
   DVLOG(1) << "Created 1st session. Now trigger public reset post handshake";
   session->connection()->CloseConnection(QUIC_PUBLIC_RESET, "test",
@@ -2992,8 +2944,7 @@
   EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
                                  /*cert_verify_flags=*/0, url2_, "GET",
                                  net_log_, callback2.callback()));
-  QuicChromiumClientSession* session2 =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2);
+  QuicChromiumClientSession* session2 = GetActiveSession(server2);
 
   session2->connection()->CloseConnection(
       QUIC_PUBLIC_RESET, "test", ConnectionCloseBehavior::SILENT_CLOSE);
@@ -3054,8 +3005,7 @@
                                 /*cert_verify_flags=*/0, url_, "GET", net_log_,
                                 callback_.callback()));
 
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
 
   std::unique_ptr<QuicHttpStream> stream = request.CreateStream();
   EXPECT_TRUE(stream.get());
@@ -3084,8 +3034,7 @@
   EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
                                  /*cert_verify_flags=*/0, url2_, "GET",
                                  net_log_, callback2.callback()));
-  QuicChromiumClientSession* session2 =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2);
+  QuicChromiumClientSession* session2 = GetActiveSession(server2);
 
   std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream();
   EXPECT_TRUE(stream2.get());
@@ -3159,8 +3108,7 @@
                                 /*cert_verify_flags=*/0, url_, "GET", net_log_,
                                 callback_.callback()));
 
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
 
   DVLOG(1) << "Created 1st session. Now trigger public reset post handshake";
   session->connection()->CloseConnection(QUIC_PUBLIC_RESET, "test",
@@ -3181,8 +3129,7 @@
   EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
                                  /*cert_verify_flags=*/0, url2_, "GET",
                                  net_log_, callback2.callback()));
-  QuicChromiumClientSession* session2 =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2);
+  QuicChromiumClientSession* session2 = GetActiveSession(server2);
 
   session2->connection()->CloseConnection(
       QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
@@ -3202,8 +3149,7 @@
   EXPECT_EQ(OK, request3.Request(server3, privacy_mode_,
                                  /*cert_verify_flags=*/0, url2_, "GET",
                                  net_log_, callback3.callback()));
-  QuicChromiumClientSession* session3 =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server3);
+  QuicChromiumClientSession* session3 = GetActiveSession(server3);
 
   session3->connection()->CloseConnection(
       QUIC_PUBLIC_RESET, "test", ConnectionCloseBehavior::SILENT_CLOSE);
@@ -3277,8 +3223,7 @@
                                 /*cert_verify_flags=*/0, url_, "GET", net_log_,
                                 callback_.callback()));
 
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
 
   std::unique_ptr<QuicHttpStream> stream = request.CreateStream();
   EXPECT_TRUE(stream.get());
@@ -3307,8 +3252,7 @@
   EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
                                  /*cert_verify_flags=*/0, url2_, "GET",
                                  net_log_, callback2.callback()));
-  QuicChromiumClientSession* session2 =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2);
+  QuicChromiumClientSession* session2 = GetActiveSession(server2);
 
   session2->connection()->CloseConnection(
       QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
@@ -3329,8 +3273,7 @@
   EXPECT_EQ(OK, request3.Request(server3, privacy_mode_,
                                  /*cert_verify_flags=*/0, url3_, "GET",
                                  net_log_, callback3.callback()));
-  QuicChromiumClientSession* session3 =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server3);
+  QuicChromiumClientSession* session3 = GetActiveSession(server3);
 
   std::unique_ptr<QuicHttpStream> stream3 = request3.CreateStream();
   EXPECT_TRUE(stream3.get());
@@ -3396,8 +3339,7 @@
                                 /*cert_verify_flags=*/0, url_, "GET", net_log_,
                                 callback_.callback()));
 
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
 
   std::unique_ptr<QuicHttpStream> stream = request.CreateStream();
   EXPECT_TRUE(stream.get());
@@ -3485,8 +3427,7 @@
                                 /*cert_verify_flags=*/0, url_, "GET", net_log_,
                                 callback_.callback()));
 
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
 
   DVLOG(1) << "Created 1st session. Now trigger public reset post handshake";
   session->connection()->CloseConnection(QUIC_PUBLIC_RESET, "test",
@@ -3507,8 +3448,7 @@
   EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
                                  /*cert_verify_flags=*/0, url2_, "GET",
                                  net_log_, callback2.callback()));
-  QuicChromiumClientSession* session2 =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2);
+  QuicChromiumClientSession* session2 = GetActiveSession(server2);
 
   session2->connection()->CloseConnection(
       QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
@@ -3526,8 +3466,7 @@
   EXPECT_EQ(OK, request3.Request(server3, privacy_mode_,
                                  /*cert_verify_flags=*/0, url3_, "GET",
                                  net_log_, callback3.callback()));
-  QuicChromiumClientSession* session3 =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server3);
+  QuicChromiumClientSession* session3 = GetActiveSession(server3);
 
   session3->connection()->CloseConnection(
       QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
@@ -3547,8 +3486,7 @@
   EXPECT_EQ(OK, request4.Request(server4, privacy_mode_,
                                  /*cert_verify_flags=*/0, url4_, "GET",
                                  net_log_, callback4.callback()));
-  QuicChromiumClientSession* session4 =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server4);
+  QuicChromiumClientSession* session4 = GetActiveSession(server4);
 
   session4->connection()->CloseConnection(
       QUIC_PUBLIC_RESET, "test", ConnectionCloseBehavior::SILENT_CLOSE);
@@ -3629,8 +3567,7 @@
                                 /*cert_verify_flags=*/0, url_, "GET", net_log_,
                                 callback_.callback()));
 
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
 
   std::unique_ptr<QuicHttpStream> stream = request.CreateStream();
   EXPECT_TRUE(stream.get());
@@ -3658,8 +3595,7 @@
   EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
                                  /*cert_verify_flags=*/0, url2_, "GET",
                                  net_log_, callback2.callback()));
-  QuicChromiumClientSession* session2 =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2);
+  QuicChromiumClientSession* session2 = GetActiveSession(server2);
 
   session2->connection()->CloseConnection(
       QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
@@ -3677,8 +3613,7 @@
   EXPECT_EQ(OK, request3.Request(server3, privacy_mode_,
                                  /*cert_verify_flags=*/0, url3_, "GET",
                                  net_log_, callback3.callback()));
-  QuicChromiumClientSession* session3 =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server3);
+  QuicChromiumClientSession* session3 = GetActiveSession(server3);
 
   session3->connection()->CloseConnection(
       QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
@@ -3699,8 +3634,7 @@
   EXPECT_EQ(OK, request4.Request(server4, privacy_mode_,
                                  /*cert_verify_flags=*/0, url4_, "GET",
                                  net_log_, callback4.callback()));
-  QuicChromiumClientSession* session4 =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server4);
+  QuicChromiumClientSession* session4 = GetActiveSession(server4);
 
   std::unique_ptr<QuicHttpStream> stream4 = request4.CreateStream();
   EXPECT_TRUE(stream4.get());
@@ -4080,8 +4014,7 @@
 
   std::string url = "https://www.example.org/";
 
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
 
   QuicClientPromisedInfo promised(session, kServerDataStreamId1, url);
   (*QuicStreamFactoryPeer::GetPushPromiseIndex(factory_.get())
@@ -4129,8 +4062,7 @@
   EXPECT_EQ(0, QuicStreamFactoryPeer::GetNumPushStreamsCreated(factory_.get()));
 
   std::string url = "https://www.example.org/";
-  QuicChromiumClientSession* session =
-      QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
 
   QuicClientPromisedInfo promised(session, kServerDataStreamId1, url);
 
diff --git a/net/quic/test_tools/crypto_test_utils_chromium.cc b/net/quic/test_tools/crypto_test_utils_chromium.cc
index d78df969..121db431 100644
--- a/net/quic/test_tools/crypto_test_utils_chromium.cc
+++ b/net/quic/test_tools/crypto_test_utils_chromium.cc
@@ -75,157 +75,11 @@
   std::unique_ptr<CTVerifier> cert_transparency_verifier_;
 };
 
-const char kSignature[] = "signature";
-const char kSCT[] = "CryptoServerTests";
-
-class FakeProofSource : public ProofSource {
- public:
-  FakeProofSource() {}
-  ~FakeProofSource() override {}
-
-  // ProofSource interface
-  bool Initialize(const base::FilePath& cert_path,
-                  const base::FilePath& key_path,
-                  const base::FilePath& sct_path) {
-    std::string cert_data;
-    if (!base::ReadFileToString(cert_path, &cert_data)) {
-      DLOG(FATAL) << "Unable to read certificates.";
-      return false;
-    }
-
-    CertificateList certs_in_file =
-        X509Certificate::CreateCertificateListFromBytes(
-            cert_data.data(), cert_data.size(), X509Certificate::FORMAT_AUTO);
-
-    if (certs_in_file.empty()) {
-      DLOG(FATAL) << "No certificates.";
-      return false;
-    }
-
-    vector<string> certs;
-    for (const scoped_refptr<X509Certificate>& cert : certs_in_file) {
-      std::string der_encoded_cert;
-      if (!X509Certificate::GetDEREncoded(cert->os_cert_handle(),
-                                          &der_encoded_cert)) {
-        return false;
-      }
-      certs.push_back(der_encoded_cert);
-    }
-    chain_ = new ProofSource::Chain(certs);
-    return true;
-  }
-
-  bool GetProof(const IPAddress& server_ip,
-                const std::string& hostname,
-                const std::string& server_config,
-                QuicVersion quic_version,
-                StringPiece chlo_hash,
-                bool ecdsa_ok,
-                scoped_refptr<ProofSource::Chain>* out_chain,
-                std::string* out_signature,
-                std::string* out_leaf_cert_sct) override {
-    out_signature->assign(kSignature);
-    *out_chain = chain_;
-    *out_leaf_cert_sct = kSCT;
-    return true;
-  }
-
- private:
-  scoped_refptr<ProofSource::Chain> chain_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeProofSource);
-};
-
-class FakeProofVerifier : public TestProofVerifierChromium {
- public:
-  FakeProofVerifier(
-      std::unique_ptr<CertVerifier> cert_verifier,
-      std::unique_ptr<TransportSecurityState> transport_security_state,
-      std::unique_ptr<CTVerifier> cert_transparency_verifier,
-      const std::string& cert_file)
-      : TestProofVerifierChromium(std::move(cert_verifier),
-                                  std::move(transport_security_state),
-                                  std::move(cert_transparency_verifier),
-                                  cert_file) {}
-  ~FakeProofVerifier() override {}
-
-  // ProofVerifier interface
-  QuicAsyncStatus VerifyProof(
-      const std::string& hostname,
-      const uint16_t port,
-      const std::string& server_config,
-      QuicVersion quic_version,
-      StringPiece chlo_hash,
-      const std::vector<std::string>& certs,
-      const std::string& cert_sct,
-      const std::string& signature,
-      const ProofVerifyContext* verify_context,
-      std::string* error_details,
-      std::unique_ptr<ProofVerifyDetails>* verify_details,
-      ProofVerifierCallback* callback) override {
-    error_details->clear();
-    std::unique_ptr<ProofVerifyDetailsChromium> verify_details_chromium(
-        new ProofVerifyDetailsChromium);
-    DCHECK(!certs.empty());
-    // Convert certs to X509Certificate.
-    vector<StringPiece> cert_pieces(certs.size());
-    for (unsigned i = 0; i < certs.size(); i++) {
-      cert_pieces[i] = base::StringPiece(certs[i]);
-    }
-    scoped_refptr<X509Certificate> x509_cert =
-        X509Certificate::CreateFromDERCertChain(cert_pieces);
-
-    if (!x509_cert.get()) {
-      *error_details = "Failed to create certificate chain";
-      verify_details_chromium->cert_verify_result.cert_status =
-          CERT_STATUS_INVALID;
-      *verify_details = std::move(verify_details_chromium);
-      return QUIC_FAILURE;
-    }
-
-    const ProofVerifyContextChromium* chromium_context =
-        reinterpret_cast<const ProofVerifyContextChromium*>(verify_context);
-    std::unique_ptr<CertVerifier::Request> cert_verifier_request_;
-    TestCompletionCallback test_callback;
-    int result = cert_verifier()->Verify(
-        x509_cert.get(), hostname, std::string(),
-        chromium_context->cert_verify_flags,
-        SSLConfigService::GetCRLSet().get(),
-        &verify_details_chromium->cert_verify_result, test_callback.callback(),
-        &cert_verifier_request_, chromium_context->net_log);
-    if (result != OK) {
-      std::string error_string = ErrorToString(result);
-      *error_details = StringPrintf("Failed to verify certificate chain: %s",
-                                    error_string.c_str());
-      verify_details_chromium->cert_verify_result.cert_status =
-          CERT_STATUS_INVALID;
-      *verify_details = std::move(verify_details_chromium);
-      return QUIC_FAILURE;
-    }
-    if (signature != kSignature) {
-      *error_details = "Invalid proof";
-      verify_details_chromium->cert_verify_result.cert_status =
-          CERT_STATUS_INVALID;
-      *verify_details = std::move(verify_details_chromium);
-      return QUIC_FAILURE;
-    }
-    *verify_details = std::move(verify_details_chromium);
-    return QUIC_SUCCESS;
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(FakeProofVerifier);
-};
-
 }  // namespace
 
 // static
 ProofSource* CryptoTestUtils::ProofSourceForTesting() {
-#if defined(USE_OPENSSL)
   ProofSourceChromium* source = new ProofSourceChromium();
-#else
-  FakeProofSource* source = new FakeProofSource();
-#endif
   base::FilePath certs_dir = GetTestCertsDirectory();
   CHECK(source->Initialize(
       certs_dir.AppendASCII("quic_chain.crt"),
@@ -252,15 +106,9 @@
         std::move(cert_verifier), base::WrapUnique(new TransportSecurityState),
         base::WrapUnique(new MultiLogCTVerifier), "quic_root.crt");
   }
-#if defined(USE_OPENSSL)
   return new TestProofVerifierChromium(
       std::move(cert_verifier), base::WrapUnique(new TransportSecurityState),
       base::WrapUnique(new MultiLogCTVerifier), "quic_root.crt");
-#else
-  return new FakeProofVerifier(
-      std::move(cert_verifier), base::WrapUnique(new TransportSecurityState),
-      base::WrapUnique(new MultiLogCTVerifier), "quic_root.crt");
-#endif
 }
 
 // static
diff --git a/net/quic/test_tools/crypto_test_utils_nss.cc b/net/quic/test_tools/crypto_test_utils_nss.cc
deleted file mode 100644
index c34dc01..0000000
--- a/net/quic/test_tools/crypto_test_utils_nss.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
-#include "base/strings/string_util.h"
-#include "crypto/ec_private_key.h"
-#include "crypto/ec_signature_creator.h"
-#include "net/quic/crypto/channel_id.h"
-#include "net/quic/crypto/channel_id_chromium.h"
-#include "net/quic/test_tools/crypto_test_utils.h"
-
-using base::StringPiece;
-using std::string;
-
-namespace net {
-
-namespace test {
-
-class TestChannelIDSource : public ChannelIDSource {
- public:
-  ~TestChannelIDSource() override { STLDeleteValues(&hostname_to_key_); }
-
-  // ChannelIDSource implementation.
-
-  QuicAsyncStatus GetChannelIDKey(
-      const string& hostname,
-      std::unique_ptr<ChannelIDKey>* channel_id_key,
-      ChannelIDSourceCallback* /*callback*/) override {
-    channel_id_key->reset(new ChannelIDKeyChromium(HostnameToKey(hostname)));
-    return QUIC_SUCCESS;
-  }
-
- private:
-  typedef std::map<string, crypto::ECPrivateKey*> HostnameToKeyMap;
-
-  std::unique_ptr<crypto::ECPrivateKey> HostnameToKey(const string& hostname) {
-    HostnameToKeyMap::const_iterator it = hostname_to_key_.find(hostname);
-    if (it != hostname_to_key_.end()) {
-      return base::WrapUnique(it->second->Copy());
-    }
-
-    crypto::ECPrivateKey* keypair = crypto::ECPrivateKey::Create();
-    if (!keypair) {
-      return nullptr;
-    }
-    hostname_to_key_[hostname] = keypair;
-    return base::WrapUnique(keypair->Copy());
-  }
-
-  HostnameToKeyMap hostname_to_key_;
-};
-
-// static
-ChannelIDSource* CryptoTestUtils::ChannelIDSourceForTesting() {
-  return new TestChannelIDSource();
-}
-
-}  // namespace test
-
-}  // namespace net
diff --git a/net/quic/test_tools/quic_test_packet_maker.cc b/net/quic/test_tools/quic_test_packet_maker.cc
index 99f5712..9ddd05d6 100644
--- a/net/quic/test_tools/quic_test_packet_maker.cc
+++ b/net/quic/test_tools/quic_test_packet_maker.cc
@@ -139,7 +139,7 @@
     QuicPacketNumber largest_received,
     QuicPacketNumber least_unacked,
     QuicErrorCode quic_error,
-    std::string& quic_error_details) {
+    const std::string& quic_error_details) {
   QuicPacketHeader header;
   header.public_header.connection_id = connection_id_;
   header.public_header.reset_flag = false;
diff --git a/net/quic/test_tools/quic_test_packet_maker.h b/net/quic/test_tools/quic_test_packet_maker.h
index e60ab3c..dec0c677 100644
--- a/net/quic/test_tools/quic_test_packet_maker.h
+++ b/net/quic/test_tools/quic_test_packet_maker.h
@@ -62,7 +62,7 @@
       QuicPacketNumber largest_received,
       QuicPacketNumber least_unacked,
       QuicErrorCode quic_error,
-      std::string& quic_error_details);
+      const std::string& quic_error_details);
   std::unique_ptr<QuicReceivedPacket> MakeConnectionClosePacket(
       QuicPacketNumber num);
   std::unique_ptr<QuicReceivedPacket> MakeGoAwayPacket(
diff --git a/net/socket/client_socket_factory.cc b/net/socket/client_socket_factory.cc
index 78685594..c7597c5 100644
--- a/net/socket/client_socket_factory.cc
+++ b/net/socket/client_socket_factory.cc
@@ -10,15 +10,10 @@
 #include "build/build_config.h"
 #include "net/cert/cert_database.h"
 #include "net/socket/client_socket_handle.h"
+#include "net/socket/ssl_client_socket_openssl.h"
 #include "net/socket/tcp_client_socket.h"
 #include "net/udp/udp_client_socket.h"
 
-#if defined(USE_OPENSSL)
-#include "net/socket/ssl_client_socket_openssl.h"
-#else
-#include "net/socket/ssl_client_socket_nss.h"
-#endif
-
 namespace net {
 
 class X509Certificate;
@@ -72,13 +67,8 @@
       const HostPortPair& host_and_port,
       const SSLConfig& ssl_config,
       const SSLClientSocketContext& context) override {
-#if defined(USE_OPENSSL)
     return std::unique_ptr<SSLClientSocket>(new SSLClientSocketOpenSSL(
         std::move(transport_socket), host_and_port, ssl_config, context));
-#else
-    return std::unique_ptr<SSLClientSocket>(new SSLClientSocketNSS(
-        std::move(transport_socket), host_and_port, ssl_config, context));
-#endif
   }
 
   void ClearSSLSessionCache() override { SSLClientSocket::ClearSessionCache(); }
diff --git a/net/socket/nss_ssl_util.cc b/net/socket/nss_ssl_util.cc
deleted file mode 100644
index 274aa2da..0000000
--- a/net/socket/nss_ssl_util.cc
+++ /dev/null
@@ -1,412 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/socket/nss_ssl_util.h"
-
-#include <nss.h>
-#include <secerr.h>
-#include <ssl.h>
-#include <sslerr.h>
-#include <sslproto.h>
-
-#include <string>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/cpu.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/memory/singleton.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/values.h"
-#include "build/build_config.h"
-#include "crypto/nss_util.h"
-#include "net/base/net_errors.h"
-#include "net/base/nss_memio.h"
-#include "net/log/net_log.h"
-
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#endif
-
-namespace net {
-
-namespace {
-
-// CiphersRemove takes a zero-terminated array of cipher suite ids in
-// |to_remove| and sets every instance of them in |ciphers| to zero. It returns
-// true if it found and removed every element of |to_remove|. It assumes that
-// there are no duplicates in |ciphers| nor in |to_remove|.
-bool CiphersRemove(const uint16_t* to_remove, uint16_t* ciphers, size_t num) {
-  size_t i, found = 0;
-
-  for (i = 0; ; i++) {
-    if (to_remove[i] == 0)
-      break;
-
-    for (size_t j = 0; j < num; j++) {
-      if (to_remove[i] == ciphers[j]) {
-        ciphers[j] = 0;
-        found++;
-        break;
-      }
-    }
-  }
-
-  return found == i;
-}
-
-// CiphersCompact takes an array of cipher suite ids in |ciphers|, where some
-// entries are zero, and moves the entries so that all the non-zero elements
-// are compacted at the end of the array.
-void CiphersCompact(uint16_t* ciphers, size_t num) {
-  size_t j = num - 1;
-
-  for (size_t i = num - 1; i < num; i--) {
-    if (ciphers[i] == 0)
-      continue;
-    ciphers[j--] = ciphers[i];
-  }
-}
-
-// CiphersCopy copies the zero-terminated array |in| to |out|. It returns the
-// number of cipher suite ids copied.
-size_t CiphersCopy(const uint16_t* in, uint16_t* out) {
-  for (size_t i = 0; ; i++) {
-    if (in[i] == 0)
-      return i;
-    out[i] = in[i];
-  }
-}
-
-std::unique_ptr<base::Value> NetLogSSLErrorCallback(
-    int net_error,
-    int ssl_lib_error,
-    NetLogCaptureMode /* capture_mode */) {
-  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
-  dict->SetInteger("net_error", net_error);
-  if (ssl_lib_error)
-    dict->SetInteger("ssl_lib_error", ssl_lib_error);
-  return std::move(dict);
-}
-
-class NSSSSLInitSingleton {
- public:
-  NSSSSLInitSingleton() : model_fd_(NULL) {
-    crypto::EnsureNSSInit();
-
-    NSS_SetDomesticPolicy();
-
-    const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers();
-    const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers();
-
-    // Disable ECDSA cipher suites on platforms that do not support ECDSA
-    // signed certificates, as servers may use the presence of such
-    // ciphersuites as a hint to send an ECDSA certificate.
-    bool disableECDSA = false;
-#if defined(OS_WIN)
-    if (base::win::GetVersion() < base::win::VERSION_VISTA)
-      disableECDSA = true;
-#endif
-
-    // Explicitly enable exactly those ciphers with keys of at least 80 bits.
-    for (int i = 0; i < num_ciphers; i++) {
-      SSLCipherSuiteInfo info;
-      if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info,
-                                 sizeof(info)) == SECSuccess) {
-        bool enabled = info.effectiveKeyBits >= 80;
-        if (info.authAlgorithm == ssl_auth_ecdsa && disableECDSA)
-          enabled = false;
-
-        // Trim the list of cipher suites in order to keep the size of the
-        // ClientHello down. DSS, ECDH, CAMELLIA, SEED, ECC+3DES, and
-        // HMAC-SHA256 cipher suites are disabled.
-        if (info.symCipher == ssl_calg_camellia ||
-            info.symCipher == ssl_calg_seed ||
-            (info.symCipher == ssl_calg_3des && info.keaType != ssl_kea_rsa) ||
-            info.authAlgorithm == ssl_auth_dsa ||
-            info.macAlgorithm == ssl_hmac_sha256 ||
-            info.nonStandard ||
-            strcmp(info.keaTypeName, "ECDH") == 0) {
-          enabled = false;
-        }
-
-        SSL_CipherPrefSetDefault(ssl_ciphers[i], enabled);
-      }
-    }
-
-    // Enable SSL.
-    SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE);
-
-    // Calculate the order of ciphers that we'll use for NSS sockets. (Note
-    // that, even if a cipher is specified in the ordering, it must still be
-    // enabled in order to be included in a ClientHello.)
-    //
-    // Our top preference cipher suites are either forward-secret AES-GCM or
-    // forward-secret ChaCha20-Poly1305. If the local machine has AES-NI then
-    // we prefer AES-GCM, otherwise ChaCha20. The remainder of the cipher suite
-    // preference is inheriented from NSS. */
-    static const uint16_t chacha_ciphers[] = {
-        TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
-        TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-        TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0,
-    };
-    static const uint16_t aes_gcm_ciphers[] = {
-        TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
-        TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-        TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, 0,
-    };
-    std::unique_ptr<uint16_t[]> ciphers(new uint16_t[num_ciphers]);
-    memcpy(ciphers.get(), ssl_ciphers, sizeof(uint16_t) * num_ciphers);
-
-    if (CiphersRemove(chacha_ciphers, ciphers.get(), num_ciphers) &&
-        CiphersRemove(aes_gcm_ciphers, ciphers.get(), num_ciphers)) {
-      CiphersCompact(ciphers.get(), num_ciphers);
-
-      const uint16_t* preference_ciphers = chacha_ciphers;
-      const uint16_t* other_ciphers = aes_gcm_ciphers;
-      base::CPU cpu;
-
-      if (cpu.has_aesni() && cpu.has_avx()) {
-        preference_ciphers = aes_gcm_ciphers;
-        other_ciphers = chacha_ciphers;
-      }
-      unsigned i = CiphersCopy(preference_ciphers, ciphers.get());
-      CiphersCopy(other_ciphers, &ciphers[i]);
-
-      if ((model_fd_ = memio_CreateIOLayer(1, 1)) == NULL ||
-          SSL_ImportFD(NULL, model_fd_) == NULL ||
-          SECSuccess !=
-              SSL_CipherOrderSet(model_fd_, ciphers.get(), num_ciphers)) {
-        NOTREACHED();
-        if (model_fd_) {
-          PR_Close(model_fd_);
-          model_fd_ = NULL;
-        }
-      }
-    }
-
-    // All other SSL options are set per-session by SSLClientSocket and
-    // SSLServerSocket.
-  }
-
-  PRFileDesc* GetModelSocket() {
-    return model_fd_;
-  }
-
-  ~NSSSSLInitSingleton() {
-    // Have to clear the cache, or NSS_Shutdown fails with SEC_ERROR_BUSY.
-    SSL_ClearSessionCache();
-    if (model_fd_)
-      PR_Close(model_fd_);
-  }
-
- private:
-  PRFileDesc* model_fd_;
-};
-
-base::LazyInstance<NSSSSLInitSingleton>::Leaky g_nss_ssl_init_singleton =
-    LAZY_INSTANCE_INITIALIZER;
-
-}  // anonymous namespace
-
-// Initialize the NSS SSL library if it isn't already initialized.  This must
-// be called before any other NSS SSL functions.  This function is
-// thread-safe, and the NSS SSL library will only ever be initialized once.
-// The NSS SSL library will be properly shut down on program exit.
-void EnsureNSSSSLInit() {
-  // Initializing SSL causes us to do blocking IO.
-  // Temporarily allow it until we fix
-  //   http://code.google.com/p/chromium/issues/detail?id=59847
-  base::ThreadRestrictions::ScopedAllowIO allow_io;
-
-  g_nss_ssl_init_singleton.Get();
-}
-
-PRFileDesc* GetNSSModelSocket() {
-  return g_nss_ssl_init_singleton.Get().GetModelSocket();
-}
-
-// Map a Chromium net error code to an NSS error code.
-// See _MD_unix_map_default_error in the NSS source
-// tree for inspiration.
-PRErrorCode MapErrorToNSS(int result) {
-  if (result >=0)
-    return result;
-
-  switch (result) {
-    case ERR_IO_PENDING:
-      return PR_WOULD_BLOCK_ERROR;
-    case ERR_ACCESS_DENIED:
-    case ERR_NETWORK_ACCESS_DENIED:
-      // For connect, this could be mapped to PR_ADDRESS_NOT_SUPPORTED_ERROR.
-      return PR_NO_ACCESS_RIGHTS_ERROR;
-    case ERR_NOT_IMPLEMENTED:
-      return PR_NOT_IMPLEMENTED_ERROR;
-    case ERR_SOCKET_NOT_CONNECTED:
-      return PR_NOT_CONNECTED_ERROR;
-    case ERR_INTERNET_DISCONNECTED:  // Equivalent to ENETDOWN.
-      return PR_NETWORK_UNREACHABLE_ERROR;  // Best approximation.
-    case ERR_CONNECTION_TIMED_OUT:
-    case ERR_TIMED_OUT:
-      return PR_IO_TIMEOUT_ERROR;
-    case ERR_CONNECTION_RESET:
-      return PR_CONNECT_RESET_ERROR;
-    case ERR_CONNECTION_ABORTED:
-      return PR_CONNECT_ABORTED_ERROR;
-    case ERR_CONNECTION_REFUSED:
-      return PR_CONNECT_REFUSED_ERROR;
-    case ERR_ADDRESS_UNREACHABLE:
-      return PR_HOST_UNREACHABLE_ERROR;  // Also PR_NETWORK_UNREACHABLE_ERROR.
-    case ERR_ADDRESS_INVALID:
-      return PR_ADDRESS_NOT_AVAILABLE_ERROR;
-    case ERR_NAME_NOT_RESOLVED:
-      return PR_DIRECTORY_LOOKUP_ERROR;
-    default:
-      LOG(WARNING) << "MapErrorToNSS " << result
-                   << " mapped to PR_UNKNOWN_ERROR";
-      return PR_UNKNOWN_ERROR;
-  }
-}
-
-// The default error mapping function.
-// Maps an NSS error code to a network error code.
-int MapNSSError(PRErrorCode err) {
-  // TODO(port): fill this out as we learn what's important
-  switch (err) {
-    case PR_WOULD_BLOCK_ERROR:
-      return ERR_IO_PENDING;
-    case PR_ADDRESS_NOT_SUPPORTED_ERROR:  // For connect.
-    case PR_NO_ACCESS_RIGHTS_ERROR:
-      return ERR_ACCESS_DENIED;
-    case PR_IO_TIMEOUT_ERROR:
-      return ERR_TIMED_OUT;
-    case PR_CONNECT_RESET_ERROR:
-      return ERR_CONNECTION_RESET;
-    case PR_CONNECT_ABORTED_ERROR:
-      return ERR_CONNECTION_ABORTED;
-    case PR_CONNECT_REFUSED_ERROR:
-      return ERR_CONNECTION_REFUSED;
-    case PR_NOT_CONNECTED_ERROR:
-      return ERR_SOCKET_NOT_CONNECTED;
-    case PR_HOST_UNREACHABLE_ERROR:
-    case PR_NETWORK_UNREACHABLE_ERROR:
-      return ERR_ADDRESS_UNREACHABLE;
-    case PR_ADDRESS_NOT_AVAILABLE_ERROR:
-      return ERR_ADDRESS_INVALID;
-    case PR_INVALID_ARGUMENT_ERROR:
-      return ERR_INVALID_ARGUMENT;
-    case PR_END_OF_FILE_ERROR:
-      return ERR_CONNECTION_CLOSED;
-    case PR_NOT_IMPLEMENTED_ERROR:
-      return ERR_NOT_IMPLEMENTED;
-
-    case SEC_ERROR_LIBRARY_FAILURE:
-      return ERR_UNEXPECTED;
-    case SEC_ERROR_INVALID_ARGS:
-      return ERR_INVALID_ARGUMENT;
-    case SEC_ERROR_NO_MEMORY:
-      return ERR_OUT_OF_MEMORY;
-    case SEC_ERROR_NO_KEY:
-      return ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY;
-    case SEC_ERROR_INVALID_KEY:
-    case SSL_ERROR_SIGN_HASHES_FAILURE:
-      LOG(ERROR) << "ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED: NSS error " << err
-                 << ", OS error " << PR_GetOSError();
-      return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
-    // A handshake (initial or renegotiation) may fail because some signature
-    // (for example, the signature in the ServerKeyExchange message for an
-    // ephemeral Diffie-Hellman cipher suite) is invalid.
-    case SEC_ERROR_BAD_SIGNATURE:
-      return ERR_SSL_PROTOCOL_ERROR;
-
-    case SSL_ERROR_SSL_DISABLED:
-      return ERR_NO_SSL_VERSIONS_ENABLED;
-    case SSL_ERROR_NO_CYPHER_OVERLAP:
-    case SSL_ERROR_PROTOCOL_VERSION_ALERT:
-    case SSL_ERROR_UNSUPPORTED_VERSION:
-      return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
-    case SSL_ERROR_HANDSHAKE_FAILURE_ALERT:
-    case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT:
-    case SSL_ERROR_ILLEGAL_PARAMETER_ALERT:
-      return ERR_SSL_PROTOCOL_ERROR;
-    case SSL_ERROR_DECOMPRESSION_FAILURE_ALERT:
-      return ERR_SSL_DECOMPRESSION_FAILURE_ALERT;
-    case SSL_ERROR_BAD_MAC_ALERT:
-      return ERR_SSL_BAD_RECORD_MAC_ALERT;
-    case SSL_ERROR_DECRYPT_ERROR_ALERT:
-      return ERR_SSL_DECRYPT_ERROR_ALERT;
-    case SSL_ERROR_UNRECOGNIZED_NAME_ALERT:
-      return ERR_SSL_UNRECOGNIZED_NAME_ALERT;
-    case SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY:
-      return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY;
-    case SSL_ERROR_HANDSHAKE_NOT_COMPLETED:
-      return ERR_SSL_HANDSHAKE_NOT_COMPLETED;
-    case SEC_ERROR_BAD_KEY:
-    case SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE:
-    // TODO(wtc): the following errors may also occur in contexts unrelated
-    // to the peer's public key.  We should add new error codes for them, or
-    // map them to ERR_SSL_BAD_PEER_PUBLIC_KEY only in the right context.
-    // General unsupported/unknown key algorithm error.
-    case SEC_ERROR_UNSUPPORTED_KEYALG:
-    // General DER decoding errors.
-    case SEC_ERROR_BAD_DER:
-    case SEC_ERROR_EXTRA_INPUT:
-      return ERR_SSL_BAD_PEER_PUBLIC_KEY;
-    // During renegotiation, the server presented a different certificate than
-    // was used earlier.
-    case SSL_ERROR_WRONG_CERTIFICATE:
-      return ERR_SSL_SERVER_CERT_CHANGED;
-    case SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT:
-      return ERR_SSL_INAPPROPRIATE_FALLBACK;
-
-    default: {
-      const char* err_name = PR_ErrorToName(err);
-      if (err_name == NULL)
-        err_name = "";
-      if (IS_SSL_ERROR(err)) {
-        LOG(WARNING) << "Unknown SSL error " << err << " (" << err_name << ")"
-                     << " mapped to net::ERR_SSL_PROTOCOL_ERROR";
-        return ERR_SSL_PROTOCOL_ERROR;
-      }
-      LOG(WARNING) << "Unknown error " << err << " (" << err_name << ")"
-                   << " mapped to net::ERR_FAILED";
-      return ERR_FAILED;
-    }
-  }
-}
-
-// Returns parameters to attach to the NetLog when we receive an error in
-// response to a call to an NSS function.  Used instead of
-// NetLogSSLErrorCallback with events of type TYPE_SSL_NSS_ERROR.
-std::unique_ptr<base::Value> NetLogSSLFailedNSSFunctionCallback(
-    const char* function,
-    const char* param,
-    int ssl_lib_error,
-    NetLogCaptureMode /* capture_mode */) {
-  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
-  dict->SetString("function", function);
-  if (param[0] != '\0')
-    dict->SetString("param", param);
-  dict->SetInteger("ssl_lib_error", ssl_lib_error);
-  return std::move(dict);
-}
-
-void LogFailedNSSFunction(const BoundNetLog& net_log,
-                          const char* function,
-                          const char* param) {
-  DCHECK(function);
-  DCHECK(param);
-  net_log.AddEvent(
-      NetLog::TYPE_SSL_NSS_ERROR,
-      base::Bind(&NetLogSSLFailedNSSFunctionCallback,
-                 function, param, PR_GetError()));
-}
-
-NetLog::ParametersCallback CreateNetLogSSLErrorCallback(int net_error,
-                                                        int ssl_lib_error) {
-  return base::Bind(&NetLogSSLErrorCallback, net_error, ssl_lib_error);
-}
-
-}  // namespace net
diff --git a/net/socket/nss_ssl_util.h b/net/socket/nss_ssl_util.h
deleted file mode 100644
index 5d9ec7e..0000000
--- a/net/socket/nss_ssl_util.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file is only included in ssl_client_socket_nss.cc and
-// ssl_server_socket_nss.cc to share common functions of NSS.
-
-#ifndef NET_SOCKET_NSS_SSL_UTIL_H_
-#define NET_SOCKET_NSS_SSL_UTIL_H_
-
-#include <prerror.h>
-#include <prio.h>
-
-#include "net/base/net_export.h"
-#include "net/log/net_log.h"
-
-namespace net {
-
-class BoundNetLog;
-
-// Initalize NSS SSL library.
-NET_EXPORT void EnsureNSSSSLInit();
-
-// Log a failed NSS funcion call.
-void LogFailedNSSFunction(const BoundNetLog& net_log,
-                          const char* function,
-                          const char* param);
-
-// Map network error code to NSS error code.
-PRErrorCode MapErrorToNSS(int result);
-
-// GetNSSModelSocket returns either NULL, or an NSS socket that can be passed
-// to |SSL_ImportFD| in order to inherit some default options.
-PRFileDesc* GetNSSModelSocket();
-
-// Map NSS error code to network error code.
-int MapNSSError(PRErrorCode err);
-
-// Creates a NetLog callback for an SSL error.
-NetLog::ParametersCallback CreateNetLogSSLErrorCallback(int net_error,
-                                                        int ssl_lib_error);
-
-
-}  // namespace net
-
-#endif  // NET_SOCKET_NSS_SSL_UTIL_H_
diff --git a/net/socket/ssl_client_socket.cc b/net/socket/ssl_client_socket.cc
index a7c0dd4..b076fb4 100644
--- a/net/socket/ssl_client_socket.cc
+++ b/net/socket/ssl_client_socket.cc
@@ -10,14 +10,12 @@
 #include "crypto/ec_private_key.h"
 #include "net/base/connection_type_histograms.h"
 #include "net/base/net_errors.h"
+#include "net/socket/ssl_client_socket_openssl.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/ssl_cipher_suite_names.h"
 #include "net/ssl/ssl_config_service.h"
 #include "net/ssl/ssl_connection_status_flags.h"
 
-#if defined(USE_OPENSSL)
-#include "net/socket/ssl_client_socket_openssl.h"
-#endif
 
 namespace net {
 
@@ -78,7 +76,7 @@
 void SSLClientSocket::SetSSLKeyLogFile(
     const base::FilePath& path,
     const scoped_refptr<base::SequencedTaskRunner>& task_runner) {
-#if defined(USE_OPENSSL) && !defined(OS_NACL)
+#if !defined(OS_NACL)
   SSLClientSocketOpenSSL::SetSSLKeyLogFile(path, task_runner);
 #else
   NOTIMPLEMENTED();
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
deleted file mode 100644
index 1d5c7157..0000000
--- a/net/socket/ssl_client_socket_nss.cc
+++ /dev/null
@@ -1,3189 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived
-// from AuthCertificateCallback() in
-// mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp.
-
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Ian McGreer <mcgreer@netscape.com>
- *   Javier Delgadillo <javi@netscape.com>
- *   Kai Engert <kengert@redhat.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "net/socket/ssl_client_socket_nss.h"
-
-#include <certdb.h>
-#include <hasht.h>
-#include <keyhi.h>
-#include <nspr.h>
-#include <nss.h>
-#include <ocsp.h>
-#include <pk11pub.h>
-#include <secerr.h>
-#include <sechash.h>
-#include <ssl.h>
-#include <sslerr.h>
-#include <sslproto.h>
-
-#include <algorithm>
-#include <limits>
-#include <map>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback_helpers.h"
-#include "base/compiler_specific.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/thread_task_runner_handle.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/values.h"
-#include "crypto/ec_private_key.h"
-#include "crypto/nss_util.h"
-#include "crypto/nss_util_internal.h"
-#include "crypto/rsa_private_key.h"
-#include "crypto/scoped_nss_types.h"
-#include "net/base/address_list.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/sockaddr_storage.h"
-#include "net/cert/asn1_util.h"
-#include "net/cert/cert_status_flags.h"
-#include "net/cert/cert_verifier.h"
-#include "net/cert/ct_ev_whitelist.h"
-#include "net/cert/ct_policy_enforcer.h"
-#include "net/cert/ct_policy_status.h"
-#include "net/cert/ct_verifier.h"
-#include "net/cert/ct_verify_result.h"
-#include "net/cert/scoped_nss_types.h"
-#include "net/cert/sct_status_flags.h"
-#include "net/cert/x509_certificate_net_log_param.h"
-#include "net/cert/x509_util.h"
-#include "net/cert_net/nss_ocsp.h"
-#include "net/dns/dns_util.h"
-#include "net/http/transport_security_state.h"
-#include "net/log/net_log.h"
-#include "net/socket/client_socket_handle.h"
-#include "net/socket/nss_ssl_util.h"
-#include "net/ssl/ssl_cert_request_info.h"
-#include "net/ssl/ssl_cipher_suite_names.h"
-#include "net/ssl/ssl_connection_status_flags.h"
-#include "net/ssl/ssl_failure_state.h"
-#include "net/ssl/ssl_info.h"
-
-#if defined(USE_NSS_CERTS)
-#include <dlfcn.h>
-#endif
-
-namespace net {
-
-// State machines are easier to debug if you log state transitions.
-// Enable these if you want to see what's going on.
-#if 1
-#define EnterFunction(x)
-#define LeaveFunction(x)
-#define GotoState(s) next_handshake_state_ = s
-#else
-#define EnterFunction(x)\
-    VLOG(1) << (void *)this << " " << __FUNCTION__ << " enter " << x\
-            << "; next_handshake_state " << next_handshake_state_
-#define LeaveFunction(x)\
-    VLOG(1) << (void *)this << " " << __FUNCTION__ << " leave " << x\
-            << "; next_handshake_state " << next_handshake_state_
-#define GotoState(s)\
-    do {\
-      VLOG(1) << (void *)this << " " << __FUNCTION__ << " jump to state " << s;\
-      next_handshake_state_ = s;\
-    } while (0)
-#endif
-
-namespace {
-
-// SSL plaintext fragments are shorter than 16KB. Although the record layer
-// overhead is allowed to be 2K + 5 bytes, in practice the overhead is much
-// smaller than 1KB. So a 17KB buffer should be large enough to hold an
-// entire SSL record.
-const int kRecvBufferSize = 17 * 1024;
-const int kSendBufferSize = 17 * 1024;
-
-// Used by SSLClientSocketNSS::Core to indicate there is no read result
-// obtained by a previous operation waiting to be returned to the caller.
-// This constant can be any non-negative/non-zero value (eg: it does not
-// overlap with any value of the net::Error range, including net::OK).
-const int kNoPendingReadResult = 1;
-
-// Helper functions to make it possible to log events from within the
-// SSLClientSocketNSS::Core.
-void AddLogEvent(const base::WeakPtr<BoundNetLog>& net_log,
-                 NetLog::EventType event_type) {
-  if (!net_log)
-    return;
-  net_log->AddEvent(event_type);
-}
-
-// Helper function to make it possible to log events from within the
-// SSLClientSocketNSS::Core.
-void AddLogEventWithCallback(const base::WeakPtr<BoundNetLog>& net_log,
-                             NetLog::EventType event_type,
-                             const NetLog::ParametersCallback& callback) {
-  if (!net_log)
-    return;
-  net_log->AddEvent(event_type, callback);
-}
-
-// Helper function to make it easier to call BoundNetLog::AddByteTransferEvent
-// from within the SSLClientSocketNSS::Core.
-// AddByteTransferEvent expects to receive a const char*, which within the
-// Core is backed by an IOBuffer. If the "const char*" is bound via
-// base::Bind and posted to another thread, and the IOBuffer that backs that
-// pointer then goes out of scope on the origin thread, this would result in
-// an invalid read of a stale pointer.
-// Instead, provide a signature that accepts an IOBuffer*, so that a reference
-// to the owning IOBuffer can be bound to the Callback. This ensures that the
-// IOBuffer will stay alive long enough to cross threads if needed.
-void LogByteTransferEvent(
-    const base::WeakPtr<BoundNetLog>& net_log, NetLog::EventType event_type,
-    int len, IOBuffer* buffer) {
-  if (!net_log)
-    return;
-  net_log->AddByteTransferEvent(event_type, len, buffer->data());
-}
-
-// PeerCertificateChain is a helper object which extracts the certificate
-// chain, as given by the server, from an NSS socket and performs the needed
-// resource management. The first element of the chain is the leaf certificate
-// and the other elements are in the order given by the server.
-class PeerCertificateChain {
- public:
-  PeerCertificateChain() {}
-  PeerCertificateChain(const PeerCertificateChain& other);
-  ~PeerCertificateChain();
-  PeerCertificateChain& operator=(const PeerCertificateChain& other);
-
-  // Resets the current chain, freeing any resources, and updates the current
-  // chain to be a copy of the chain stored in |nss_fd|.
-  // If |nss_fd| is NULL, then the current certificate chain will be freed.
-  void Reset(PRFileDesc* nss_fd);
-
-  // Returns the current certificate chain as a vector of DER-encoded
-  // base::StringPieces. The returned vector remains valid until Reset is
-  // called.
-  std::vector<base::StringPiece> AsStringPieceVector() const;
-
-  bool empty() const { return certs_.empty(); }
-
-  CERTCertificate* operator[](size_t index) const {
-    DCHECK_LT(index, certs_.size());
-    return certs_[index];
-  }
-
- private:
-  std::vector<CERTCertificate*> certs_;
-};
-
-PeerCertificateChain::PeerCertificateChain(
-    const PeerCertificateChain& other) {
-  *this = other;
-}
-
-PeerCertificateChain::~PeerCertificateChain() {
-  Reset(NULL);
-}
-
-PeerCertificateChain& PeerCertificateChain::operator=(
-    const PeerCertificateChain& other) {
-  if (this == &other)
-    return *this;
-
-  Reset(NULL);
-  certs_.reserve(other.certs_.size());
-  for (size_t i = 0; i < other.certs_.size(); ++i)
-    certs_.push_back(CERT_DupCertificate(other.certs_[i]));
-
-  return *this;
-}
-
-void PeerCertificateChain::Reset(PRFileDesc* nss_fd) {
-  for (size_t i = 0; i < certs_.size(); ++i)
-    CERT_DestroyCertificate(certs_[i]);
-  certs_.clear();
-
-  if (nss_fd == NULL)
-    return;
-
-  CERTCertList* list = SSL_PeerCertificateChain(nss_fd);
-  // The handshake on |nss_fd| may not have completed.
-  if (list == NULL)
-    return;
-
-  for (CERTCertListNode* node = CERT_LIST_HEAD(list);
-       !CERT_LIST_END(node, list); node = CERT_LIST_NEXT(node)) {
-    certs_.push_back(CERT_DupCertificate(node->cert));
-  }
-  CERT_DestroyCertList(list);
-}
-
-std::vector<base::StringPiece>
-PeerCertificateChain::AsStringPieceVector() const {
-  std::vector<base::StringPiece> v(certs_.size());
-  for (unsigned i = 0; i < certs_.size(); i++) {
-    v[i] = base::StringPiece(
-        reinterpret_cast<const char*>(certs_[i]->derCert.data),
-        certs_[i]->derCert.len);
-  }
-
-  return v;
-}
-
-// HandshakeState is a helper struct used to pass handshake state between
-// the NSS task runner and the network task runner.
-//
-// It contains members that may be read or written on the NSS task runner,
-// but which also need to be read from the network task runner. The NSS task
-// runner will notify the network task runner whenever this state changes, so
-// that the network task runner can safely make a copy, which avoids the need
-// for locking.
-struct HandshakeState {
-  HandshakeState() { Reset(); }
-
-  void Reset() {
-    next_proto_status = SSLClientSocket::kNextProtoUnsupported;
-    next_proto.clear();
-    negotiation_extension_ = SSLClientSocket::kExtensionUnknown;
-    channel_id_sent = false;
-    server_cert_chain.Reset(NULL);
-    server_cert = NULL;
-    sct_list_from_tls_extension.clear();
-    stapled_ocsp_response.clear();
-    resumed_handshake = false;
-    ssl_connection_status = 0;
-  }
-
-  // Set to kNextProtoNegotiated if NPN was successfully negotiated, with the
-  // negotiated protocol stored in |next_proto|.
-  SSLClientSocket::NextProtoStatus next_proto_status;
-  std::string next_proto;
-
-  // TLS extension used for protocol negotiation.
-  SSLClientSocket::SSLNegotiationExtension negotiation_extension_;
-
-  // True if a channel ID was sent.
-  bool channel_id_sent;
-
-  // List of DER-encoded X.509 DistinguishedName of certificate authorities
-  // allowed by the server.
-  std::vector<std::string> cert_authorities;
-
-  // Set when the handshake fully completes.
-  //
-  // The server certificate is first received from NSS as an NSS certificate
-  // chain (|server_cert_chain|) and then converted into a platform-specific
-  // X509Certificate object (|server_cert|). It's possible for some
-  // certificates to be successfully parsed by NSS, and not by the platform
-  // libraries (i.e.: when running within a sandbox, different parsing
-  // algorithms, etc), so it's not safe to assume that |server_cert| will
-  // always be non-NULL.
-  PeerCertificateChain server_cert_chain;
-  scoped_refptr<X509Certificate> server_cert;
-  // SignedCertificateTimestampList received via TLS extension (RFC 6962).
-  std::string sct_list_from_tls_extension;
-  // Stapled OCSP response received.
-  std::string stapled_ocsp_response;
-
-  // True if the current handshake was the result of TLS session resumption.
-  bool resumed_handshake;
-
-  // The negotiated security parameters (TLS version, cipher, extensions) of
-  // the SSL connection.
-  int ssl_connection_status;
-};
-
-// Client-side error mapping functions.
-
-// Map NSS error code to network error code.
-int MapNSSClientError(PRErrorCode err) {
-  switch (err) {
-    case SSL_ERROR_BAD_CERT_ALERT:
-    case SSL_ERROR_UNSUPPORTED_CERT_ALERT:
-    case SSL_ERROR_REVOKED_CERT_ALERT:
-    case SSL_ERROR_EXPIRED_CERT_ALERT:
-    case SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT:
-    case SSL_ERROR_UNKNOWN_CA_ALERT:
-    case SSL_ERROR_ACCESS_DENIED_ALERT:
-      return ERR_BAD_SSL_CLIENT_AUTH_CERT;
-    default:
-      return MapNSSError(err);
-  }
-}
-
-}  // namespace
-
-// SSLClientSocketNSS::Core provides a thread-safe, ref-counted core that is
-// able to marshal data between NSS functions and an underlying transport
-// socket.
-//
-// All public functions are meant to be called from the network task runner,
-// and any callbacks supplied will be invoked there as well, provided that
-// Detach() has not been called yet.
-//
-/////////////////////////////////////////////////////////////////////////////
-//
-// Threading within SSLClientSocketNSS and SSLClientSocketNSS::Core:
-//
-// Because NSS may block on either hardware or user input during operations
-// such as signing, creating certificates, or locating private keys, the Core
-// handles all of the interactions with the underlying NSS SSL socket, so
-// that these blocking calls can be executed on a dedicated task runner.
-//
-// Note that the network task runner and the NSS task runner may be executing
-// on the same thread. If that happens, then it's more performant to try to
-// complete as much work as possible synchronously, even if it might block,
-// rather than continually PostTask-ing to the same thread.
-//
-// Because NSS functions should only be called on the NSS task runner, while
-// I/O resources should only be accessed on the network task runner, most
-// public functions are implemented via three methods, each with different
-// task runner affinities.
-//
-// In the single-threaded mode (where the network and NSS task runners run on
-// the same thread), these are all attempted synchronously, while in the
-// multi-threaded mode, message passing is used.
-//
-// 1) NSS Task Runner: Execute NSS function (DoPayloadRead, DoPayloadWrite,
-//    DoHandshake)
-// 2) NSS Task Runner: Prepare data to go from NSS to an IO function:
-//    (BufferRecv, BufferSend)
-// 3) Network Task Runner: Perform IO on that data (DoBufferRecv,
-//    DoBufferSend, DoGetChannelID, OnGetChannelIDComplete)
-// 4) Both Task Runners: Callback for asynchronous completion or to marshal
-//    data from the network task runner back to NSS (BufferRecvComplete,
-//    BufferSendComplete, OnHandshakeIOComplete)
-//
-/////////////////////////////////////////////////////////////////////////////
-// Single-threaded example
-//
-// |--------------------------Network Task Runner--------------------------|
-//  SSLClientSocketNSS              Core               (Transport Socket)
-//       Read()
-//         |-------------------------V
-//                                 Read()
-//                                   |
-//                            DoPayloadRead()
-//                                   |
-//                               BufferRecv()
-//                                   |
-//                              DoBufferRecv()
-//                                   |-------------------------V
-//                                                           Read()
-//                                   V-------------------------|
-//                          BufferRecvComplete()
-//                                   |
-//                           PostOrRunCallback()
-//         V-------------------------|
-//    (Read Callback)
-//
-/////////////////////////////////////////////////////////////////////////////
-// Multi-threaded example:
-//
-// |--------------------Network Task Runner-------------|--NSS Task Runner--|
-//  SSLClientSocketNSS          Core            Socket         Core
-//       Read()
-//         |---------------------V
-//                             Read()
-//                               |-------------------------------V
-//                                                             Read()
-//                                                               |
-//                                                         DoPayloadRead()
-//                                                               |
-//                                                          BufferRecv
-//                               V-------------------------------|
-//                          DoBufferRecv
-//                               |----------------V
-//                                              Read()
-//                               V----------------|
-//                        BufferRecvComplete()
-//                               |-------------------------------V
-//                                                      BufferRecvComplete()
-//                                                               |
-//                                                       PostOrRunCallback()
-//                               V-------------------------------|
-//                        PostOrRunCallback()
-//         V---------------------|
-//    (Read Callback)
-//
-/////////////////////////////////////////////////////////////////////////////
-class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
- public:
-  // Creates a new Core.
-  //
-  // Any calls to NSS are executed on the |nss_task_runner|, while any calls
-  // that need to operate on the underlying transport, net log, or server
-  // bound certificate fetching will happen on the |network_task_runner|, so
-  // that their lifetimes match that of the owning SSLClientSocketNSS.
-  //
-  // The caller retains ownership of |transport|, |net_log|, and
-  // |channel_id_service|, and they will not be accessed once Detach()
-  // has been called.
-  Core(base::SequencedTaskRunner* network_task_runner,
-       base::SequencedTaskRunner* nss_task_runner,
-       ClientSocketHandle* transport,
-       const HostPortPair& host_and_port,
-       const SSLConfig& ssl_config,
-       BoundNetLog* net_log,
-       ChannelIDService* channel_id_service);
-
-  // Called on the network task runner.
-  // Transfers ownership of |socket|, an NSS SSL socket, and |buffers|, the
-  // underlying memio implementation, to the Core. Returns true if the Core
-  // was successfully registered with the socket.
-  bool Init(PRFileDesc* socket, memio_Private* buffers);
-
-  // Called on the network task runner.
-  //
-  // Attempts to perform an SSL handshake. If the handshake cannot be
-  // completed synchronously, returns ERR_IO_PENDING, invoking |callback| on
-  // the network task runner once the handshake has completed. Otherwise,
-  // returns OK on success or a network error code on failure.
-  int Connect(const CompletionCallback& callback);
-
-  // Called on the network task runner.
-  // Signals that the resources owned by the network task runner are going
-  // away. No further callbacks will be invoked on the network task runner.
-  // May be called at any time.
-  void Detach();
-
-  // Called on the network task runner.
-  // Returns the current state of the underlying SSL socket. May be called at
-  // any time.
-  const HandshakeState& state() const { return network_handshake_state_; }
-
-  // Called on the network task runner.
-  // Read() and Write() mirror the net::Socket functions of the same name.
-  // If ERR_IO_PENDING is returned, |callback| will be invoked on the network
-  // task runner at a later point, unless the caller calls Detach().
-  int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
-  int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
-
-  // Called on the network task runner.
-  bool IsConnected() const;
-  bool HasPendingAsyncOperation() const;
-  bool HasUnhandledReceivedData() const;
-  bool WasEverUsed() const;
-
-  // Called on the network task runner.
-  // Causes the associated SSL/TLS session ID to be added to NSS's session
-  // cache, but only if the connection has not been False Started.
-  //
-  // This should only be called after the server's certificate has been
-  // verified, and may not be called within an NSS callback.
-  void CacheSessionIfNecessary();
-
-  crypto::ECPrivateKey* GetChannelIDKey() const {
-    return channel_id_key_.get();
-  }
-
- private:
-  friend class base::RefCountedThreadSafe<Core>;
-  ~Core();
-
-  enum State {
-    STATE_NONE,
-    STATE_HANDSHAKE,
-    STATE_GET_DOMAIN_BOUND_CERT_COMPLETE,
-  };
-
-  bool OnNSSTaskRunner() const;
-  bool OnNetworkTaskRunner() const;
-
-  ////////////////////////////////////////////////////////////////////////////
-  // Methods that are ONLY called on the NSS task runner:
-  ////////////////////////////////////////////////////////////////////////////
-
-  // Called by NSS during full handshakes to allow the application to
-  // verify the certificate. Instead of verifying the certificate in the midst
-  // of the handshake, SECSuccess is always returned and the peer's certificate
-  // is verified afterwards.
-  // This behaviour is an artifact of the original SSLClientSocketWin
-  // implementation, which could not verify the peer's certificate until after
-  // the handshake had completed, as well as bugs in NSS that prevent
-  // SSL_RestartHandshakeAfterCertReq from working.
-  static SECStatus OwnAuthCertHandler(void* arg,
-                                      PRFileDesc* socket,
-                                      PRBool checksig,
-                                      PRBool is_server);
-
-  // Callbacks called by NSS when the peer requests client certificate
-  // authentication.
-  // See the documentation in third_party/nss/ssl/ssl.h for the meanings of
-  // the arguments.
-  static SECStatus ClientAuthHandler(void* arg,
-                                     PRFileDesc* socket,
-                                     CERTDistNames* ca_names,
-                                     CERTCertificate** result_certificate,
-                                     SECKEYPrivateKey** result_private_key);
-
-  // Called by NSS to determine if we can False Start.
-  // |arg| contains a pointer to the current SSLClientSocketNSS::Core.
-  static SECStatus CanFalseStartCallback(PRFileDesc* socket,
-                                         void* arg,
-                                         PRBool* can_false_start);
-
-  // Called by NSS each time a handshake completely finishes.
-  // |arg| contains a pointer to the current SSLClientSocketNSS::Core.
-  static void HandshakeCallback(PRFileDesc* socket, void* arg);
-
-  // Called once for each successful handshake. If the initial handshake false
-  // starts, it is called when it false starts and not when it completely
-  // finishes. is_initial is true if this is the initial handshake.
-  void HandshakeSucceeded(bool is_initial);
-
-  // Handles an NSS error generated while handshaking or performing IO.
-  // Returns a network error code mapped from the original NSS error.
-  int HandleNSSError(PRErrorCode error);
-
-  int DoHandshakeLoop(int last_io_result);
-  int DoReadLoop(int result);
-  int DoWriteLoop(int result);
-
-  int DoHandshake();
-  int DoGetDBCertComplete(int result);
-
-  int DoPayloadRead();
-  int DoPayloadWrite();
-
-  bool DoTransportIO();
-  int BufferRecv();
-  int BufferSend();
-
-  void OnRecvComplete(int result);
-  void OnSendComplete(int result);
-
-  void DoConnectCallback(int result);
-  void DoReadCallback(int result);
-  void DoWriteCallback(int result);
-
-  // Client channel ID handler.
-  static SECStatus ClientChannelIDHandler(
-      void* arg,
-      PRFileDesc* socket,
-      SECKEYPublicKey **out_public_key,
-      SECKEYPrivateKey **out_private_key);
-
-  // ImportChannelIDKeys is a helper function for turning a DER-encoded cert and
-  // key into a SECKEYPublicKey and SECKEYPrivateKey. Returns OK upon success
-  // and an error code otherwise.
-  // Requires |domain_bound_private_key_| and |domain_bound_cert_| to have been
-  // set by a call to ChannelIDService->GetChannelID. The caller
-  // takes ownership of the |*cert| and |*key|.
-  int ImportChannelIDKeys(SECKEYPublicKey** public_key, SECKEYPrivateKey** key);
-
-  // Updates the NSS and platform specific certificates.
-  void UpdateServerCert();
-  // Update the nss_handshake_state_ with the SignedCertificateTimestampList
-  // received in the handshake via a TLS extension.
-  void UpdateSignedCertTimestamps();
-  // Update the OCSP response cache with the stapled response received in the
-  // handshake, and update nss_handshake_state_ with
-  // the SignedCertificateTimestampList received in the stapled OCSP response.
-  void UpdateStapledOCSPResponse();
-  // Updates the nss_handshake_state_ with the negotiated security parameters.
-  void UpdateConnectionStatus();
-  // Record histograms for channel id support during full handshakes - resumed
-  // handshakes are ignored.
-  void RecordChannelIDSupportOnNSSTaskRunner();
-  // UpdateNextProto gets any application-layer protocol that may have been
-  // negotiated by the TLS connection.
-  void UpdateNextProto();
-  // Record TLS extension used for protocol negotiation (NPN or ALPN).
-  void UpdateExtensionUsed();
-
-  // Returns true if renegotiations are allowed.
-  bool IsRenegotiationAllowed() const;
-
-  ////////////////////////////////////////////////////////////////////////////
-  // Methods that are ONLY called on the network task runner:
-  ////////////////////////////////////////////////////////////////////////////
-  int DoBufferRecv(IOBuffer* buffer, int len);
-  int DoBufferSend(IOBuffer* buffer, int len);
-  int DoGetChannelID(const std::string& host);
-
-  void OnGetChannelIDComplete(int result);
-  void OnHandshakeStateUpdated(const HandshakeState& state);
-  void OnNSSBufferUpdated(int amount_in_read_buffer);
-  void DidNSSRead(int result);
-  void DidNSSWrite(int result);
-  void RecordChannelIDSupportOnNetworkTaskRunner(bool negotiated_channel_id,
-                                                 bool channel_id_enabled) const;
-
-  ////////////////////////////////////////////////////////////////////////////
-  // Methods that are called on both the network task runner and the NSS
-  // task runner.
-  ////////////////////////////////////////////////////////////////////////////
-  void OnHandshakeIOComplete(int result);
-  void BufferRecvComplete(IOBuffer* buffer, int result);
-  void BufferSendComplete(int result);
-
-  // PostOrRunCallback is a helper function to ensure that |callback| is
-  // invoked on the network task runner, but only if Detach() has not yet
-  // been called.
-  void PostOrRunCallback(const tracked_objects::Location& location,
-                         const base::Closure& callback);
-
-  // Uses PostOrRunCallback and |weak_net_log_| to try and log a
-  // SSL_CLIENT_CERT_PROVIDED event, with the indicated count.
-  void AddCertProvidedEvent(int cert_count);
-
-  // Sets the handshake state |channel_id_sent| flag and logs the
-  // SSL_CHANNEL_ID_PROVIDED event.
-  void SetChannelIDProvided();
-
-  ////////////////////////////////////////////////////////////////////////////
-  // Members that are ONLY accessed on the network task runner:
-  ////////////////////////////////////////////////////////////////////////////
-
-  // True if the owning SSLClientSocketNSS has called Detach(). No further
-  // callbacks will be invoked nor access to members owned by the network
-  // task runner.
-  bool detached_;
-
-  // The underlying transport to use for network IO.
-  ClientSocketHandle* transport_;
-  base::WeakPtrFactory<BoundNetLog> weak_net_log_factory_;
-
-  // The current handshake state. Mirrors |nss_handshake_state_|.
-  HandshakeState network_handshake_state_;
-
-  // The service for retrieving Channel ID keys.  May be NULL.
-  ChannelIDService* channel_id_service_;
-  ChannelIDService::Request channel_id_request_;
-
-  // The information about NSS task runner.
-  int unhandled_buffer_size_;
-  bool nss_waiting_read_;
-  bool nss_waiting_write_;
-  bool nss_is_closed_;
-
-  // Set when Read() or Write() successfully reads or writes data to or from the
-  // network.
-  bool was_ever_used_;
-
-  ////////////////////////////////////////////////////////////////////////////
-  // Members that are ONLY accessed on the NSS task runner:
-  ////////////////////////////////////////////////////////////////////////////
-  HostPortPair host_and_port_;
-  SSLConfig ssl_config_;
-
-  // NSS SSL socket.
-  PRFileDesc* nss_fd_;
-
-  // Buffers for the network end of the SSL state machine
-  memio_Private* nss_bufs_;
-
-  // Used by DoPayloadRead() when attempting to fill the caller's buffer with
-  // as much data as possible, without blocking.
-  // If DoPayloadRead() encounters an error after having read some data, stores
-  // the results to return on the *next* call to DoPayloadRead(). A value of
-  // kNoPendingReadResult indicates there is no pending result, otherwise 0
-  // indicates EOF and < 0 indicates an error.
-  int pending_read_result_;
-  // Contains the previously observed NSS error. Only valid when
-  // pending_read_result_ != kNoPendingReadResult.
-  PRErrorCode pending_read_nss_error_;
-
-  // The certificate chain, in DER form, that is expected to be received from
-  // the server.
-  std::vector<std::string> predicted_certs_;
-
-  State next_handshake_state_;
-
-  // True if channel ID extension was negotiated.
-  bool channel_id_xtn_negotiated_;
-  // True if the handshake state machine was interrupted for channel ID.
-  bool channel_id_needed_;
-  // True if the handshake state machine was interrupted for client auth.
-  bool client_auth_cert_needed_;
-  // True if NSS has False Started in the initial handshake, but the initial
-  // handshake has not yet completely finished..
-  bool false_started_;
-  // True if NSS has called HandshakeCallback.
-  bool handshake_callback_called_;
-
-  HandshakeState nss_handshake_state_;
-
-  bool transport_recv_busy_;
-  bool transport_recv_eof_;
-  bool transport_send_busy_;
-
-  // Used by Read function.
-  scoped_refptr<IOBuffer> user_read_buf_;
-  int user_read_buf_len_;
-
-  // Used by Write function.
-  scoped_refptr<IOBuffer> user_write_buf_;
-  int user_write_buf_len_;
-
-  CompletionCallback user_connect_callback_;
-  CompletionCallback user_read_callback_;
-  CompletionCallback user_write_callback_;
-
-  ////////////////////////////////////////////////////////////////////////////
-  // Members that are accessed on both the network task runner and the NSS
-  // task runner.
-  ////////////////////////////////////////////////////////////////////////////
-  scoped_refptr<base::SequencedTaskRunner> network_task_runner_;
-  scoped_refptr<base::SequencedTaskRunner> nss_task_runner_;
-
-  // Dereferenced only on the network task runner, but bound to tasks destined
-  // for the network task runner from the NSS task runner.
-  base::WeakPtr<BoundNetLog> weak_net_log_;
-
-  // Written on the network task runner by the |channel_id_service_|,
-  // prior to invoking OnHandshakeIOComplete.
-  // Read on the NSS task runner when once OnHandshakeIOComplete is invoked
-  // on the NSS task runner.
-  std::unique_ptr<crypto::ECPrivateKey> channel_id_key_;
-
-  DISALLOW_COPY_AND_ASSIGN(Core);
-};
-
-SSLClientSocketNSS::Core::Core(
-    base::SequencedTaskRunner* network_task_runner,
-    base::SequencedTaskRunner* nss_task_runner,
-    ClientSocketHandle* transport,
-    const HostPortPair& host_and_port,
-    const SSLConfig& ssl_config,
-    BoundNetLog* net_log,
-    ChannelIDService* channel_id_service)
-    : detached_(false),
-      transport_(transport),
-      weak_net_log_factory_(net_log),
-      channel_id_service_(channel_id_service),
-      unhandled_buffer_size_(0),
-      nss_waiting_read_(false),
-      nss_waiting_write_(false),
-      nss_is_closed_(false),
-      was_ever_used_(false),
-      host_and_port_(host_and_port),
-      ssl_config_(ssl_config),
-      nss_fd_(NULL),
-      nss_bufs_(NULL),
-      pending_read_result_(kNoPendingReadResult),
-      pending_read_nss_error_(0),
-      next_handshake_state_(STATE_NONE),
-      channel_id_xtn_negotiated_(false),
-      channel_id_needed_(false),
-      client_auth_cert_needed_(false),
-      false_started_(false),
-      handshake_callback_called_(false),
-      transport_recv_busy_(false),
-      transport_recv_eof_(false),
-      transport_send_busy_(false),
-      user_read_buf_len_(0),
-      user_write_buf_len_(0),
-      network_task_runner_(network_task_runner),
-      nss_task_runner_(nss_task_runner),
-      weak_net_log_(weak_net_log_factory_.GetWeakPtr()) {
-}
-
-SSLClientSocketNSS::Core::~Core() {
-  // TODO(wtc): Send SSL close_notify alert.
-  if (nss_fd_ != NULL) {
-    PR_Close(nss_fd_);
-    nss_fd_ = NULL;
-  }
-  nss_bufs_ = NULL;
-}
-
-bool SSLClientSocketNSS::Core::Init(PRFileDesc* socket,
-                                    memio_Private* buffers) {
-  DCHECK(OnNetworkTaskRunner());
-  DCHECK(!nss_fd_);
-  DCHECK(!nss_bufs_);
-
-  nss_fd_ = socket;
-  nss_bufs_ = buffers;
-
-  SECStatus rv = SECSuccess;
-
-  if (!ssl_config_.alpn_protos.empty()) {
-    NextProtoVector alpn_protos = ssl_config_.alpn_protos;
-    // TODO(bnc): Check ssl_config_.disabled_cipher_suites.
-    if (!IsTLSVersionAdequateForHTTP2(ssl_config_))
-      DisableHTTP2(&alpn_protos);
-    // |ssl_config_| has fallback protocol at the end of the list, but NSS
-    // expects fallback at the first place, thus protocols need to be reordered.
-    ReorderNextProtos(&alpn_protos);
-    // NSS only supports a single protocol vector to be used with ALPN and NPN.
-    // Because of this limitation, |alpn_prototos| will be used for both.
-    // However, it is possible to enable ALPN and NPN separately.
-    std::vector<uint8_t> wire_protos = SerializeNextProtos(alpn_protos);
-    rv = SSL_SetNextProtoNego(
-        nss_fd_, wire_protos.empty() ? NULL : &wire_protos[0],
-        wire_protos.size());
-    if (rv != SECSuccess)
-      LogFailedNSSFunction(*weak_net_log_, "SSL_SetNextProtoNego", "");
-    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_ALPN, PR_TRUE);
-    if (rv != SECSuccess)
-      LogFailedNSSFunction(*weak_net_log_, "SSL_OptionSet", "SSL_ENABLE_ALPN");
-    if (!ssl_config_.npn_protos.empty()) {
-      rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_NPN, PR_TRUE);
-      if (rv != SECSuccess)
-        LogFailedNSSFunction(*weak_net_log_, "SSL_OptionSet", "SSL_ENABLE_NPN");
-    }
-  }
-
-  rv = SSL_AuthCertificateHook(
-      nss_fd_, SSLClientSocketNSS::Core::OwnAuthCertHandler, this);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(*weak_net_log_, "SSL_AuthCertificateHook", "");
-    return false;
-  }
-
-  rv = SSL_GetClientAuthDataHook(
-      nss_fd_, SSLClientSocketNSS::Core::ClientAuthHandler, this);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(*weak_net_log_, "SSL_GetClientAuthDataHook", "");
-    return false;
-  }
-
-  if (IsChannelIDEnabled(ssl_config_, channel_id_service_)) {
-    rv = SSL_SetClientChannelIDCallback(
-        nss_fd_, SSLClientSocketNSS::Core::ClientChannelIDHandler, this);
-    if (rv != SECSuccess) {
-      LogFailedNSSFunction(
-          *weak_net_log_, "SSL_SetClientChannelIDCallback", "");
-    }
-  }
-
-  rv = SSL_SetCanFalseStartCallback(
-      nss_fd_, SSLClientSocketNSS::Core::CanFalseStartCallback, this);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(*weak_net_log_, "SSL_SetCanFalseStartCallback", "");
-    return false;
-  }
-
-  rv = SSL_HandshakeCallback(
-      nss_fd_, SSLClientSocketNSS::Core::HandshakeCallback, this);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(*weak_net_log_, "SSL_HandshakeCallback", "");
-    return false;
-  }
-
-  return true;
-}
-
-int SSLClientSocketNSS::Core::Connect(const CompletionCallback& callback) {
-  if (!OnNSSTaskRunner()) {
-    DCHECK(!detached_);
-    bool posted = nss_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(IgnoreResult(&Core::Connect), this, callback));
-    return posted ? ERR_IO_PENDING : ERR_ABORTED;
-  }
-
-  DCHECK(OnNSSTaskRunner());
-  DCHECK_EQ(STATE_NONE, next_handshake_state_);
-  DCHECK(user_read_callback_.is_null());
-  DCHECK(user_write_callback_.is_null());
-  DCHECK(user_connect_callback_.is_null());
-  DCHECK(!user_read_buf_.get());
-  DCHECK(!user_write_buf_.get());
-
-  next_handshake_state_ = STATE_HANDSHAKE;
-  int rv = DoHandshakeLoop(OK);
-  if (rv == ERR_IO_PENDING) {
-    user_connect_callback_ = callback;
-  } else if (rv > OK) {
-    rv = OK;
-  }
-  if (rv != ERR_IO_PENDING && !OnNetworkTaskRunner()) {
-    PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
-    return ERR_IO_PENDING;
-  }
-
-  return rv;
-}
-
-void SSLClientSocketNSS::Core::Detach() {
-  DCHECK(OnNetworkTaskRunner());
-
-  detached_ = true;
-  transport_ = NULL;
-  weak_net_log_factory_.InvalidateWeakPtrs();
-
-  network_handshake_state_.Reset();
-
-  channel_id_request_.Cancel();
-}
-
-int SSLClientSocketNSS::Core::Read(IOBuffer* buf, int buf_len,
-                                   const CompletionCallback& callback) {
-  if (!OnNSSTaskRunner()) {
-    DCHECK(OnNetworkTaskRunner());
-    DCHECK(!detached_);
-    DCHECK(transport_);
-    DCHECK(!nss_waiting_read_);
-
-    nss_waiting_read_ = true;
-    bool posted = nss_task_runner_->PostTask(
-        FROM_HERE, base::Bind(IgnoreResult(&Core::Read), this,
-                              base::RetainedRef(buf), buf_len, callback));
-    if (!posted) {
-      nss_is_closed_ = true;
-      nss_waiting_read_ = false;
-    }
-    return posted ? ERR_IO_PENDING : ERR_ABORTED;
-  }
-
-  DCHECK(OnNSSTaskRunner());
-  DCHECK(false_started_ || handshake_callback_called_);
-  DCHECK_EQ(STATE_NONE, next_handshake_state_);
-  DCHECK(user_read_callback_.is_null());
-  DCHECK(user_connect_callback_.is_null());
-  DCHECK(!user_read_buf_.get());
-  DCHECK(nss_bufs_);
-
-  user_read_buf_ = buf;
-  user_read_buf_len_ = buf_len;
-
-  int rv = DoReadLoop(OK);
-  if (rv == ERR_IO_PENDING) {
-    if (OnNetworkTaskRunner())
-      nss_waiting_read_ = true;
-    user_read_callback_ = callback;
-  } else {
-    user_read_buf_ = NULL;
-    user_read_buf_len_ = 0;
-
-    if (!OnNetworkTaskRunner()) {
-      PostOrRunCallback(FROM_HERE, base::Bind(&Core::DidNSSRead, this, rv));
-      PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
-      return ERR_IO_PENDING;
-    } else {
-      DCHECK(!nss_waiting_read_);
-      if (rv <= 0) {
-        nss_is_closed_ = true;
-      } else {
-        was_ever_used_ = true;
-      }
-    }
-  }
-
-  return rv;
-}
-
-int SSLClientSocketNSS::Core::Write(IOBuffer* buf, int buf_len,
-                                    const CompletionCallback& callback) {
-  if (!OnNSSTaskRunner()) {
-    DCHECK(OnNetworkTaskRunner());
-    DCHECK(!detached_);
-    DCHECK(transport_);
-    DCHECK(!nss_waiting_write_);
-
-    nss_waiting_write_ = true;
-    bool posted = nss_task_runner_->PostTask(
-        FROM_HERE, base::Bind(IgnoreResult(&Core::Write), this,
-                              base::RetainedRef(buf), buf_len, callback));
-    if (!posted) {
-      nss_is_closed_ = true;
-      nss_waiting_write_ = false;
-    }
-    return posted ? ERR_IO_PENDING : ERR_ABORTED;
-  }
-
-  DCHECK(OnNSSTaskRunner());
-  DCHECK(false_started_ || handshake_callback_called_);
-  DCHECK_EQ(STATE_NONE, next_handshake_state_);
-  DCHECK(user_write_callback_.is_null());
-  DCHECK(user_connect_callback_.is_null());
-  DCHECK(!user_write_buf_.get());
-  DCHECK(nss_bufs_);
-
-  user_write_buf_ = buf;
-  user_write_buf_len_ = buf_len;
-
-  int rv = DoWriteLoop(OK);
-  if (rv == ERR_IO_PENDING) {
-    if (OnNetworkTaskRunner())
-      nss_waiting_write_ = true;
-    user_write_callback_ = callback;
-  } else {
-    user_write_buf_ = NULL;
-    user_write_buf_len_ = 0;
-
-    if (!OnNetworkTaskRunner()) {
-      PostOrRunCallback(FROM_HERE, base::Bind(&Core::DidNSSWrite, this, rv));
-      PostOrRunCallback(FROM_HERE, base::Bind(callback, rv));
-      return ERR_IO_PENDING;
-    } else {
-      DCHECK(!nss_waiting_write_);
-      if (rv < 0) {
-        nss_is_closed_ = true;
-      } else if (rv > 0) {
-        was_ever_used_ = true;
-      }
-    }
-  }
-
-  return rv;
-}
-
-bool SSLClientSocketNSS::Core::IsConnected() const {
-  DCHECK(OnNetworkTaskRunner());
-  return !nss_is_closed_;
-}
-
-bool SSLClientSocketNSS::Core::HasPendingAsyncOperation() const {
-  DCHECK(OnNetworkTaskRunner());
-  return nss_waiting_read_ || nss_waiting_write_;
-}
-
-bool SSLClientSocketNSS::Core::HasUnhandledReceivedData() const {
-  DCHECK(OnNetworkTaskRunner());
-  return unhandled_buffer_size_ != 0;
-}
-
-bool SSLClientSocketNSS::Core::WasEverUsed() const {
-  DCHECK(OnNetworkTaskRunner());
-  return was_ever_used_;
-}
-
-void SSLClientSocketNSS::Core::CacheSessionIfNecessary() {
-  // TODO(rsleevi): This should occur on the NSS task runner, due to the use of
-  // nss_fd_. However, it happens on the network task runner in order to match
-  // the buggy behavior of ExportKeyingMaterial.
-  //
-  // Once http://crbug.com/330360 is fixed, this should be moved to an
-  // implementation that exclusively does this work on the NSS TaskRunner. This
-  // is "safe" because it is only called during the certificate verification
-  // state machine of the main socket, which is safe because no underlying
-  // transport IO will be occuring in that state, and NSS will not be blocking
-  // on any PKCS#11 related locks that might block the Network TaskRunner.
-  DCHECK(OnNetworkTaskRunner());
-
-  // Only cache the session if the connection was not False Started, because
-  // sessions should only be cached *after* the peer's Finished message is
-  // processed.
-  // In the case of False Start, the session will be cached once the
-  // HandshakeCallback is called, which signals the receipt and processing of
-  // the Finished message, and which will happen during a call to
-  // PR_Read/PR_Write.
-  if (!false_started_)
-    SSL_CacheSession(nss_fd_);
-}
-
-bool SSLClientSocketNSS::Core::OnNSSTaskRunner() const {
-  return nss_task_runner_->RunsTasksOnCurrentThread();
-}
-
-bool SSLClientSocketNSS::Core::OnNetworkTaskRunner() const {
-  return network_task_runner_->RunsTasksOnCurrentThread();
-}
-
-// static
-SECStatus SSLClientSocketNSS::Core::OwnAuthCertHandler(
-    void* arg,
-    PRFileDesc* socket,
-    PRBool checksig,
-    PRBool is_server) {
-  Core* core = reinterpret_cast<Core*>(arg);
-  if (core->handshake_callback_called_) {
-    // Disallow the server certificate to change in a renegotiation.
-    CERTCertificate* old_cert = core->nss_handshake_state_.server_cert_chain[0];
-    ScopedCERTCertificate new_cert(SSL_PeerCertificate(socket));
-    if (new_cert->derCert.len != old_cert->derCert.len ||
-        memcmp(new_cert->derCert.data, old_cert->derCert.data,
-               new_cert->derCert.len) != 0) {
-      // NSS doesn't have an error code that indicates the server certificate
-      // changed. Borrow SSL_ERROR_WRONG_CERTIFICATE (which NSS isn't using)
-      // for this purpose.
-      PORT_SetError(SSL_ERROR_WRONG_CERTIFICATE);
-      return SECFailure;
-    }
-  }
-
-  // Tell NSS to not verify the certificate.
-  return SECSuccess;
-}
-
-#if defined(OS_IOS)
-
-// static
-SECStatus SSLClientSocketNSS::Core::ClientAuthHandler(
-    void* arg,
-    PRFileDesc* socket,
-    CERTDistNames* ca_names,
-    CERTCertificate** result_certificate,
-    SECKEYPrivateKey** result_private_key) {
-  Core* core = reinterpret_cast<Core*>(arg);
-  DCHECK(core->OnNSSTaskRunner());
-
-  core->PostOrRunCallback(
-      FROM_HERE,
-      base::Bind(&AddLogEvent, core->weak_net_log_,
-                 NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED));
-
-  // TODO(droger): Support client auth on iOS. See http://crbug.com/145954).
-  LOG(WARNING) << "Client auth is not supported";
-
-  // Never send a certificate.
-  core->AddCertProvidedEvent(0);
-  return SECFailure;
-}
-
-#else   // !OS_IOS
-
-// static
-// Based on Mozilla's NSS_GetClientAuthData.
-SECStatus SSLClientSocketNSS::Core::ClientAuthHandler(
-    void* arg,
-    PRFileDesc* socket,
-    CERTDistNames* ca_names,
-    CERTCertificate** result_certificate,
-    SECKEYPrivateKey** result_private_key) {
-  Core* core = reinterpret_cast<Core*>(arg);
-  DCHECK(core->OnNSSTaskRunner());
-
-  core->PostOrRunCallback(
-      FROM_HERE,
-      base::Bind(&AddLogEvent, core->weak_net_log_,
-                 NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED));
-
-  // Regular client certificate requested.
-  core->client_auth_cert_needed_ = !core->ssl_config_.send_client_cert;
-  void* wincx  = SSL_RevealPinArg(socket);
-
-  if (core->ssl_config_.send_client_cert) {
-    // Second pass: a client certificate should have been selected.
-    if (core->ssl_config_.client_cert.get()) {
-      CERTCertificate* cert =
-          CERT_DupCertificate(core->ssl_config_.client_cert->os_cert_handle());
-      SECKEYPrivateKey* privkey = PK11_FindKeyByAnyCert(cert, wincx);
-      if (privkey) {
-        // TODO(jsorianopastor): We should wait for server certificate
-        // verification before sending our credentials.  See
-        // http://crbug.com/13934.
-        *result_certificate = cert;
-        *result_private_key = privkey;
-        // A cert_count of -1 means the number of certificates is unknown.
-        // NSS will construct the certificate chain.
-        core->AddCertProvidedEvent(-1);
-
-        return SECSuccess;
-      }
-      LOG(WARNING) << "Client cert found without private key";
-    }
-    // Send no client certificate.
-    core->AddCertProvidedEvent(0);
-    return SECFailure;
-  }
-
-  // First pass: client certificate is needed.
-  core->nss_handshake_state_.cert_authorities.clear();
-
-  // Retrieve the DER-encoded DistinguishedName of the cert issuers accepted by
-  // the server and save them in |cert_authorities|.
-  for (int i = 0; i < ca_names->nnames; i++) {
-    core->nss_handshake_state_.cert_authorities.push_back(std::string(
-        reinterpret_cast<const char*>(ca_names->names[i].data),
-        static_cast<size_t>(ca_names->names[i].len)));
-  }
-
-  // Update the network task runner's view of the handshake state now that
-  // server certificate request has been recorded.
-  core->PostOrRunCallback(
-      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, core,
-                            core->nss_handshake_state_));
-
-  // Tell NSS to suspend the client authentication.  We will then abort the
-  // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
-  return SECWouldBlock;
-}
-#endif  // OS_IOS
-
-// static
-SECStatus SSLClientSocketNSS::Core::CanFalseStartCallback(
-    PRFileDesc* socket,
-    void* arg,
-    PRBool* can_false_start) {
-  // If the server doesn't support NPN or ALPN, then we don't do False
-  // Start with it.
-  PRBool negotiated_extension;
-  SECStatus rv = SSL_HandshakeNegotiatedExtension(socket,
-                                                  ssl_app_layer_protocol_xtn,
-                                                  &negotiated_extension);
-  if (rv != SECSuccess || !negotiated_extension) {
-    rv = SSL_HandshakeNegotiatedExtension(socket,
-                                          ssl_next_proto_nego_xtn,
-                                          &negotiated_extension);
-  }
-  if (rv != SECSuccess || !negotiated_extension) {
-    *can_false_start = PR_FALSE;
-    return SECSuccess;
-  }
-
-  SSLChannelInfo channel_info;
-  SECStatus ok =
-      SSL_GetChannelInfo(socket, &channel_info, sizeof(channel_info));
-  if (ok != SECSuccess || channel_info.length != sizeof(channel_info) ||
-      channel_info.protocolVersion < SSL_LIBRARY_VERSION_TLS_1_2 ||
-      !IsSecureTLSCipherSuite(channel_info.cipherSuite)) {
-    *can_false_start = PR_FALSE;
-    return SECSuccess;
-  }
-
-  return SSL_RecommendedCanFalseStart(socket, can_false_start);
-}
-
-// static
-void SSLClientSocketNSS::Core::HandshakeCallback(
-    PRFileDesc* socket,
-    void* arg) {
-  Core* core = reinterpret_cast<Core*>(arg);
-  DCHECK(core->OnNSSTaskRunner());
-
-  bool is_initial = !core->handshake_callback_called_;
-  core->handshake_callback_called_ = true;
-  if (core->false_started_) {
-    core->false_started_ = false;
-    // If the connection was False Started, then at the time of this callback,
-    // the peer's certificate will have been verified or the caller will have
-    // accepted the error.
-    // This is guaranteed when using False Start because this callback will
-    // not be invoked until processing the peer's Finished message, which
-    // will only happen in a PR_Read/PR_Write call, which can only happen
-    // after the peer's certificate is verified.
-    SSL_CacheSessionUnlocked(socket);
-
-    // Additionally, when False Starting, DoHandshake() will have already
-    // called HandshakeSucceeded(), so return now.
-    return;
-  }
-  core->HandshakeSucceeded(is_initial);
-}
-
-void SSLClientSocketNSS::Core::HandshakeSucceeded(bool is_initial) {
-  DCHECK(OnNSSTaskRunner());
-
-  PRBool last_handshake_resumed;
-  SECStatus rv = SSL_HandshakeResumedSession(nss_fd_, &last_handshake_resumed);
-  if (rv == SECSuccess && last_handshake_resumed) {
-    nss_handshake_state_.resumed_handshake = true;
-  } else {
-    nss_handshake_state_.resumed_handshake = false;
-  }
-
-  RecordChannelIDSupportOnNSSTaskRunner();
-  UpdateServerCert();
-  UpdateSignedCertTimestamps();
-  UpdateStapledOCSPResponse();
-  UpdateConnectionStatus();
-  UpdateNextProto();
-  UpdateExtensionUsed();
-
-  if (is_initial && IsRenegotiationAllowed()) {
-    // For compatibility, do not enforce RFC 5746 support. Per section 4.1,
-    // enforcement falls largely on the server.
-    //
-    // This is done in a callback rather than after SSL_ForceHandshake returns
-    // because SSL_ForceHandshake will otherwise greedly consume renegotiations
-    // before returning if Finished and HelloRequest are in the same
-    // record.
-    //
-    // Note that SSL_OptionSet should only be called for an initial
-    // handshake. See https://crbug.com/125299.
-    SECStatus rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION,
-                                 SSL_RENEGOTIATE_TRANSITIONAL);
-    DCHECK_EQ(SECSuccess, rv);
-  }
-
-  // Update the network task runners view of the handshake state whenever
-  // a handshake has completed.
-  PostOrRunCallback(
-      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, this,
-                            nss_handshake_state_));
-}
-
-int SSLClientSocketNSS::Core::HandleNSSError(PRErrorCode nss_error) {
-  DCHECK(OnNSSTaskRunner());
-
-  return MapNSSClientError(nss_error);
-}
-
-int SSLClientSocketNSS::Core::DoHandshakeLoop(int last_io_result) {
-  DCHECK(OnNSSTaskRunner());
-
-  int rv = last_io_result;
-  do {
-    // Default to STATE_NONE for next state.
-    State state = next_handshake_state_;
-    GotoState(STATE_NONE);
-
-    switch (state) {
-      case STATE_HANDSHAKE:
-        rv = DoHandshake();
-        break;
-      case STATE_GET_DOMAIN_BOUND_CERT_COMPLETE:
-        rv = DoGetDBCertComplete(rv);
-        break;
-      case STATE_NONE:
-      default:
-        rv = ERR_UNEXPECTED;
-        LOG(DFATAL) << "unexpected state " << state;
-        break;
-    }
-
-    // Do the actual network I/O
-    bool network_moved = DoTransportIO();
-    if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
-      // In general we exit the loop if rv is ERR_IO_PENDING.  In this
-      // special case we keep looping even if rv is ERR_IO_PENDING because
-      // the transport IO may allow DoHandshake to make progress.
-      DCHECK(rv == OK || rv == ERR_IO_PENDING);
-      rv = OK;  // This causes us to stay in the loop.
-    }
-  } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
-  return rv;
-}
-
-int SSLClientSocketNSS::Core::DoReadLoop(int result) {
-  DCHECK(OnNSSTaskRunner());
-  DCHECK(false_started_ || handshake_callback_called_);
-  DCHECK_EQ(STATE_NONE, next_handshake_state_);
-
-  if (result < 0)
-    return result;
-
-  if (!nss_bufs_) {
-    LOG(DFATAL) << "!nss_bufs_";
-    int rv = ERR_UNEXPECTED;
-    PostOrRunCallback(
-        FROM_HERE,
-        base::Bind(&AddLogEventWithCallback, weak_net_log_,
-                   NetLog::TYPE_SSL_READ_ERROR,
-                   CreateNetLogSSLErrorCallback(rv, 0)));
-    return rv;
-  }
-
-  bool network_moved;
-  int rv;
-  do {
-    rv = DoPayloadRead();
-    network_moved = DoTransportIO();
-  } while (rv == ERR_IO_PENDING && network_moved);
-
-  return rv;
-}
-
-int SSLClientSocketNSS::Core::DoWriteLoop(int result) {
-  DCHECK(OnNSSTaskRunner());
-  DCHECK(false_started_ || handshake_callback_called_);
-  DCHECK_EQ(STATE_NONE, next_handshake_state_);
-
-  if (result < 0)
-    return result;
-
-  if (!nss_bufs_) {
-    LOG(DFATAL) << "!nss_bufs_";
-    int rv = ERR_UNEXPECTED;
-    PostOrRunCallback(
-        FROM_HERE,
-        base::Bind(&AddLogEventWithCallback, weak_net_log_,
-                   NetLog::TYPE_SSL_READ_ERROR,
-                   CreateNetLogSSLErrorCallback(rv, 0)));
-    return rv;
-  }
-
-  bool network_moved;
-  int rv;
-  do {
-    rv = DoPayloadWrite();
-    network_moved = DoTransportIO();
-  } while (rv == ERR_IO_PENDING && network_moved);
-
-  LeaveFunction(rv);
-  return rv;
-}
-
-int SSLClientSocketNSS::Core::DoHandshake() {
-  DCHECK(OnNSSTaskRunner());
-
-  int net_error = OK;
-  SECStatus rv = SSL_ForceHandshake(nss_fd_);
-
-  // Note: this function may be called multiple times during the handshake, so
-  // even though channel id and client auth are separate else cases, they can
-  // both be used during a single SSL handshake.
-  if (channel_id_needed_) {
-    GotoState(STATE_GET_DOMAIN_BOUND_CERT_COMPLETE);
-    net_error = ERR_IO_PENDING;
-  } else if (client_auth_cert_needed_) {
-    net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
-    PostOrRunCallback(
-        FROM_HERE,
-        base::Bind(&AddLogEventWithCallback, weak_net_log_,
-                   NetLog::TYPE_SSL_HANDSHAKE_ERROR,
-                   CreateNetLogSSLErrorCallback(net_error, 0)));
-  } else if (rv == SECSuccess) {
-    if (!handshake_callback_called_) {
-      false_started_ = true;
-      HandshakeSucceeded(true);
-    }
-  } else {
-    PRErrorCode prerr = PR_GetError();
-    net_error = HandleNSSError(prerr);
-
-    // If not done, stay in this state
-    if (net_error == ERR_IO_PENDING) {
-      GotoState(STATE_HANDSHAKE);
-    } else {
-      PostOrRunCallback(
-          FROM_HERE,
-          base::Bind(&AddLogEventWithCallback, weak_net_log_,
-                     NetLog::TYPE_SSL_HANDSHAKE_ERROR,
-                     CreateNetLogSSLErrorCallback(net_error, prerr)));
-    }
-  }
-
-  return net_error;
-}
-
-int SSLClientSocketNSS::Core::DoGetDBCertComplete(int result) {
-  SECStatus rv;
-  PostOrRunCallback(
-      FROM_HERE,
-      base::Bind(&BoundNetLog::EndEventWithNetErrorCode, weak_net_log_,
-                 NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT, result));
-
-  channel_id_needed_ = false;
-
-  if (result != OK)
-    return result;
-
-  SECKEYPublicKey* public_key;
-  SECKEYPrivateKey* private_key;
-  int error = ImportChannelIDKeys(&public_key, &private_key);
-  if (error != OK)
-    return error;
-
-  rv = SSL_RestartHandshakeAfterChannelIDReq(nss_fd_, public_key, private_key);
-  if (rv != SECSuccess)
-    return MapNSSError(PORT_GetError());
-
-  SetChannelIDProvided();
-  GotoState(STATE_HANDSHAKE);
-  return OK;
-}
-
-int SSLClientSocketNSS::Core::DoPayloadRead() {
-  DCHECK(OnNSSTaskRunner());
-  DCHECK(user_read_buf_.get());
-  DCHECK_GT(user_read_buf_len_, 0);
-
-  int rv;
-  // If a previous greedy read resulted in an error that was not consumed (eg:
-  // due to the caller having read some data successfully), then return that
-  // pending error now.
-  if (pending_read_result_ != kNoPendingReadResult) {
-    rv = pending_read_result_;
-    PRErrorCode prerr = pending_read_nss_error_;
-    pending_read_result_ = kNoPendingReadResult;
-    pending_read_nss_error_ = 0;
-
-    if (rv == 0) {
-      PostOrRunCallback(FROM_HERE,
-                        base::Bind(&LogByteTransferEvent, weak_net_log_,
-                                   NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
-                                   base::RetainedRef(user_read_buf_)));
-    } else {
-      PostOrRunCallback(
-          FROM_HERE,
-          base::Bind(&AddLogEventWithCallback, weak_net_log_,
-                     NetLog::TYPE_SSL_READ_ERROR,
-                     CreateNetLogSSLErrorCallback(rv, prerr)));
-    }
-    return rv;
-  }
-
-  // Perform a greedy read, attempting to read as much as the caller has
-  // requested. In the current NSS implementation, PR_Read will return
-  // exactly one SSL application data record's worth of data per invocation.
-  // The record size is dictated by the server, and may be noticeably smaller
-  // than the caller's buffer. This may be as little as a single byte, if the
-  // server is performing 1/n-1 record splitting.
-  //
-  // However, this greedy read may result in renegotiations/re-handshakes
-  // happening or may lead to some data being read, followed by an EOF (such as
-  // a TLS close-notify). If at least some data was read, then that result
-  // should be deferred until the next call to DoPayloadRead(). Otherwise, if no
-  // data was read, it's safe to return the error or EOF immediately.
-  int total_bytes_read = 0;
-  do {
-    rv = PR_Read(nss_fd_, user_read_buf_->data() + total_bytes_read,
-                 user_read_buf_len_ - total_bytes_read);
-    if (rv > 0)
-      total_bytes_read += rv;
-  } while (total_bytes_read < user_read_buf_len_ && rv > 0);
-  int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
-  PostOrRunCallback(FROM_HERE, base::Bind(&Core::OnNSSBufferUpdated, this,
-                                          amount_in_read_buffer));
-
-  if (total_bytes_read == user_read_buf_len_) {
-    // The caller's entire request was satisfied without error. No further
-    // processing needed.
-    rv = total_bytes_read;
-  } else {
-    // Otherwise, an error occurred (rv <= 0). The error needs to be handled
-    // immediately, while the NSPR/NSS errors are still available in
-    // thread-local storage. However, the handled/remapped error code should
-    // only be returned if no application data was already read; if it was, the
-    // error code should be deferred until the next call of DoPayloadRead.
-    //
-    // If no data was read, |*next_result| will point to the return value of
-    // this function. If at least some data was read, |*next_result| will point
-    // to |pending_read_error_|, to be returned in a future call to
-    // DoPayloadRead() (e.g.: after the current data is handled).
-    int* next_result = &rv;
-    if (total_bytes_read > 0) {
-      pending_read_result_ = rv;
-      rv = total_bytes_read;
-      next_result = &pending_read_result_;
-    }
-
-    if (client_auth_cert_needed_) {
-      *next_result = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
-      pending_read_nss_error_ = 0;
-    } else if (*next_result < 0) {
-      // If *next_result == 0, then that indicates EOF, and no special error
-      // handling is needed.
-      pending_read_nss_error_ = PR_GetError();
-      *next_result = HandleNSSError(pending_read_nss_error_);
-      if (rv > 0 && *next_result == ERR_IO_PENDING) {
-        // If at least some data was read from PR_Read(), do not treat
-        // insufficient data as an error to return in the next call to
-        // DoPayloadRead() - instead, let the call fall through to check
-        // PR_Read() again. This is because DoTransportIO() may complete
-        // in between the next call to DoPayloadRead(), and thus it is
-        // important to check PR_Read() on subsequent invocations to see
-        // if a complete record may now be read.
-        pending_read_nss_error_ = 0;
-        pending_read_result_ = kNoPendingReadResult;
-      }
-    }
-  }
-
-  DCHECK_NE(ERR_IO_PENDING, pending_read_result_);
-
-  if (rv >= 0) {
-    PostOrRunCallback(FROM_HERE,
-                      base::Bind(&LogByteTransferEvent, weak_net_log_,
-                                 NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
-                                 base::RetainedRef(user_read_buf_)));
-  } else if (rv != ERR_IO_PENDING) {
-    PostOrRunCallback(
-        FROM_HERE,
-        base::Bind(&AddLogEventWithCallback, weak_net_log_,
-                   NetLog::TYPE_SSL_READ_ERROR,
-                   CreateNetLogSSLErrorCallback(rv, pending_read_nss_error_)));
-    pending_read_nss_error_ = 0;
-  }
-  return rv;
-}
-
-int SSLClientSocketNSS::Core::DoPayloadWrite() {
-  DCHECK(OnNSSTaskRunner());
-
-  DCHECK(user_write_buf_.get());
-
-  int old_amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
-  int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
-  int new_amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
-  // PR_Write could potentially consume the unhandled data in the memio read
-  // buffer if a renegotiation is in progress. If the buffer is consumed,
-  // notify the latest buffer size to NetworkRunner.
-  if (old_amount_in_read_buffer != new_amount_in_read_buffer) {
-    PostOrRunCallback(
-        FROM_HERE,
-        base::Bind(&Core::OnNSSBufferUpdated, this, new_amount_in_read_buffer));
-  }
-  if (rv >= 0) {
-    PostOrRunCallback(FROM_HERE,
-                      base::Bind(&LogByteTransferEvent, weak_net_log_,
-                                 NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv,
-                                 base::RetainedRef(user_write_buf_)));
-    return rv;
-  }
-  PRErrorCode prerr = PR_GetError();
-  if (prerr == PR_WOULD_BLOCK_ERROR)
-    return ERR_IO_PENDING;
-
-  rv = HandleNSSError(prerr);
-  PostOrRunCallback(
-      FROM_HERE,
-      base::Bind(&AddLogEventWithCallback, weak_net_log_,
-                 NetLog::TYPE_SSL_WRITE_ERROR,
-                 CreateNetLogSSLErrorCallback(rv, prerr)));
-  return rv;
-}
-
-// Do as much network I/O as possible between the buffer and the
-// transport socket. Return true if some I/O performed, false
-// otherwise (error or ERR_IO_PENDING).
-bool SSLClientSocketNSS::Core::DoTransportIO() {
-  DCHECK(OnNSSTaskRunner());
-
-  bool network_moved = false;
-  if (nss_bufs_ != NULL) {
-    int rv;
-    // Read and write as much data as we can. The loop is neccessary
-    // because Write() may return synchronously.
-    do {
-      rv = BufferSend();
-      if (rv != ERR_IO_PENDING && rv != 0)
-        network_moved = true;
-    } while (rv > 0);
-    if (!transport_recv_eof_ && BufferRecv() != ERR_IO_PENDING)
-      network_moved = true;
-  }
-  return network_moved;
-}
-
-int SSLClientSocketNSS::Core::BufferRecv() {
-  DCHECK(OnNSSTaskRunner());
-
-  if (transport_recv_busy_)
-    return ERR_IO_PENDING;
-
-  // If NSS is blocked on reading from |nss_bufs_|, because it is empty,
-  // determine how much data NSS wants to read. If NSS was not blocked,
-  // this will return 0.
-  int requested = memio_GetReadRequest(nss_bufs_);
-  if (requested == 0) {
-    // This is not a perfect match of error codes, as no operation is
-    // actually pending. However, returning 0 would be interpreted as a
-    // possible sign of EOF, which is also an inappropriate match.
-    return ERR_IO_PENDING;
-  }
-
-  char* buf;
-  int nb = memio_GetReadParams(nss_bufs_, &buf);
-  int rv;
-  if (!nb) {
-    // buffer too full to read into, so no I/O possible at moment
-    rv = ERR_IO_PENDING;
-  } else {
-    scoped_refptr<IOBuffer> read_buffer(new IOBuffer(nb));
-    if (OnNetworkTaskRunner()) {
-      rv = DoBufferRecv(read_buffer.get(), nb);
-    } else {
-      bool posted = network_task_runner_->PostTask(
-          FROM_HERE, base::Bind(IgnoreResult(&Core::DoBufferRecv), this,
-                                base::RetainedRef(read_buffer), nb));
-      rv = posted ? ERR_IO_PENDING : ERR_ABORTED;
-    }
-
-    if (rv == ERR_IO_PENDING) {
-      transport_recv_busy_ = true;
-    } else {
-      if (rv > 0) {
-        memcpy(buf, read_buffer->data(), rv);
-      } else if (rv == 0) {
-        transport_recv_eof_ = true;
-      }
-      memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
-    }
-  }
-  return rv;
-}
-
-// Return 0 if nss_bufs_ was empty,
-// > 0 for bytes transferred immediately,
-// < 0 for error (or the non-error ERR_IO_PENDING).
-int SSLClientSocketNSS::Core::BufferSend() {
-  DCHECK(OnNSSTaskRunner());
-
-  if (transport_send_busy_)
-    return ERR_IO_PENDING;
-
-  const char* buf1;
-  const char* buf2;
-  unsigned int len1, len2;
-  if (memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2)) {
-    // It is important this return synchronously to prevent spinning infinitely
-    // in the off-thread NSS case. The error code itself is ignored, so just
-    // return ERR_ABORTED. See https://crbug.com/381160.
-    return ERR_ABORTED;
-  }
-  const size_t len = len1 + len2;
-
-  int rv = 0;
-  if (len) {
-    scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
-    memcpy(send_buffer->data(), buf1, len1);
-    memcpy(send_buffer->data() + len1, buf2, len2);
-
-    if (OnNetworkTaskRunner()) {
-      rv = DoBufferSend(send_buffer.get(), len);
-    } else {
-      bool posted = network_task_runner_->PostTask(
-          FROM_HERE, base::Bind(IgnoreResult(&Core::DoBufferSend), this,
-                                base::RetainedRef(send_buffer), len));
-      rv = posted ? ERR_IO_PENDING : ERR_ABORTED;
-    }
-
-    if (rv == ERR_IO_PENDING) {
-      transport_send_busy_ = true;
-    } else {
-      memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
-    }
-  }
-
-  return rv;
-}
-
-void SSLClientSocketNSS::Core::OnRecvComplete(int result) {
-  DCHECK(OnNSSTaskRunner());
-
-  if (next_handshake_state_ == STATE_HANDSHAKE) {
-    OnHandshakeIOComplete(result);
-    return;
-  }
-
-  // Network layer received some data, check if client requested to read
-  // decrypted data.
-  if (!user_read_buf_.get())
-    return;
-
-  int rv = DoReadLoop(result);
-  if (rv != ERR_IO_PENDING)
-    DoReadCallback(rv);
-}
-
-void SSLClientSocketNSS::Core::OnSendComplete(int result) {
-  DCHECK(OnNSSTaskRunner());
-
-  if (next_handshake_state_ == STATE_HANDSHAKE) {
-    OnHandshakeIOComplete(result);
-    return;
-  }
-
-  // OnSendComplete may need to call DoPayloadRead while the renegotiation
-  // handshake is in progress.
-  int rv_read = ERR_IO_PENDING;
-  int rv_write = ERR_IO_PENDING;
-  bool network_moved;
-  do {
-    if (user_read_buf_.get())
-      rv_read = DoPayloadRead();
-    if (user_write_buf_.get())
-      rv_write = DoPayloadWrite();
-    network_moved = DoTransportIO();
-  } while (rv_read == ERR_IO_PENDING && rv_write == ERR_IO_PENDING &&
-           (user_read_buf_.get() || user_write_buf_.get()) && network_moved);
-
-  // If the parent SSLClientSocketNSS is deleted during the processing of the
-  // Read callback and OnNSSTaskRunner() == OnNetworkTaskRunner(), then the Core
-  // will be detached (and possibly deleted). Guard against deletion by taking
-  // an extra reference, then check if the Core was detached before invoking the
-  // next callback.
-  scoped_refptr<Core> guard(this);
-  if (user_read_buf_.get() && rv_read != ERR_IO_PENDING)
-    DoReadCallback(rv_read);
-
-  if (OnNetworkTaskRunner() && detached_)
-    return;
-
-  if (user_write_buf_.get() && rv_write != ERR_IO_PENDING)
-    DoWriteCallback(rv_write);
-}
-
-// As part of Connect(), the SSLClientSocketNSS object performs an SSL
-// handshake. This requires network IO, which in turn calls
-// BufferRecvComplete() with a non-zero byte count. This byte count eventually
-// winds its way through the state machine and ends up being passed to the
-// callback. For Read() and Write(), that's what we want. But for Connect(),
-// the caller expects OK (i.e. 0) for success.
-void SSLClientSocketNSS::Core::DoConnectCallback(int rv) {
-  DCHECK(OnNSSTaskRunner());
-  DCHECK_NE(rv, ERR_IO_PENDING);
-  DCHECK(!user_connect_callback_.is_null());
-
-  base::Closure c = base::Bind(
-      base::ResetAndReturn(&user_connect_callback_),
-      rv > OK ? OK : rv);
-  PostOrRunCallback(FROM_HERE, c);
-}
-
-void SSLClientSocketNSS::Core::DoReadCallback(int rv) {
-  DCHECK(OnNSSTaskRunner());
-  DCHECK_NE(ERR_IO_PENDING, rv);
-  DCHECK(!user_read_callback_.is_null());
-
-  user_read_buf_ = NULL;
-  user_read_buf_len_ = 0;
-  int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
-  // This is used to curry the |amount_int_read_buffer| and |user_cb| back to
-  // the network task runner.
-  PostOrRunCallback(
-      FROM_HERE,
-      base::Bind(&Core::OnNSSBufferUpdated, this, amount_in_read_buffer));
-  PostOrRunCallback(
-      FROM_HERE,
-      base::Bind(&Core::DidNSSRead, this, rv));
-  PostOrRunCallback(
-      FROM_HERE,
-      base::Bind(base::ResetAndReturn(&user_read_callback_), rv));
-}
-
-void SSLClientSocketNSS::Core::DoWriteCallback(int rv) {
-  DCHECK(OnNSSTaskRunner());
-  DCHECK_NE(ERR_IO_PENDING, rv);
-  DCHECK(!user_write_callback_.is_null());
-
-  // Since Run may result in Write being called, clear |user_write_callback_|
-  // up front.
-  user_write_buf_ = NULL;
-  user_write_buf_len_ = 0;
-  // Update buffer status because DoWriteLoop called DoTransportIO which may
-  // perform read operations.
-  int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_);
-  // This is used to curry the |amount_int_read_buffer| and |user_cb| back to
-  // the network task runner.
-  PostOrRunCallback(
-      FROM_HERE,
-      base::Bind(&Core::OnNSSBufferUpdated, this, amount_in_read_buffer));
-  PostOrRunCallback(
-      FROM_HERE,
-      base::Bind(&Core::DidNSSWrite, this, rv));
-  PostOrRunCallback(
-      FROM_HERE,
-      base::Bind(base::ResetAndReturn(&user_write_callback_), rv));
-}
-
-SECStatus SSLClientSocketNSS::Core::ClientChannelIDHandler(
-    void* arg,
-    PRFileDesc* socket,
-    SECKEYPublicKey **out_public_key,
-    SECKEYPrivateKey **out_private_key) {
-  Core* core = reinterpret_cast<Core*>(arg);
-  DCHECK(core->OnNSSTaskRunner());
-
-  core->PostOrRunCallback(
-      FROM_HERE,
-      base::Bind(&AddLogEvent, core->weak_net_log_,
-                 NetLog::TYPE_SSL_CHANNEL_ID_REQUESTED));
-
-  // We have negotiated the TLS channel ID extension.
-  core->channel_id_xtn_negotiated_ = true;
-  std::string host = core->host_and_port_.host();
-  int error = ERR_UNEXPECTED;
-  if (core->OnNetworkTaskRunner()) {
-    error = core->DoGetChannelID(host);
-  } else {
-    bool posted = core->network_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(
-            IgnoreResult(&Core::DoGetChannelID),
-            core, host));
-    error = posted ? ERR_IO_PENDING : ERR_ABORTED;
-  }
-
-  if (error == ERR_IO_PENDING) {
-    // Asynchronous case.
-    core->channel_id_needed_ = true;
-    return SECWouldBlock;
-  }
-
-  core->PostOrRunCallback(
-      FROM_HERE,
-      base::Bind(&BoundNetLog::EndEventWithNetErrorCode, core->weak_net_log_,
-                 NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT, error));
-  SECStatus rv = SECSuccess;
-  if (error == OK) {
-    // Synchronous success.
-    int result = core->ImportChannelIDKeys(out_public_key, out_private_key);
-    if (result == OK)
-      core->SetChannelIDProvided();
-    else
-      rv = SECFailure;
-  } else {
-    rv = SECFailure;
-  }
-
-  return rv;
-}
-
-int SSLClientSocketNSS::Core::ImportChannelIDKeys(SECKEYPublicKey** public_key,
-                                                  SECKEYPrivateKey** key) {
-  if (!channel_id_key_)
-    return SECFailure;
-
-  *public_key = SECKEY_CopyPublicKey(channel_id_key_->public_key());
-  *key = SECKEY_CopyPrivateKey(channel_id_key_->key());
-
-  return OK;
-}
-
-void SSLClientSocketNSS::Core::UpdateServerCert() {
-  nss_handshake_state_.server_cert_chain.Reset(nss_fd_);
-  nss_handshake_state_.server_cert = X509Certificate::CreateFromDERCertChain(
-      nss_handshake_state_.server_cert_chain.AsStringPieceVector());
-  if (nss_handshake_state_.server_cert.get()) {
-    // Since this will be called asynchronously on another thread, it needs to
-    // own a reference to the certificate.
-    NetLog::ParametersCallback net_log_callback =
-        base::Bind(&NetLogX509CertificateCallback,
-                   base::RetainedRef(nss_handshake_state_.server_cert));
-    PostOrRunCallback(
-        FROM_HERE,
-        base::Bind(&AddLogEventWithCallback, weak_net_log_,
-                   NetLog::TYPE_SSL_CERTIFICATES_RECEIVED,
-                   net_log_callback));
-  }
-}
-
-void SSLClientSocketNSS::Core::UpdateSignedCertTimestamps() {
-  const SECItem* signed_cert_timestamps =
-      SSL_PeerSignedCertTimestamps(nss_fd_);
-
-  if (!signed_cert_timestamps || !signed_cert_timestamps->len)
-    return;
-
-  nss_handshake_state_.sct_list_from_tls_extension = std::string(
-      reinterpret_cast<char*>(signed_cert_timestamps->data),
-      signed_cert_timestamps->len);
-}
-
-void SSLClientSocketNSS::Core::UpdateStapledOCSPResponse() {
-  PRBool ocsp_requested = PR_FALSE;
-  SSL_OptionGet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, &ocsp_requested);
-  const SECItemArray* ocsp_responses =
-      SSL_PeerStapledOCSPResponses(nss_fd_);
-  bool ocsp_responses_present = ocsp_responses && ocsp_responses->len;
-  if (ocsp_requested)
-    UMA_HISTOGRAM_BOOLEAN("Net.OCSPResponseStapled", ocsp_responses_present);
-  if (!ocsp_responses_present)
-    return;
-
-  nss_handshake_state_.stapled_ocsp_response = std::string(
-      reinterpret_cast<char*>(ocsp_responses->items[0].data),
-      ocsp_responses->items[0].len);
-}
-
-void SSLClientSocketNSS::Core::UpdateConnectionStatus() {
-  // Note: This function may be called multiple times for a single connection
-  // if renegotiations occur.
-  nss_handshake_state_.ssl_connection_status = 0;
-
-  SSLChannelInfo channel_info;
-  SECStatus ok = SSL_GetChannelInfo(nss_fd_,
-                                    &channel_info, sizeof(channel_info));
-  if (ok == SECSuccess &&
-      channel_info.length == sizeof(channel_info) &&
-      channel_info.cipherSuite) {
-    nss_handshake_state_.ssl_connection_status |= channel_info.cipherSuite;
-
-    nss_handshake_state_.ssl_connection_status |=
-        (static_cast<int>(channel_info.compressionMethod) &
-         SSL_CONNECTION_COMPRESSION_MASK) <<
-        SSL_CONNECTION_COMPRESSION_SHIFT;
-
-    int version = SSL_CONNECTION_VERSION_UNKNOWN;
-    if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_TLS_1_0) {
-      version = SSL_CONNECTION_VERSION_TLS1;
-    } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_TLS_1_1) {
-      version = SSL_CONNECTION_VERSION_TLS1_1;
-    } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_TLS_1_2) {
-      version = SSL_CONNECTION_VERSION_TLS1_2;
-    }
-    DCHECK_NE(SSL_CONNECTION_VERSION_UNKNOWN, version);
-    nss_handshake_state_.ssl_connection_status |=
-        (version & SSL_CONNECTION_VERSION_MASK) <<
-        SSL_CONNECTION_VERSION_SHIFT;
-  }
-
-  PRBool peer_supports_renego_ext;
-  ok = SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn,
-                                        &peer_supports_renego_ext);
-  if (ok == SECSuccess) {
-    if (!peer_supports_renego_ext) {
-      nss_handshake_state_.ssl_connection_status |=
-          SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
-      // Log an informational message if the server does not support secure
-      // renegotiation (RFC 5746).
-      VLOG(1) << "The server " << host_and_port_.ToString()
-              << " does not support the TLS renegotiation_info extension.";
-    }
-  }
-
-  if (ssl_config_.version_fallback) {
-    nss_handshake_state_.ssl_connection_status |=
-        SSL_CONNECTION_VERSION_FALLBACK;
-  }
-}
-
-void SSLClientSocketNSS::Core::UpdateNextProto() {
-  uint8_t buf[256];
-  SSLNextProtoState state;
-  unsigned buf_len;
-
-  SECStatus rv = SSL_GetNextProto(nss_fd_, &state, buf, &buf_len, sizeof(buf));
-  if (rv != SECSuccess)
-    return;
-
-  nss_handshake_state_.next_proto =
-      std::string(reinterpret_cast<char*>(buf), buf_len);
-  switch (state) {
-    case SSL_NEXT_PROTO_NEGOTIATED:
-    case SSL_NEXT_PROTO_SELECTED:
-      nss_handshake_state_.next_proto_status = kNextProtoNegotiated;
-      break;
-    case SSL_NEXT_PROTO_NO_OVERLAP:
-      nss_handshake_state_.next_proto_status = kNextProtoNoOverlap;
-      break;
-    case SSL_NEXT_PROTO_NO_SUPPORT:
-      nss_handshake_state_.next_proto_status = kNextProtoUnsupported;
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
-}
-
-void SSLClientSocketNSS::Core::UpdateExtensionUsed() {
-  PRBool negotiated_extension;
-  SECStatus rv = SSL_HandshakeNegotiatedExtension(nss_fd_,
-                                                  ssl_app_layer_protocol_xtn,
-                                                  &negotiated_extension);
-  if (rv == SECSuccess && negotiated_extension) {
-    nss_handshake_state_.negotiation_extension_ = kExtensionALPN;
-  } else {
-    rv = SSL_HandshakeNegotiatedExtension(nss_fd_,
-                                          ssl_next_proto_nego_xtn,
-                                          &negotiated_extension);
-    if (rv == SECSuccess && negotiated_extension) {
-      nss_handshake_state_.negotiation_extension_ = kExtensionNPN;
-    }
-  }
-}
-
-bool SSLClientSocketNSS::Core::IsRenegotiationAllowed() const {
-  DCHECK(OnNSSTaskRunner());
-
-  if (nss_handshake_state_.next_proto_status == kNextProtoUnsupported)
-    return ssl_config_.renego_allowed_default;
-
-  NextProto next_proto = NextProtoFromString(nss_handshake_state_.next_proto);
-  for (NextProto allowed : ssl_config_.renego_allowed_for_protos) {
-    if (next_proto == allowed)
-      return true;
-  }
-  return false;
-}
-
-void SSLClientSocketNSS::Core::RecordChannelIDSupportOnNSSTaskRunner() {
-  DCHECK(OnNSSTaskRunner());
-  if (nss_handshake_state_.resumed_handshake)
-    return;
-
-  // Copy the NSS task runner-only state to the network task runner and
-  // log histograms from there, since the histograms also need access to the
-  // network task runner state.
-  PostOrRunCallback(
-      FROM_HERE,
-      base::Bind(&Core::RecordChannelIDSupportOnNetworkTaskRunner, this,
-                 channel_id_xtn_negotiated_, ssl_config_.channel_id_enabled));
-}
-
-void SSLClientSocketNSS::Core::RecordChannelIDSupportOnNetworkTaskRunner(
-    bool negotiated_channel_id,
-    bool channel_id_enabled) const {
-  DCHECK(OnNetworkTaskRunner());
-
-  RecordChannelIDSupport(channel_id_service_, negotiated_channel_id,
-                         channel_id_enabled);
-}
-
-int SSLClientSocketNSS::Core::DoBufferRecv(IOBuffer* read_buffer, int len) {
-  DCHECK(OnNetworkTaskRunner());
-  DCHECK_GT(len, 0);
-
-  if (detached_)
-    return ERR_ABORTED;
-
-  int rv = transport_->socket()->Read(
-      read_buffer, len,
-      base::Bind(&Core::BufferRecvComplete, base::Unretained(this),
-                 base::RetainedRef(read_buffer)));
-
-  if (!OnNSSTaskRunner() && rv != ERR_IO_PENDING) {
-    nss_task_runner_->PostTask(FROM_HERE,
-                               base::Bind(&Core::BufferRecvComplete, this,
-                                          base::RetainedRef(read_buffer), rv));
-    return rv;
-  }
-
-  return rv;
-}
-
-int SSLClientSocketNSS::Core::DoBufferSend(IOBuffer* send_buffer, int len) {
-  DCHECK(OnNetworkTaskRunner());
-  DCHECK_GT(len, 0);
-
-  if (detached_)
-    return ERR_ABORTED;
-
-  int rv = transport_->socket()->Write(
-      send_buffer, len,
-      base::Bind(&Core::BufferSendComplete,
-                 base::Unretained(this)));
-
-  if (!OnNSSTaskRunner() && rv != ERR_IO_PENDING) {
-    nss_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&Core::BufferSendComplete, this, rv));
-    return rv;
-  }
-
-  return rv;
-}
-
-int SSLClientSocketNSS::Core::DoGetChannelID(const std::string& host) {
-  DCHECK(OnNetworkTaskRunner());
-
-  if (detached_)
-    return ERR_ABORTED;
-
-  weak_net_log_->BeginEvent(NetLog::TYPE_SSL_GET_DOMAIN_BOUND_CERT);
-
-  int rv = channel_id_service_->GetOrCreateChannelID(
-      host, &channel_id_key_,
-      base::Bind(&Core::OnGetChannelIDComplete, base::Unretained(this)),
-      &channel_id_request_);
-
-  if (rv != ERR_IO_PENDING && !OnNSSTaskRunner()) {
-    nss_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&Core::OnHandshakeIOComplete, this, rv));
-    return ERR_IO_PENDING;
-  }
-
-  return rv;
-}
-
-void SSLClientSocketNSS::Core::OnHandshakeStateUpdated(
-    const HandshakeState& state) {
-  DCHECK(OnNetworkTaskRunner());
-  network_handshake_state_ = state;
-}
-
-void SSLClientSocketNSS::Core::OnNSSBufferUpdated(int amount_in_read_buffer) {
-  DCHECK(OnNetworkTaskRunner());
-  unhandled_buffer_size_ = amount_in_read_buffer;
-}
-
-void SSLClientSocketNSS::Core::DidNSSRead(int result) {
-  DCHECK(OnNetworkTaskRunner());
-  DCHECK(nss_waiting_read_);
-  nss_waiting_read_ = false;
-  if (result <= 0) {
-    nss_is_closed_ = true;
-  } else {
-    was_ever_used_ = true;
-  }
-}
-
-void SSLClientSocketNSS::Core::DidNSSWrite(int result) {
-  DCHECK(OnNetworkTaskRunner());
-  DCHECK(nss_waiting_write_);
-  nss_waiting_write_ = false;
-  if (result < 0) {
-    nss_is_closed_ = true;
-  } else if (result > 0) {
-    was_ever_used_ = true;
-  }
-}
-
-void SSLClientSocketNSS::Core::BufferSendComplete(int result) {
-  if (!OnNSSTaskRunner()) {
-    if (detached_)
-      return;
-
-    nss_task_runner_->PostTask(
-        FROM_HERE, base::Bind(&Core::BufferSendComplete, this, result));
-    return;
-  }
-
-  DCHECK(OnNSSTaskRunner());
-
-  memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
-  transport_send_busy_ = false;
-  OnSendComplete(result);
-}
-
-void SSLClientSocketNSS::Core::OnHandshakeIOComplete(int result) {
-  if (!OnNSSTaskRunner()) {
-    if (detached_)
-      return;
-
-    nss_task_runner_->PostTask(
-        FROM_HERE, base::Bind(&Core::OnHandshakeIOComplete, this, result));
-    return;
-  }
-
-  DCHECK(OnNSSTaskRunner());
-
-  int rv = DoHandshakeLoop(result);
-  if (rv != ERR_IO_PENDING)
-    DoConnectCallback(rv);
-}
-
-void SSLClientSocketNSS::Core::OnGetChannelIDComplete(int result) {
-  DVLOG(1) << __FUNCTION__ << " " << result;
-  DCHECK(OnNetworkTaskRunner());
-
-  OnHandshakeIOComplete(result);
-}
-
-void SSLClientSocketNSS::Core::BufferRecvComplete(
-    IOBuffer* read_buffer,
-    int result) {
-  DCHECK(read_buffer);
-
-  if (!OnNSSTaskRunner()) {
-    if (detached_)
-      return;
-
-    nss_task_runner_->PostTask(
-        FROM_HERE, base::Bind(&Core::BufferRecvComplete, this,
-                              base::RetainedRef(read_buffer), result));
-    return;
-  }
-
-  DCHECK(OnNSSTaskRunner());
-
-  if (result > 0) {
-    char* buf;
-    int nb = memio_GetReadParams(nss_bufs_, &buf);
-    CHECK_GE(nb, result);
-    memcpy(buf, read_buffer->data(), result);
-  } else if (result == 0) {
-    transport_recv_eof_ = true;
-  }
-
-  memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
-  transport_recv_busy_ = false;
-  OnRecvComplete(result);
-}
-
-void SSLClientSocketNSS::Core::PostOrRunCallback(
-    const tracked_objects::Location& location,
-    const base::Closure& task) {
-  if (!OnNetworkTaskRunner()) {
-    network_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&Core::PostOrRunCallback, this, location, task));
-    return;
-  }
-
-  if (detached_ || task.is_null())
-    return;
-  task.Run();
-}
-
-void SSLClientSocketNSS::Core::AddCertProvidedEvent(int cert_count) {
-  PostOrRunCallback(FROM_HERE,
-                    base::Bind(&AddLogEventWithCallback, weak_net_log_,
-                               NetLog::TYPE_SSL_CLIENT_CERT_PROVIDED,
-                               NetLog::IntCallback("cert_count", cert_count)));
-}
-
-void SSLClientSocketNSS::Core::SetChannelIDProvided() {
-  PostOrRunCallback(
-      FROM_HERE, base::Bind(&AddLogEvent, weak_net_log_,
-                            NetLog::TYPE_SSL_CHANNEL_ID_PROVIDED));
-  nss_handshake_state_.channel_id_sent = true;
-  // Update the network task runner's view of the handshake state now that
-  // channel id has been sent.
-  PostOrRunCallback(
-      FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, this,
-                            nss_handshake_state_));
-}
-
-SSLClientSocketNSS::SSLClientSocketNSS(
-    std::unique_ptr<ClientSocketHandle> transport_socket,
-    const HostPortPair& host_and_port,
-    const SSLConfig& ssl_config,
-    const SSLClientSocketContext& context)
-    : transport_(std::move(transport_socket)),
-      host_and_port_(host_and_port),
-      ssl_config_(ssl_config),
-      cert_verifier_(context.cert_verifier),
-      cert_transparency_verifier_(context.cert_transparency_verifier),
-      channel_id_service_(context.channel_id_service),
-      ssl_session_cache_shard_(context.ssl_session_cache_shard),
-      completed_handshake_(false),
-      next_handshake_state_(STATE_NONE),
-      disconnected_(false),
-      nss_fd_(NULL),
-      net_log_(transport_->socket()->NetLog()),
-      transport_security_state_(context.transport_security_state),
-      policy_enforcer_(context.ct_policy_enforcer),
-      valid_thread_id_(base::kInvalidThreadId) {
-  DCHECK(cert_verifier_);
-
-  EnterFunction("");
-  InitCore();
-  LeaveFunction("");
-}
-
-SSLClientSocketNSS::~SSLClientSocketNSS() {
-  EnterFunction("");
-  Disconnect();
-  LeaveFunction("");
-}
-
-// static
-void SSLClientSocket::ClearSessionCache() {
-  // SSL_ClearSessionCache can't be called before NSS is initialized.  Don't
-  // bother initializing NSS just to clear an empty SSL session cache.
-  if (!NSS_IsInitialized())
-    return;
-
-  SSL_ClearSessionCache();
-}
-
-bool SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
-  EnterFunction("");
-  ssl_info->Reset();
-  if (core_->state().server_cert_chain.empty() ||
-      !core_->state().server_cert_chain[0]) {
-    return false;
-  }
-
-  ssl_info->cert_status = server_cert_verify_result_.cert_status;
-  ssl_info->cert = server_cert_verify_result_.verified_cert;
-  ssl_info->unverified_cert = core_->state().server_cert;
-
-  AddCTInfoToSSLInfo(ssl_info);
-
-  ssl_info->connection_status =
-      core_->state().ssl_connection_status;
-  ssl_info->public_key_hashes = server_cert_verify_result_.public_key_hashes;
-  ssl_info->is_issued_by_known_root =
-      server_cert_verify_result_.is_issued_by_known_root;
-  ssl_info->client_cert_sent =
-      ssl_config_.send_client_cert && ssl_config_.client_cert.get();
-  ssl_info->channel_id_sent = core_->state().channel_id_sent;
-  ssl_info->pinning_failure_log = pinning_failure_log_;
-
-  PRUint16 cipher_suite = SSLConnectionStatusToCipherSuite(
-      core_->state().ssl_connection_status);
-  SSLCipherSuiteInfo cipher_info;
-  SECStatus ok = SSL_GetCipherSuiteInfo(cipher_suite,
-                                        &cipher_info, sizeof(cipher_info));
-  if (ok == SECSuccess) {
-    ssl_info->security_bits = cipher_info.effectiveKeyBits;
-  } else {
-    ssl_info->security_bits = -1;
-    LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError()
-                << " for cipherSuite " << cipher_suite;
-  }
-
-  ssl_info->handshake_type = core_->state().resumed_handshake ?
-      SSLInfo::HANDSHAKE_RESUME : SSLInfo::HANDSHAKE_FULL;
-
-  LeaveFunction("");
-  return true;
-}
-
-void SSLClientSocketNSS::GetConnectionAttempts(ConnectionAttempts* out) const {
-  out->clear();
-}
-
-int64_t SSLClientSocketNSS::GetTotalReceivedBytes() const {
-  NOTIMPLEMENTED();
-  return 0;
-}
-
-void SSLClientSocketNSS::GetSSLCertRequestInfo(
-    SSLCertRequestInfo* cert_request_info) {
-  EnterFunction("");
-  cert_request_info->host_and_port = host_and_port_;
-  cert_request_info->cert_authorities = core_->state().cert_authorities;
-  LeaveFunction("");
-}
-
-int SSLClientSocketNSS::ExportKeyingMaterial(const base::StringPiece& label,
-                                             bool has_context,
-                                             const base::StringPiece& context,
-                                             unsigned char* out,
-                                             unsigned int outlen) {
-  if (!IsConnected())
-    return ERR_SOCKET_NOT_CONNECTED;
-
-  // SSL_ExportKeyingMaterial may block the current thread if |core_| is in
-  // the midst of a handshake.
-  SECStatus result = SSL_ExportKeyingMaterial(
-      nss_fd_, label.data(), label.size(), has_context,
-      reinterpret_cast<const unsigned char*>(context.data()),
-      context.length(), out, outlen);
-  if (result != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_ExportKeyingMaterial", "");
-    return MapNSSError(PORT_GetError());
-  }
-  return OK;
-}
-
-SSLClientSocket::NextProtoStatus SSLClientSocketNSS::GetNextProto(
-    std::string* proto) const {
-  *proto = core_->state().next_proto;
-  return core_->state().next_proto_status;
-}
-
-int SSLClientSocketNSS::Connect(const CompletionCallback& callback) {
-  EnterFunction("");
-  DCHECK(transport_.get());
-  // It is an error to create an SSLClientSocket whose context has no
-  // TransportSecurityState.
-  DCHECK(transport_security_state_);
-  DCHECK_EQ(STATE_NONE, next_handshake_state_);
-  DCHECK(user_connect_callback_.is_null());
-  DCHECK(!callback.is_null());
-
-  // Although StreamSocket does allow calling Connect() after Disconnect(),
-  // this has never worked for layered sockets. CHECK to detect any consumers
-  // reconnecting an SSL socket.
-  //
-  // TODO(davidben,mmenke): Remove this API feature. See
-  // https://crbug.com/499289.
-  CHECK(!disconnected_);
-
-  EnsureThreadIdAssigned();
-
-  net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT);
-
-  int rv = Init();
-  if (rv != OK) {
-    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
-    return rv;
-  }
-
-  rv = InitializeSSLOptions();
-  if (rv != OK) {
-    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
-    return rv;
-  }
-
-  rv = InitializeSSLPeerName();
-  if (rv != OK) {
-    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
-    return rv;
-  }
-
-  GotoState(STATE_HANDSHAKE);
-
-  rv = DoHandshakeLoop(OK);
-  if (rv == ERR_IO_PENDING) {
-    user_connect_callback_ = callback;
-  } else {
-    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
-  }
-
-  LeaveFunction("");
-  return rv > OK ? OK : rv;
-}
-
-void SSLClientSocketNSS::Disconnect() {
-  EnterFunction("");
-
-  CHECK(CalledOnValidThread());
-
-  // Shut down anything that may call us back.
-  core_->Detach();
-  cert_verifier_request_.reset();
-  transport_->socket()->Disconnect();
-
-  disconnected_ = true;
-
-  // Reset object state.
-  user_connect_callback_.Reset();
-  server_cert_verify_result_.Reset();
-  completed_handshake_   = false;
-  start_cert_verification_time_ = base::TimeTicks();
-  InitCore();
-
-  LeaveFunction("");
-}
-
-bool SSLClientSocketNSS::IsConnected() const {
-  EnterFunction("");
-  bool ret = completed_handshake_ &&
-             (core_->HasPendingAsyncOperation() ||
-              (core_->IsConnected() && core_->HasUnhandledReceivedData()) ||
-              transport_->socket()->IsConnected());
-  LeaveFunction("");
-  return ret;
-}
-
-bool SSLClientSocketNSS::IsConnectedAndIdle() const {
-  EnterFunction("");
-  bool ret = completed_handshake_ &&
-             !core_->HasPendingAsyncOperation() &&
-             !(core_->IsConnected() && core_->HasUnhandledReceivedData()) &&
-             transport_->socket()->IsConnectedAndIdle();
-  LeaveFunction("");
-  return ret;
-}
-
-int SSLClientSocketNSS::GetPeerAddress(IPEndPoint* address) const {
-  return transport_->socket()->GetPeerAddress(address);
-}
-
-int SSLClientSocketNSS::GetLocalAddress(IPEndPoint* address) const {
-  return transport_->socket()->GetLocalAddress(address);
-}
-
-const BoundNetLog& SSLClientSocketNSS::NetLog() const {
-  return net_log_;
-}
-
-void SSLClientSocketNSS::SetSubresourceSpeculation() {
-  if (transport_.get() && transport_->socket()) {
-    transport_->socket()->SetSubresourceSpeculation();
-  } else {
-    NOTREACHED();
-  }
-}
-
-void SSLClientSocketNSS::SetOmniboxSpeculation() {
-  if (transport_.get() && transport_->socket()) {
-    transport_->socket()->SetOmniboxSpeculation();
-  } else {
-    NOTREACHED();
-  }
-}
-
-bool SSLClientSocketNSS::WasEverUsed() const {
-  DCHECK(core_.get());
-
-  return core_->WasEverUsed();
-}
-
-int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len,
-                             const CompletionCallback& callback) {
-  DCHECK(core_.get());
-  DCHECK(!callback.is_null());
-
-  EnterFunction(buf_len);
-  int rv = core_->Read(buf, buf_len, callback);
-  LeaveFunction(rv);
-
-  return rv;
-}
-
-int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len,
-                              const CompletionCallback& callback) {
-  DCHECK(core_.get());
-  DCHECK(!callback.is_null());
-
-  EnterFunction(buf_len);
-  int rv = core_->Write(buf, buf_len, callback);
-  LeaveFunction(rv);
-
-  return rv;
-}
-
-int SSLClientSocketNSS::SetReceiveBufferSize(int32_t size) {
-  return transport_->socket()->SetReceiveBufferSize(size);
-}
-
-int SSLClientSocketNSS::SetSendBufferSize(int32_t size) {
-  return transport_->socket()->SetSendBufferSize(size);
-}
-
-int SSLClientSocketNSS::Init() {
-  EnterFunction("");
-  // Initialize the NSS SSL library in a threadsafe way.  This also
-  // initializes the NSS base library.
-  EnsureNSSSSLInit();
-  if (!NSS_IsInitialized())
-    return ERR_UNEXPECTED;
-#if defined(USE_NSS_VERIFIER)
-  if (ssl_config_.cert_io_enabled) {
-    // We must call EnsureNSSHttpIOInit() here, on the IO thread, to get the IO
-    // loop by MessageLoopForIO::current().
-    // X509Certificate::Verify() runs on a worker thread of CertVerifier.
-    EnsureNSSHttpIOInit();
-  }
-#endif
-
-  LeaveFunction("");
-  return OK;
-}
-
-void SSLClientSocketNSS::InitCore() {
-  // TODO(davidben): Both task runners are now always the same. Unwind this code
-  // further, although the entire class is due to be deleted eventually, so it
-  // may not be worth bothering.
-  core_ = new Core(base::ThreadTaskRunnerHandle::Get().get(),
-                   base::ThreadTaskRunnerHandle::Get().get(), transport_.get(),
-                   host_and_port_, ssl_config_, &net_log_, channel_id_service_);
-}
-
-int SSLClientSocketNSS::InitializeSSLOptions() {
-  // Transport connected, now hook it up to nss
-  nss_fd_ = memio_CreateIOLayer(kRecvBufferSize, kSendBufferSize);
-  if (nss_fd_ == NULL) {
-    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR error code.
-  }
-
-  // Grab pointer to buffers
-  memio_Private* nss_bufs = memio_GetSecret(nss_fd_);
-
-  /* Create SSL state machine */
-  /* Push SSL onto our fake I/O socket */
-  if (SSL_ImportFD(GetNSSModelSocket(), nss_fd_) == NULL) {
-    LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
-    PR_Close(nss_fd_);
-    nss_fd_ = NULL;
-    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR/NSS error code.
-  }
-  // TODO(port): set more ssl options!  Check errors!
-
-  int rv;
-
-  rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
-    return ERR_UNEXPECTED;
-  }
-
-  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
-    return ERR_UNEXPECTED;
-  }
-
-  // Don't do V2 compatible hellos because they don't support TLS extensions.
-  rv = SSL_OptionSet(nss_fd_, SSL_V2_COMPATIBLE_HELLO, PR_FALSE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_V2_COMPATIBLE_HELLO");
-    return ERR_UNEXPECTED;
-  }
-
-  SSLVersionRange version_range;
-  version_range.min = ssl_config_.version_min;
-  version_range.max = ssl_config_.version_max;
-  rv = SSL_VersionRangeSet(nss_fd_, &version_range);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", "");
-    return ERR_NO_SSL_VERSIONS_ENABLED;
-  }
-
-  if (ssl_config_.require_ecdhe) {
-    const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers();
-    const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers();
-
-    // Iterate over the cipher suites and disable those that don't use ECDHE.
-    for (unsigned i = 0; i < num_ciphers; i++) {
-      SSLCipherSuiteInfo info;
-      if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info, sizeof(info)) ==
-          SECSuccess) {
-        if (strcmp(info.keaTypeName, "ECDHE") != 0) {
-          SSL_CipherPrefSet(nss_fd_, ssl_ciphers[i], PR_FALSE);
-        }
-      }
-    }
-  }
-
-  if (ssl_config_.version_fallback) {
-    rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALLBACK_SCSV, PR_TRUE);
-    if (rv != SECSuccess) {
-      LogFailedNSSFunction(
-          net_log_, "SSL_OptionSet", "SSL_ENABLE_FALLBACK_SCSV");
-    }
-  }
-
-  for (std::vector<uint16_t>::const_iterator it =
-           ssl_config_.disabled_cipher_suites.begin();
-       it != ssl_config_.disabled_cipher_suites.end(); ++it) {
-    // This will fail if the specified cipher is not implemented by NSS, but
-    // the failure is harmless.
-    SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
-  }
-
-  const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers();
-  const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers();
-  for (int i = 0; i < num_ciphers; i++) {
-    SSLCipherSuiteInfo info;
-    if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info, sizeof(info)) !=
-        SECSuccess) {
-      continue;
-    }
-    if (info.symCipher == ssl_calg_rc4 &&
-        !(ssl_config_.rc4_enabled &&
-          ssl_config_.deprecated_cipher_suites_enabled)) {
-      SSL_CipherPrefSet(nss_fd_, ssl_ciphers[i], PR_FALSE);
-    }
-    if (info.keaType == ssl_kea_dh &&
-        !ssl_config_.deprecated_cipher_suites_enabled) {
-      // Only offer DHE on the second handshake. https://crbug.com/538690
-      SSL_CipherPrefSet(nss_fd_, ssl_ciphers[i], PR_FALSE);
-    }
-  }
-
-  // Support RFC 5077
-  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(
-        net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
-  }
-
-  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALSE_START,
-                     ssl_config_.false_start_enabled);
-  if (rv != SECSuccess)
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_FALSE_START");
-
-  // By default, renegotiations are rejected. After the initial handshake
-  // completes, some application protocols may re-enable it.
-  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_NEVER);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(
-        net_log_, "SSL_OptionSet", "SSL_ENABLE_RENEGOTIATION");
-  }
-
-  rv = SSL_OptionSet(nss_fd_, SSL_CBC_RANDOM_IV, PR_TRUE);
-  if (rv != SECSuccess)
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_CBC_RANDOM_IV");
-
-// Added in NSS 3.15
-#ifdef SSL_ENABLE_OCSP_STAPLING
-  // Request OCSP stapling even on platforms that don't support it, in
-  // order to extract Certificate Transparency information.
-  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING,
-                     cert_verifier_->SupportsOCSPStapling() ||
-                         ssl_config_.signed_cert_timestamps_enabled);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet",
-                         "SSL_ENABLE_OCSP_STAPLING");
-  }
-#endif
-
-  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
-                     ssl_config_.signed_cert_timestamps_enabled);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet",
-                         "SSL_ENABLE_SIGNED_CERT_TIMESTAMPS");
-  }
-
-  rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
-    return ERR_UNEXPECTED;
-  }
-
-  if (!core_->Init(nss_fd_, nss_bufs))
-    return ERR_UNEXPECTED;
-
-  // Tell SSL the hostname we're trying to connect to.
-  SSL_SetURL(nss_fd_, host_and_port_.host().c_str());
-
-  // Tell SSL we're a client; needed if not letting NSPR do socket I/O
-  SSL_ResetHandshake(nss_fd_, PR_FALSE);
-
-  return OK;
-}
-
-int SSLClientSocketNSS::InitializeSSLPeerName() {
-  // Tell NSS who we're connected to
-  IPEndPoint peer_address;
-  int err = transport_->socket()->GetPeerAddress(&peer_address);
-  if (err != OK)
-    return err;
-
-  SockaddrStorage storage;
-  if (!peer_address.ToSockAddr(storage.addr, &storage.addr_len))
-    return ERR_ADDRESS_INVALID;
-
-  PRNetAddr peername;
-  memset(&peername, 0, sizeof(peername));
-  DCHECK_LE(static_cast<size_t>(storage.addr_len), sizeof(peername));
-  size_t len = std::min(static_cast<size_t>(storage.addr_len),
-                        sizeof(peername));
-  memcpy(&peername, storage.addr, len);
-
-  // Adjust the address family field for BSD, whose sockaddr
-  // structure has a one-byte length and one-byte address family
-  // field at the beginning.  PRNetAddr has a two-byte address
-  // family field at the beginning.
-  peername.raw.family = storage.addr->sa_family;
-
-  memio_SetPeerName(nss_fd_, &peername);
-
-  // Set the peer ID for session reuse.  This is necessary when we create an
-  // SSL tunnel through a proxy -- GetPeerName returns the proxy's address
-  // rather than the destination server's address in that case.
-  std::string peer_id = host_and_port_.ToString();
-  // Append |ssl_session_cache_shard_| to the peer id. This is used to partition
-  // the session cache for incognito mode.
-  peer_id += "/" + ssl_session_cache_shard_;
-  peer_id += "/";
-  // Shard the session cache based on maximum protocol version. This causes
-  // fallback connections to use a separate session cache.
-  switch (ssl_config_.version_max) {
-    case SSL_PROTOCOL_VERSION_TLS1:
-      peer_id += "tls1";
-      break;
-    case SSL_PROTOCOL_VERSION_TLS1_1:
-      peer_id += "tls1.1";
-      break;
-    case SSL_PROTOCOL_VERSION_TLS1_2:
-      peer_id += "tls1.2";
-      break;
-    default:
-      NOTREACHED();
-  }
-  peer_id += "/";
-  if (ssl_config_.deprecated_cipher_suites_enabled)
-    peer_id += "deprecated";
-
-  peer_id += "/";
-  if (ssl_config_.channel_id_enabled)
-    peer_id += "channelid";
-
-  SECStatus rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str()));
-  if (rv != SECSuccess)
-    LogFailedNSSFunction(net_log_, "SSL_SetSockPeerID", peer_id.c_str());
-
-  return OK;
-}
-
-void SSLClientSocketNSS::DoConnectCallback(int rv) {
-  EnterFunction(rv);
-  DCHECK_NE(ERR_IO_PENDING, rv);
-  DCHECK(!user_connect_callback_.is_null());
-
-  base::ResetAndReturn(&user_connect_callback_).Run(rv > OK ? OK : rv);
-  LeaveFunction("");
-}
-
-void SSLClientSocketNSS::OnHandshakeIOComplete(int result) {
-  EnterFunction(result);
-  int rv = DoHandshakeLoop(result);
-  if (rv != ERR_IO_PENDING) {
-    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
-    DoConnectCallback(rv);
-  }
-  LeaveFunction("");
-}
-
-int SSLClientSocketNSS::DoHandshakeLoop(int last_io_result) {
-  EnterFunction(last_io_result);
-  int rv = last_io_result;
-  do {
-    // Default to STATE_NONE for next state.
-    // (This is a quirk carried over from the windows
-    // implementation.  It makes reading the logs a bit harder.)
-    // State handlers can and often do call GotoState just
-    // to stay in the current state.
-    State state = next_handshake_state_;
-    GotoState(STATE_NONE);
-    switch (state) {
-      case STATE_HANDSHAKE:
-        rv = DoHandshake();
-        break;
-      case STATE_HANDSHAKE_COMPLETE:
-        rv = DoHandshakeComplete(rv);
-        break;
-      case STATE_VERIFY_CERT:
-        DCHECK(rv == OK);
-        rv = DoVerifyCert(rv);
-        break;
-      case STATE_VERIFY_CERT_COMPLETE:
-        rv = DoVerifyCertComplete(rv);
-        break;
-      case STATE_NONE:
-      default:
-        rv = ERR_UNEXPECTED;
-        LOG(DFATAL) << "unexpected state " << state;
-        break;
-    }
-  } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
-  LeaveFunction("");
-  return rv;
-}
-
-int SSLClientSocketNSS::DoHandshake() {
-  EnterFunction("");
-
-  int rv = core_->Connect(
-      base::Bind(&SSLClientSocketNSS::OnHandshakeIOComplete,
-                 base::Unretained(this)));
-  GotoState(STATE_HANDSHAKE_COMPLETE);
-
-  LeaveFunction(rv);
-  return rv;
-}
-
-int SSLClientSocketNSS::DoHandshakeComplete(int result) {
-  EnterFunction(result);
-
-  if (result == OK) {
-    if (ssl_config_.version_fallback &&
-        ssl_config_.version_max < ssl_config_.version_fallback_min) {
-      return ERR_SSL_FALLBACK_BEYOND_MINIMUM_VERSION;
-    }
-
-    RecordNegotiationExtension();
-
-    // SSL handshake is completed. Let's verify the certificate.
-    GotoState(STATE_VERIFY_CERT);
-    // Done!
-  }
-  set_signed_cert_timestamps_received(
-      !core_->state().sct_list_from_tls_extension.empty());
-  set_stapled_ocsp_response_received(
-      !core_->state().stapled_ocsp_response.empty());
-  set_negotiation_extension(core_->state().negotiation_extension_);
-
-  LeaveFunction(result);
-  return result;
-}
-
-int SSLClientSocketNSS::DoVerifyCert(int result) {
-  DCHECK(!core_->state().server_cert_chain.empty());
-  DCHECK(core_->state().server_cert_chain[0]);
-
-  GotoState(STATE_VERIFY_CERT_COMPLETE);
-
-  // NSS decoded the certificate, but the platform certificate implementation
-  // could not. This is treated as a fatal SSL-level protocol error rather than
-  // a certificate error. See https://crbug.com/91341.
-  if (!core_->state().server_cert.get())
-    return ERR_SSL_SERVER_CERT_BAD_FORMAT;
-
-  // If the certificate is expected to be bad we can use the expectation as
-  // the cert status.
-  base::StringPiece der_cert(
-      reinterpret_cast<char*>(
-          core_->state().server_cert_chain[0]->derCert.data),
-      core_->state().server_cert_chain[0]->derCert.len);
-  CertStatus cert_status;
-  if (ssl_config_.IsAllowedBadCert(der_cert, &cert_status)) {
-    DCHECK(start_cert_verification_time_.is_null());
-    VLOG(1) << "Received an expected bad cert with status: " << cert_status;
-    server_cert_verify_result_.Reset();
-    server_cert_verify_result_.cert_status = cert_status;
-    server_cert_verify_result_.verified_cert = core_->state().server_cert;
-    return OK;
-  }
-
-  start_cert_verification_time_ = base::TimeTicks::Now();
-
-  return cert_verifier_->Verify(
-      core_->state().server_cert.get(), host_and_port_.host(),
-      core_->state().stapled_ocsp_response, ssl_config_.GetCertVerifyFlags(),
-      SSLConfigService::GetCRLSet().get(), &server_cert_verify_result_,
-      base::Bind(&SSLClientSocketNSS::OnHandshakeIOComplete,
-                 base::Unretained(this)),
-      &cert_verifier_request_, net_log_);
-}
-
-// Derived from AuthCertificateCallback() in
-// mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp.
-int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
-  cert_verifier_request_.reset();
-
-  if (!start_cert_verification_time_.is_null()) {
-    base::TimeDelta verify_time =
-        base::TimeTicks::Now() - start_cert_verification_time_;
-    if (result == OK)
-        UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTime", verify_time);
-    else
-        UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTimeError", verify_time);
-  }
-
-  // We used to remember the intermediate CA certs in the NSS database
-  // persistently.  However, NSS opens a connection to the SQLite database
-  // during NSS initialization and doesn't close the connection until NSS
-  // shuts down.  If the file system where the database resides is gone,
-  // the database connection goes bad.  What's worse, the connection won't
-  // recover when the file system comes back.  Until this NSS or SQLite bug
-  // is fixed, we need to  avoid using the NSS database for non-essential
-  // purposes.  See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and
-  // http://crbug.com/15630 for more info.
-
-  const CertStatus cert_status = server_cert_verify_result_.cert_status;
-  if (transport_security_state_ &&
-      (result == OK ||
-       (IsCertificateError(result) && IsCertStatusMinorError(cert_status))) &&
-      !transport_security_state_->CheckPublicKeyPins(
-          host_and_port_, server_cert_verify_result_.is_issued_by_known_root,
-          server_cert_verify_result_.public_key_hashes,
-          core_->state().server_cert.get(),
-          server_cert_verify_result_.verified_cert.get(),
-          TransportSecurityState::ENABLE_PIN_REPORTS, &pinning_failure_log_)) {
-    result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
-  }
-
-  if (result == OK) {
-    // Only check Certificate Transparency if there were no other errors with
-    // the connection.
-    VerifyCT();
-
-    // Only cache the session if the certificate verified successfully.
-    core_->CacheSessionIfNecessary();
-  }
-
-  completed_handshake_ = true;
-
-  // Exit DoHandshakeLoop and return the result to the caller to Connect.
-  DCHECK_EQ(STATE_NONE, next_handshake_state_);
-  return result;
-}
-
-void SSLClientSocketNSS::VerifyCT() {
-  if (!cert_transparency_verifier_)
-    return;
-
-  // Note that this is a completely synchronous operation: The CT Log Verifier
-  // gets all the data it needs for SCT verification and does not do any
-  // external communication.
-  cert_transparency_verifier_->Verify(
-      server_cert_verify_result_.verified_cert.get(),
-      core_->state().stapled_ocsp_response,
-      core_->state().sct_list_from_tls_extension, &ct_verify_result_, net_log_);
-  // TODO(ekasper): wipe stapled_ocsp_response and sct_list_from_tls_extension
-  // from the state after verification is complete, to conserve memory.
-
-  ct_verify_result_.ct_policies_applied = (policy_enforcer_ != nullptr);
-  ct_verify_result_.ev_policy_compliance =
-      ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
-  if (policy_enforcer_) {
-    if ((server_cert_verify_result_.cert_status & CERT_STATUS_IS_EV)) {
-      scoped_refptr<ct::EVCertsWhitelist> ev_whitelist =
-          SSLConfigService::GetEVCertsWhitelist();
-      ct::EVPolicyCompliance ev_policy_compliance =
-          policy_enforcer_->DoesConformToCTEVPolicy(
-              server_cert_verify_result_.verified_cert.get(),
-              ev_whitelist.get(), ct_verify_result_.verified_scts, net_log_);
-      ct_verify_result_.ev_policy_compliance = ev_policy_compliance;
-      if (ev_policy_compliance !=
-              ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY &&
-          ev_policy_compliance !=
-              ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST &&
-          ev_policy_compliance !=
-              ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS) {
-        // TODO(eranm): Log via the BoundNetLog, see crbug.com/437766
-        VLOG(1) << "EV certificate for "
-                << server_cert_verify_result_.verified_cert->subject()
-                       .GetDisplayName()
-                << " does not conform to CT policy, removing EV status.";
-        server_cert_verify_result_.cert_status |=
-            CERT_STATUS_CT_COMPLIANCE_FAILED;
-        server_cert_verify_result_.cert_status &= ~CERT_STATUS_IS_EV;
-      }
-    }
-    ct_verify_result_.cert_policy_compliance =
-        policy_enforcer_->DoesConformToCertPolicy(
-            server_cert_verify_result_.verified_cert.get(),
-            ct_verify_result_.verified_scts, net_log_);
-  }
-}
-
-void SSLClientSocketNSS::EnsureThreadIdAssigned() const {
-  base::AutoLock auto_lock(lock_);
-  if (valid_thread_id_ != base::kInvalidThreadId)
-    return;
-  valid_thread_id_ = base::PlatformThread::CurrentId();
-}
-
-bool SSLClientSocketNSS::CalledOnValidThread() const {
-  EnsureThreadIdAssigned();
-  base::AutoLock auto_lock(lock_);
-  return valid_thread_id_ == base::PlatformThread::CurrentId();
-}
-
-void SSLClientSocketNSS::AddCTInfoToSSLInfo(SSLInfo* ssl_info) const {
-  ssl_info->UpdateCertificateTransparencyInfo(ct_verify_result_);
-}
-
-// static
-void SSLClientSocketNSS::ReorderNextProtos(NextProtoVector* next_protos) {
-  if (next_protos->size() < 2) {
-    return;
-  }
-
-  NextProto fallback_proto = next_protos->back();
-  for (size_t i = next_protos->size() - 1; i > 0; --i) {
-    (*next_protos)[i] = (*next_protos)[i - 1];
-  }
-  (*next_protos)[0] = fallback_proto;
-}
-
-ChannelIDService* SSLClientSocketNSS::GetChannelIDService() const {
-  return channel_id_service_;
-}
-
-Error SSLClientSocketNSS::GetSignedEKMForTokenBinding(
-    crypto::ECPrivateKey* key,
-    std::vector<uint8_t>* out) {
-  NOTREACHED();
-  return ERR_NOT_IMPLEMENTED;
-}
-
-crypto::ECPrivateKey* SSLClientSocketNSS::GetChannelIDKey() const {
-  return core_->GetChannelIDKey();
-}
-
-SSLFailureState SSLClientSocketNSS::GetSSLFailureState() const {
-  if (completed_handshake_)
-    return SSL_FAILURE_NONE;
-  return SSL_FAILURE_UNKNOWN;
-}
-
-}  // namespace net
diff --git a/net/socket/ssl_client_socket_nss.h b/net/socket/ssl_client_socket_nss.h
deleted file mode 100644
index c96fc41..0000000
--- a/net/socket/ssl_client_socket_nss.h
+++ /dev/null
@@ -1,218 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_SOCKET_SSL_CLIENT_SOCKET_NSS_H_
-#define NET_SOCKET_SSL_CLIENT_SOCKET_NSS_H_
-
-#include <certt.h>
-#include <keyt.h>
-#include <nspr.h>
-#include <nss.h>
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/synchronization/lock.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "net/base/completion_callback.h"
-#include "net/base/host_port_pair.h"
-#include "net/base/net_export.h"
-#include "net/base/nss_memio.h"
-#include "net/cert/cert_verifier.h"
-#include "net/cert/cert_verify_result.h"
-#include "net/cert/ct_verify_result.h"
-#include "net/cert/x509_certificate.h"
-#include "net/log/net_log.h"
-#include "net/socket/ssl_client_socket.h"
-#include "net/ssl/channel_id_service.h"
-#include "net/ssl/ssl_config_service.h"
-
-namespace net {
-
-class BoundNetLog;
-class CTPolicyEnforcer;
-class CertVerifier;
-class ChannelIDService;
-class CTVerifier;
-class ClientSocketHandle;
-class TransportSecurityState;
-class X509Certificate;
-
-// An SSL client socket implemented with Mozilla NSS.
-class SSLClientSocketNSS : public SSLClientSocket {
- public:
-  // Takes ownership of the |transport_socket|, which must already be connected.
-  // The hostname specified in |host_and_port| will be compared with the name(s)
-  // in the server's certificate during the SSL handshake.  If SSL client
-  // authentication is requested, the host_and_port field of SSLCertRequestInfo
-  // will be populated with |host_and_port|.  |ssl_config| specifies
-  // the SSL settings.
-  SSLClientSocketNSS(std::unique_ptr<ClientSocketHandle> transport_socket,
-                     const HostPortPair& host_and_port,
-                     const SSLConfig& ssl_config,
-                     const SSLClientSocketContext& context);
-  ~SSLClientSocketNSS() override;
-
-  // SSLClientSocket implementation.
-  void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
-  NextProtoStatus GetNextProto(std::string* proto) const override;
-
-  // SSLSocket implementation.
-  int ExportKeyingMaterial(const base::StringPiece& label,
-                           bool has_context,
-                           const base::StringPiece& context,
-                           unsigned char* out,
-                           unsigned int outlen) override;
-
-  // StreamSocket implementation.
-  int Connect(const CompletionCallback& callback) override;
-  void Disconnect() override;
-  bool IsConnected() const override;
-  bool IsConnectedAndIdle() const override;
-  int GetPeerAddress(IPEndPoint* address) const override;
-  int GetLocalAddress(IPEndPoint* address) const override;
-  const BoundNetLog& NetLog() const override;
-  void SetSubresourceSpeculation() override;
-  void SetOmniboxSpeculation() override;
-  bool WasEverUsed() const override;
-  bool GetSSLInfo(SSLInfo* ssl_info) override;
-  void GetConnectionAttempts(ConnectionAttempts* out) const override;
-  void ClearConnectionAttempts() override {}
-  void AddConnectionAttempts(const ConnectionAttempts& attempts) override {}
-  int64_t GetTotalReceivedBytes() const override;
-
-  // Socket implementation.
-  int Read(IOBuffer* buf,
-           int buf_len,
-           const CompletionCallback& callback) override;
-  int Write(IOBuffer* buf,
-            int buf_len,
-            const CompletionCallback& callback) override;
-  int SetReceiveBufferSize(int32_t size) override;
-  int SetSendBufferSize(int32_t size) override;
-
-  // SSLClientSocket implementation.
-  ChannelIDService* GetChannelIDService() const override;
-  Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
-                                    std::vector<uint8_t>* out) override;
-  crypto::ECPrivateKey* GetChannelIDKey() const override;
-  SSLFailureState GetSSLFailureState() const override;
-
- private:
-  // Helper class to handle marshalling any NSS interaction to and from the
-  // NSS and network task runners. Not every call needs to happen on the Core
-  class Core;
-
-  enum State {
-    STATE_NONE,
-    STATE_HANDSHAKE,
-    STATE_HANDSHAKE_COMPLETE,
-    STATE_VERIFY_CERT,
-    STATE_VERIFY_CERT_COMPLETE,
-  };
-
-  int Init();
-  void InitCore();
-
-  // Initializes NSS SSL options.  Returns a net error code.
-  int InitializeSSLOptions();
-
-  // Initializes the socket peer name in SSL.  Returns a net error code.
-  int InitializeSSLPeerName();
-
-  void DoConnectCallback(int result);
-  void OnHandshakeIOComplete(int result);
-
-  int DoHandshakeLoop(int last_io_result);
-  int DoHandshake();
-  int DoHandshakeComplete(int result);
-  int DoVerifyCert(int result);
-  int DoVerifyCertComplete(int result);
-
-  void VerifyCT();
-
-  // The following methods are for debugging bug 65948. Will remove this code
-  // after fixing bug 65948.
-  void EnsureThreadIdAssigned() const;
-  bool CalledOnValidThread() const;
-
-  // Adds the SignedCertificateTimestamps from ct_verify_result_ to |ssl_info|.
-  // SCTs are held in three separate vectors in ct_verify_result, each
-  // vetor representing a particular verification state, this method associates
-  // each of the SCTs with the corresponding SCTVerifyStatus as it adds it to
-  // the |ssl_info|.signed_certificate_timestamps list.
-  void AddCTInfoToSSLInfo(SSLInfo* ssl_info) const;
-
-  // Move last protocol to first place: SSLConfig::next_protos has protocols in
-  // decreasing order of preference with NPN fallback protocol at the end, but
-  // NSS moves the first one to the last place before sending them in ALPN, and
-  // uses the first one as a fallback for NPN.
-  static void ReorderNextProtos(NextProtoVector* next_protos);
-
-  std::unique_ptr<ClientSocketHandle> transport_;
-  HostPortPair host_and_port_;
-  SSLConfig ssl_config_;
-
-  scoped_refptr<Core> core_;
-
-  CompletionCallback user_connect_callback_;
-
-  CertVerifyResult server_cert_verify_result_;
-
-  CertVerifier* const cert_verifier_;
-  std::unique_ptr<CertVerifier::Request> cert_verifier_request_;
-
-  // Certificate Transparency: Verifier and result holder.
-  ct::CTVerifyResult ct_verify_result_;
-  CTVerifier* cert_transparency_verifier_;
-
-  // The service for retrieving Channel ID keys.  May be NULL.
-  ChannelIDService* channel_id_service_;
-
-  // ssl_session_cache_shard_ is an opaque string that partitions the SSL
-  // session cache. i.e. sessions created with one value will not attempt to
-  // resume on the socket with a different value.
-  const std::string ssl_session_cache_shard_;
-
-  // True if the SSL handshake has been completed.
-  bool completed_handshake_;
-
-  State next_handshake_state_;
-
-  // True if the socket has been disconnected.
-  bool disconnected_;
-
-  // The NSS SSL state machine. This is owned by |core_|.
-  // TODO(rsleevi): http://crbug.com/130616 - Remove this member once
-  // ExportKeyingMaterial is updated to be asynchronous.
-  PRFileDesc* nss_fd_;
-
-  BoundNetLog net_log_;
-
-  base::TimeTicks start_cert_verification_time_;
-
-  TransportSecurityState* transport_security_state_;
-
-  CTPolicyEnforcer* const policy_enforcer_;
-
-  // pinning_failure_log contains a message produced by
-  // TransportSecurityState::CheckPublicKeyPins in the event of a
-  // pinning failure. It is a (somewhat) human-readable string.
-  std::string pinning_failure_log_;
-
-  // The following two variables are added for debugging bug 65948. Will
-  // remove this code after fixing bug 65948.
-  // Added the following code Debugging in release mode.
-  mutable base::Lock lock_;
-  // This is mutable so that CalledOnValidThread can set it.
-  // It's guarded by |lock_|.
-  mutable base::PlatformThreadId valid_thread_id_;
-};
-
-}  // namespace net
-
-#endif  // NET_SOCKET_SSL_CLIENT_SOCKET_NSS_H_
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc
index 03e33ad3e..228e689 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -59,7 +59,7 @@
 #include "net/ssl/ssl_key_logger.h"
 #endif
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
 #include "net/cert_net/nss_ocsp.h"
 #endif
 
@@ -396,7 +396,7 @@
   // this will behave as if Reset(NULL) was called.
   void Reset(STACK_OF(X509)* chain);
 
-  // Note that when USE_OPENSSL is defined, OSCertHandle is X509*
+  // Note that when USE_OPENSSL_CERTS is defined, OSCertHandle is X509*
   scoped_refptr<X509Certificate> AsOSChain() const;
 
   size_t size() const {
@@ -877,7 +877,7 @@
   DCHECK(!ssl_);
   DCHECK(!transport_bio_);
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
   if (ssl_config_.cert_io_enabled) {
     // TODO(davidben): Move this out of SSLClientSocket. See
     // https://crbug.com/539520.
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index b3088999..63884f4 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -4,8 +4,15 @@
 
 #include "net/socket/ssl_client_socket.h"
 
+#include <errno.h>
+#include <string.h>
+
 #include <utility>
 
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+
 #include "base/callback_helpers.h"
 #include "base/files/file_util.h"
 #include "base/location.h"
@@ -15,6 +22,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "crypto/scoped_openssl_types.h"
 #include "net/base/address_list.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
@@ -45,23 +53,13 @@
 #include "net/ssl/ssl_config_service.h"
 #include "net/ssl/ssl_connection_status_flags.h"
 #include "net/ssl/ssl_info.h"
+#include "net/ssl/test_ssl_private_key.h"
 #include "net/test/cert_test_util.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
-#if defined(USE_OPENSSL)
-#include <errno.h>
-#include <openssl/bio.h>
-#include <openssl/evp.h>
-#include <openssl/pem.h>
-#include <string.h>
-
-#include "crypto/scoped_openssl_types.h"
-#include "net/ssl/test_ssl_private_key.h"
-#endif
-
 using testing::_;
 using testing::Return;
 using testing::Truly;
@@ -1503,35 +1501,6 @@
   ASSERT_EQ(ERR_IO_PENDING, rv);
   ASSERT_FALSE(read_callback.have_result());
 
-#if !defined(USE_OPENSSL)
-  // NSS follows a pattern where a call to PR_Write will only consume as
-  // much data as it can encode into application data records before the
-  // internal memio buffer is full, which should only fill if writing a large
-  // amount of data and the underlying transport is blocked. Once this happens,
-  // NSS will return (total size of all application data records it wrote) - 1,
-  // with the caller expected to resume with the remaining unsent data.
-  //
-  // This causes SSLClientSocketNSS::Write to return that it wrote some data
-  // before it will return ERR_IO_PENDING, so make an extra call to Write() to
-  // get the socket in the state needed for the test below.
-  //
-  // This is not needed for OpenSSL, because for OpenSSL,
-  // SSL_MODE_ENABLE_PARTIAL_WRITE is not specified - thus
-  // SSLClientSocketOpenSSL::Write() will not return until all of
-  // |request_buffer| has been written to the underlying BIO (although not
-  // necessarily the underlying transport).
-  rv = callback.GetResult(raw_sock->Write(request_buffer.get(),
-                                          request_buffer->BytesRemaining(),
-                                          callback.callback()));
-  ASSERT_LT(0, rv);
-  request_buffer->DidConsume(rv);
-
-  // Guard to ensure that |request_buffer| was larger than all of the internal
-  // buffers (transport, memio, NSS) along the way - otherwise the next call
-  // to Write() will crash with an invalid buffer.
-  ASSERT_LT(0, request_buffer->BytesRemaining());
-#endif
-
   // Attempt to write the remaining data. NSS will not be able to consume the
   // application data because the internal buffers are full, while OpenSSL will
   // return that its blocked because the underlying transport is blocked.
@@ -1641,15 +1610,8 @@
   raw_transport->UnblockReadResult();
   rv = read_callback.WaitForResult();
 
-#if defined(USE_OPENSSL)
   // Should still read bytes despite the write error.
   EXPECT_LT(0, rv);
-#else
-  // NSS attempts to flush the write buffer in PR_Read on an SSL socket before
-  // pumping the read state machine, unless configured with SSL_ENABLE_FDX, so
-  // the write error stops future reads.
-  EXPECT_EQ(ERR_CONNECTION_RESET, rv);
-#endif
 }
 
 // Tests that SSLClientSocket fails the handshake if the underlying
@@ -2273,8 +2235,6 @@
       request_info->cert_authorities[1]);
 }
 
-// cert_key_types is currently only populated on OpenSSL.
-#if defined(USE_OPENSSL)
 TEST_F(SSLClientSocketCertRequestInfoTest, CertKeyTypes) {
   SpawnedTestServer::SSLOptions ssl_options;
   ssl_options.request_client_certificate = true;
@@ -2286,7 +2246,6 @@
   EXPECT_EQ(CLIENT_CERT_RSA_SIGN, request_info->cert_key_types[0]);
   EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, request_info->cert_key_types[1]);
 }
-#endif  // defined(USE_OPENSSL)
 
 TEST_F(SSLClientSocketTest, ConnectSignedCertTimestampsEnabledTLSExtension) {
   SpawnedTestServer::SSLOptions ssl_options;
@@ -2839,9 +2798,6 @@
       SpawnedTestServer::SSLOptions::BULK_CIPHER_AES128GCM;
   server_options.npn_protocols.push_back(std::string("http/1.1"));
   SSLConfig client_config;
-#if !defined(USE_OPENSSL)
-  client_config.alpn_protos.push_back(kProtoHTTP11);
-#endif
   client_config.npn_protos.push_back(kProtoHTTP11);
   ASSERT_NO_FATAL_FAILURE(
       TestFalseStart(server_options, client_config, true));
@@ -2870,9 +2826,6 @@
       SpawnedTestServer::SSLOptions::BULK_CIPHER_AES128GCM;
   server_options.npn_protocols.push_back(std::string("http/1.1"));
   SSLConfig client_config;
-#if !defined(USE_OPENSSL)
-  client_config.alpn_protos.push_back(kProtoHTTP11);
-#endif
   client_config.npn_protos.push_back(kProtoHTTP11);
   ASSERT_NO_FATAL_FAILURE(
       TestFalseStart(server_options, client_config, false));
@@ -2887,9 +2840,6 @@
       SpawnedTestServer::SSLOptions::BULK_CIPHER_AES128GCM;
   server_options.npn_protocols.push_back(std::string("http/1.1"));
   SSLConfig client_config;
-#if !defined(USE_OPENSSL)
-  client_config.alpn_protos.push_back(kProtoHTTP11);
-#endif
   client_config.npn_protos.push_back(kProtoHTTP11);
   // DHE is only advertised when deprecated ciphers are enabled.
   client_config.deprecated_cipher_suites_enabled = true;
@@ -2905,9 +2855,6 @@
       SpawnedTestServer::SSLOptions::BULK_CIPHER_AES128;
   server_options.npn_protocols.push_back(std::string("http/1.1"));
   SSLConfig client_config;
-#if !defined(USE_OPENSSL)
-  client_config.alpn_protos.push_back(kProtoHTTP11);
-#endif
   client_config.npn_protos.push_back(kProtoHTTP11);
   ASSERT_NO_FATAL_FAILURE(TestFalseStart(server_options, client_config, false));
 }
@@ -2922,9 +2869,6 @@
       SpawnedTestServer::SSLOptions::BULK_CIPHER_AES128GCM;
   server_options.npn_protocols.push_back(std::string("http/1.1"));
   SSLConfig client_config;
-#if !defined(USE_OPENSSL)
-  client_config.alpn_protos.push_back(kProtoHTTP11);
-#endif
   client_config.npn_protos.push_back(kProtoHTTP11);
 
   // Let a full handshake complete with False Start.
@@ -2955,9 +2899,6 @@
   ASSERT_TRUE(StartTestServer(server_options));
 
   SSLConfig client_config;
-#if !defined(USE_OPENSSL)
-  client_config.alpn_protos.push_back(kProtoHTTP11);
-#endif
   client_config.npn_protos.push_back(kProtoHTTP11);
 
   // Start a handshake up to the server Finished message.
@@ -3012,9 +2953,6 @@
   ASSERT_TRUE(StartTestServer(server_options));
 
   SSLConfig client_config;
-#if !defined(USE_OPENSSL)
-  client_config.alpn_protos.push_back(kProtoHTTP11);
-#endif
   client_config.npn_protos.push_back(kProtoHTTP11);
 
   // Start a handshake up to the server Finished message.
@@ -3161,10 +3099,6 @@
   ASSERT_TRUE(StartTestServer(server_options));
 
   SSLConfig client_config;
-#if !defined(USE_OPENSSL)
-  client_config.alpn_protos.push_back(kProtoHTTP2);
-  client_config.alpn_protos.push_back(kProtoHTTP11);
-#endif
   client_config.npn_protos.push_back(kProtoHTTP2);
   client_config.npn_protos.push_back(kProtoHTTP11);
 
@@ -3185,10 +3119,6 @@
   ASSERT_TRUE(StartTestServer(server_options));
 
   SSLConfig client_config;
-#if !defined(USE_OPENSSL)
-  client_config.alpn_protos.push_back(kProtoSPDY31);
-  client_config.alpn_protos.push_back(kProtoHTTP2);
-#endif
   client_config.npn_protos.push_back(kProtoSPDY31);
   client_config.npn_protos.push_back(kProtoHTTP2);
 
@@ -3210,10 +3140,6 @@
   ASSERT_TRUE(StartTestServer(server_options));
 
   SSLConfig client_config;
-#if !defined(USE_OPENSSL)
-  client_config.alpn_protos.push_back(kProtoHTTP2);
-  client_config.alpn_protos.push_back(kProtoSPDY31);
-#endif
   client_config.npn_protos.push_back(kProtoHTTP2);
   client_config.npn_protos.push_back(kProtoSPDY31);
 
@@ -3251,9 +3177,6 @@
   ASSERT_TRUE(StartTestServer(server_options));
 
   SSLConfig client_config;
-#if !defined(USE_OPENSSL)
-  client_config.alpn_protos.push_back(kProtoHTTP11);
-#endif
   client_config.npn_protos.push_back(kProtoHTTP11);
 
   int rv;
@@ -3265,9 +3188,6 @@
             sock_->GetNextProto(&proto));
 }
 
-// Client auth is not supported in NSS ports.
-#if defined(USE_OPENSSL)
-
 namespace {
 
 // Loads a PEM-encoded private key file into a SSLPrivateKey object.
@@ -3370,6 +3290,5 @@
   sock_->Disconnect();
   EXPECT_FALSE(sock_->IsConnected());
 }
-#endif  // defined(USE_OPENSSL)
 
 }  // namespace net
diff --git a/net/socket/ssl_server_socket_nss.cc b/net/socket/ssl_server_socket_nss.cc
deleted file mode 100644
index 17f7d62..0000000
--- a/net/socket/ssl_server_socket_nss.cc
+++ /dev/null
@@ -1,982 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/socket/ssl_server_socket_nss.h"
-
-#include <utility>
-
-#if defined(OS_WIN)
-#include <winsock2.h>
-#endif
-
-#if defined(USE_SYSTEM_SSL)
-#include <dlfcn.h>
-#endif
-#if defined(OS_MACOSX)
-#include <Security/Security.h>
-#endif
-#include <certdb.h>
-#include <cryptohi.h>
-#include <hasht.h>
-#include <keyhi.h>
-#include <nspr.h>
-#include <nss.h>
-#include <pk11pub.h>
-#include <secerr.h>
-#include <sechash.h>
-#include <ssl.h>
-#include <sslerr.h>
-#include <sslproto.h>
-
-#include <limits>
-
-#include "base/callback_helpers.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "crypto/nss_util_internal.h"
-#include "crypto/rsa_private_key.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/log/net_log.h"
-#include "net/socket/nss_ssl_util.h"
-
-// SSL plaintext fragments are shorter than 16KB. Although the record layer
-// overhead is allowed to be 2K + 5 bytes, in practice the overhead is much
-// smaller than 1KB. So a 17KB buffer should be large enough to hold an
-// entire SSL record.
-static const int kRecvBufferSize = 17 * 1024;
-static const int kSendBufferSize = 17 * 1024;
-
-#define GotoState(s) next_handshake_state_ = s
-
-namespace net {
-
-namespace {
-
-bool g_nss_server_sockets_init = false;
-
-class NSSSSLServerInitSingleton {
- public:
-  NSSSSLServerInitSingleton() {
-    EnsureNSSSSLInit();
-
-    SSL_ConfigServerSessionIDCache(64, 28800, 28800, NULL);
-    g_nss_server_sockets_init = true;
-  }
-
-  ~NSSSSLServerInitSingleton() {
-    SSL_ShutdownServerSessionIDCache();
-    g_nss_server_sockets_init = false;
-  }
-};
-
-static base::LazyInstance<NSSSSLServerInitSingleton>::Leaky
-    g_nss_ssl_server_init_singleton = LAZY_INSTANCE_INITIALIZER;
-
-class SSLServerSocketNSS : public SSLServerSocket {
- public:
-  // See comments on CreateSSLServerSocket for details of how these
-  // parameters are used.
-  SSLServerSocketNSS(std::unique_ptr<StreamSocket> socket,
-                     X509Certificate* certificate,
-                     const crypto::RSAPrivateKey& key,
-                     const SSLServerConfig& ssl_server_config);
-  ~SSLServerSocketNSS() override;
-
-  // SSLServerSocket interface.
-  int Handshake(const CompletionCallback& callback) override;
-
-  // SSLSocket interface.
-  int ExportKeyingMaterial(const base::StringPiece& label,
-                           bool has_context,
-                           const base::StringPiece& context,
-                           unsigned char* out,
-                           unsigned int outlen) override;
-
-  // Socket interface (via StreamSocket).
-  int Read(IOBuffer* buf,
-           int buf_len,
-           const CompletionCallback& callback) override;
-  int Write(IOBuffer* buf,
-            int buf_len,
-            const CompletionCallback& callback) override;
-  int SetReceiveBufferSize(int32_t size) override;
-  int SetSendBufferSize(int32_t size) override;
-
-  // StreamSocket implementation.
-  int Connect(const CompletionCallback& callback) override;
-  void Disconnect() override;
-  bool IsConnected() const override;
-  bool IsConnectedAndIdle() const override;
-  int GetPeerAddress(IPEndPoint* address) const override;
-  int GetLocalAddress(IPEndPoint* address) const override;
-  const BoundNetLog& NetLog() const override;
-  void SetSubresourceSpeculation() override;
-  void SetOmniboxSpeculation() override;
-  bool WasEverUsed() const override;
-  bool WasNpnNegotiated() const override;
-  NextProto GetNegotiatedProtocol() const override;
-  bool GetSSLInfo(SSLInfo* ssl_info) override;
-  void GetConnectionAttempts(ConnectionAttempts* out) const override;
-  void ClearConnectionAttempts() override {}
-  void AddConnectionAttempts(const ConnectionAttempts& attempts) override {}
-  int64_t GetTotalReceivedBytes() const override;
-
- private:
-  enum State {
-    STATE_NONE,
-    STATE_HANDSHAKE,
-  };
-
-  int InitializeSSLOptions();
-
-  void OnSendComplete(int result);
-  void OnRecvComplete(int result);
-  void OnHandshakeIOComplete(int result);
-
-  int BufferSend();
-  void BufferSendComplete(int result);
-  int BufferRecv();
-  void BufferRecvComplete(int result);
-  bool DoTransportIO();
-  int DoPayloadRead();
-  int DoPayloadWrite();
-
-  int DoHandshakeLoop(int last_io_result);
-  int DoReadLoop(int result);
-  int DoWriteLoop(int result);
-  int DoHandshake();
-  void DoHandshakeCallback(int result);
-  void DoReadCallback(int result);
-  void DoWriteCallback(int result);
-
-  static SECStatus OwnAuthCertHandler(void* arg,
-                                      PRFileDesc* socket,
-                                      PRBool checksig,
-                                      PRBool is_server);
-  static void HandshakeCallback(PRFileDesc* socket, void* arg);
-
-  int Init();
-
-  // Members used to send and receive buffer.
-  bool transport_send_busy_;
-  bool transport_recv_busy_;
-
-  scoped_refptr<IOBuffer> recv_buffer_;
-
-  BoundNetLog net_log_;
-
-  CompletionCallback user_handshake_callback_;
-  CompletionCallback user_read_callback_;
-  CompletionCallback user_write_callback_;
-
-  // Used by Read function.
-  scoped_refptr<IOBuffer> user_read_buf_;
-  int user_read_buf_len_;
-
-  // Used by Write function.
-  scoped_refptr<IOBuffer> user_write_buf_;
-  int user_write_buf_len_;
-
-  // The NSS SSL state machine
-  PRFileDesc* nss_fd_;
-
-  // Buffers for the network end of the SSL state machine
-  memio_Private* nss_bufs_;
-
-  // StreamSocket for sending and receiving data.
-  std::unique_ptr<StreamSocket> transport_socket_;
-
-  // Options for the SSL socket.
-  SSLServerConfig ssl_server_config_;
-
-  // Certificate for the server.
-  scoped_refptr<X509Certificate> cert_;
-
-  // Private key used by the server.
-  std::unique_ptr<crypto::RSAPrivateKey> key_;
-
-  State next_handshake_state_;
-  bool completed_handshake_;
-
-  DISALLOW_COPY_AND_ASSIGN(SSLServerSocketNSS);
-};
-
-SSLServerSocketNSS::SSLServerSocketNSS(
-    std::unique_ptr<StreamSocket> transport_socket,
-    X509Certificate* cert,
-    const crypto::RSAPrivateKey& key,
-    const SSLServerConfig& ssl_server_config)
-    : transport_send_busy_(false),
-      transport_recv_busy_(false),
-      user_read_buf_len_(0),
-      user_write_buf_len_(0),
-      nss_fd_(NULL),
-      nss_bufs_(NULL),
-      transport_socket_(std::move(transport_socket)),
-      ssl_server_config_(ssl_server_config),
-      cert_(cert),
-      key_(key.Copy()),
-      next_handshake_state_(STATE_NONE),
-      completed_handshake_(false) {
-  CHECK(key_);
-}
-
-SSLServerSocketNSS::~SSLServerSocketNSS() {
-  if (nss_fd_ != NULL) {
-    PR_Close(nss_fd_);
-    nss_fd_ = NULL;
-  }
-}
-
-int SSLServerSocketNSS::Handshake(const CompletionCallback& callback) {
-  net_log_.BeginEvent(NetLog::TYPE_SSL_SERVER_HANDSHAKE);
-
-  int rv = Init();
-  if (rv != OK) {
-    LOG(ERROR) << "Failed to initialize NSS";
-    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
-    return rv;
-  }
-
-  rv = InitializeSSLOptions();
-  if (rv != OK) {
-    LOG(ERROR) << "Failed to initialize SSL options";
-    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
-    return rv;
-  }
-
-  // Set peer address. TODO(hclam): This should be in a separate method.
-  PRNetAddr peername;
-  memset(&peername, 0, sizeof(peername));
-  peername.raw.family = AF_INET;
-  memio_SetPeerName(nss_fd_, &peername);
-
-  GotoState(STATE_HANDSHAKE);
-  rv = DoHandshakeLoop(OK);
-  if (rv == ERR_IO_PENDING) {
-    user_handshake_callback_ = callback;
-  } else {
-    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
-  }
-
-  return rv > OK ? OK : rv;
-}
-
-int SSLServerSocketNSS::ExportKeyingMaterial(const base::StringPiece& label,
-                                             bool has_context,
-                                             const base::StringPiece& context,
-                                             unsigned char* out,
-                                             unsigned int outlen) {
-  if (!IsConnected())
-    return ERR_SOCKET_NOT_CONNECTED;
-  SECStatus result = SSL_ExportKeyingMaterial(
-      nss_fd_, label.data(), label.size(), has_context,
-      reinterpret_cast<const unsigned char*>(context.data()),
-      context.length(), out, outlen);
-  if (result != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_ExportKeyingMaterial", "");
-    return MapNSSError(PORT_GetError());
-  }
-  return OK;
-}
-
-int SSLServerSocketNSS::Connect(const CompletionCallback& callback) {
-  NOTIMPLEMENTED();
-  return ERR_NOT_IMPLEMENTED;
-}
-
-int SSLServerSocketNSS::Read(IOBuffer* buf,
-                             int buf_len,
-                             const CompletionCallback& callback) {
-  DCHECK(user_read_callback_.is_null());
-  DCHECK(user_handshake_callback_.is_null());
-  DCHECK(!user_read_buf_);
-  DCHECK(nss_bufs_);
-  DCHECK(!callback.is_null());
-
-  user_read_buf_ = buf;
-  user_read_buf_len_ = buf_len;
-
-  DCHECK(completed_handshake_);
-
-  int rv = DoReadLoop(OK);
-
-  if (rv == ERR_IO_PENDING) {
-    user_read_callback_ = callback;
-  } else {
-    user_read_buf_ = NULL;
-    user_read_buf_len_ = 0;
-  }
-  return rv;
-}
-
-int SSLServerSocketNSS::Write(IOBuffer* buf,
-                              int buf_len,
-                              const CompletionCallback& callback) {
-  DCHECK(user_write_callback_.is_null());
-  DCHECK(!user_write_buf_);
-  DCHECK(nss_bufs_);
-  DCHECK(!callback.is_null());
-
-  user_write_buf_ = buf;
-  user_write_buf_len_ = buf_len;
-
-  int rv = DoWriteLoop(OK);
-
-  if (rv == ERR_IO_PENDING) {
-    user_write_callback_ = callback;
-  } else {
-    user_write_buf_ = NULL;
-    user_write_buf_len_ = 0;
-  }
-  return rv;
-}
-
-int SSLServerSocketNSS::SetReceiveBufferSize(int32_t size) {
-  return transport_socket_->SetReceiveBufferSize(size);
-}
-
-int SSLServerSocketNSS::SetSendBufferSize(int32_t size) {
-  return transport_socket_->SetSendBufferSize(size);
-}
-
-bool SSLServerSocketNSS::IsConnected() const {
-  // TODO(wtc): Find out if we should check transport_socket_->IsConnected()
-  // as well.
-  return completed_handshake_;
-}
-
-void SSLServerSocketNSS::Disconnect() {
-  transport_socket_->Disconnect();
-}
-
-bool SSLServerSocketNSS::IsConnectedAndIdle() const {
-  return completed_handshake_ && transport_socket_->IsConnectedAndIdle();
-}
-
-int SSLServerSocketNSS::GetPeerAddress(IPEndPoint* address) const {
-  if (!IsConnected())
-    return ERR_SOCKET_NOT_CONNECTED;
-  return transport_socket_->GetPeerAddress(address);
-}
-
-int SSLServerSocketNSS::GetLocalAddress(IPEndPoint* address) const {
-  if (!IsConnected())
-    return ERR_SOCKET_NOT_CONNECTED;
-  return transport_socket_->GetLocalAddress(address);
-}
-
-const BoundNetLog& SSLServerSocketNSS::NetLog() const {
-  return net_log_;
-}
-
-void SSLServerSocketNSS::SetSubresourceSpeculation() {
-  transport_socket_->SetSubresourceSpeculation();
-}
-
-void SSLServerSocketNSS::SetOmniboxSpeculation() {
-  transport_socket_->SetOmniboxSpeculation();
-}
-
-bool SSLServerSocketNSS::WasEverUsed() const {
-  return transport_socket_->WasEverUsed();
-}
-
-bool SSLServerSocketNSS::WasNpnNegotiated() const {
-  NOTIMPLEMENTED();
-  return false;
-}
-
-NextProto SSLServerSocketNSS::GetNegotiatedProtocol() const {
-  // NPN is not supported by this class.
-  return kProtoUnknown;
-}
-
-bool SSLServerSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
-  NOTIMPLEMENTED();
-  return false;
-}
-
-void SSLServerSocketNSS::GetConnectionAttempts(ConnectionAttempts* out) const {
-  out->clear();
-}
-
-int64_t SSLServerSocketNSS::GetTotalReceivedBytes() const {
-  NOTIMPLEMENTED();
-  return 0;
-}
-
-int SSLServerSocketNSS::InitializeSSLOptions() {
-  // Transport connected, now hook it up to nss
-  nss_fd_ = memio_CreateIOLayer(kRecvBufferSize, kSendBufferSize);
-  if (nss_fd_ == NULL) {
-    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR error code.
-  }
-
-  // Grab pointer to buffers
-  nss_bufs_ = memio_GetSecret(nss_fd_);
-
-  /* Create SSL state machine */
-  /* Push SSL onto our fake I/O socket */
-  nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
-  if (nss_fd_ == NULL) {
-    LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
-    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR/NSS error code.
-  }
-  // TODO(port): set more ssl options!  Check errors!
-
-  int rv;
-
-  if (ssl_server_config_.client_cert_type ==
-      SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT) {
-    rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_TRUE);
-    if (rv != SECSuccess) {
-      LogFailedNSSFunction(net_log_, "SSL_OptionSet",
-                           "SSL_REQUEST_CERTIFICATE");
-      return ERR_UNEXPECTED;
-    }
-  }
-
-  rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
-    return ERR_UNEXPECTED;
-  }
-
-  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
-    return ERR_UNEXPECTED;
-  }
-
-  SSLVersionRange version_range;
-  version_range.min = ssl_server_config_.version_min;
-  version_range.max = ssl_server_config_.version_max;
-  rv = SSL_VersionRangeSet(nss_fd_, &version_range);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", "");
-    return ERR_NO_SSL_VERSIONS_ENABLED;
-  }
-
-  if (ssl_server_config_.require_ecdhe) {
-    const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers();
-    const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers();
-
-    // Iterate over the cipher suites and disable those that don't use ECDHE.
-    for (unsigned i = 0; i < num_ciphers; i++) {
-      SSLCipherSuiteInfo info;
-      if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info, sizeof(info)) ==
-          SECSuccess) {
-        if (strcmp(info.keaTypeName, "ECDHE") != 0) {
-          SSL_CipherPrefSet(nss_fd_, ssl_ciphers[i], PR_FALSE);
-        }
-      }
-    }
-  }
-
-  for (std::vector<uint16_t>::const_iterator it =
-           ssl_server_config_.disabled_cipher_suites.begin();
-       it != ssl_server_config_.disabled_cipher_suites.end(); ++it) {
-    // This will fail if the specified cipher is not implemented by NSS, but
-    // the failure is harmless.
-    SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
-  }
-
-  // Server socket doesn't need session tickets.
-  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(
-        net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
-  }
-
-  // Doing this will force PR_Accept perform handshake as server.
-  rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_FALSE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
-    return ERR_UNEXPECTED;
-  }
-
-  rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_SERVER");
-    return ERR_UNEXPECTED;
-  }
-
-  rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_FALSE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUEST_CERTIFICATE");
-    return ERR_UNEXPECTED;
-  }
-
-  rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_CERTIFICATE, PR_FALSE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUIRE_CERTIFICATE");
-    return ERR_UNEXPECTED;
-  }
-
-  rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
-    return ERR_UNEXPECTED;
-  }
-
-  rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
-    return ERR_UNEXPECTED;
-  }
-
-  // Get a certificate of CERTCertificate structure.
-  std::string der_string;
-  if (!X509Certificate::GetDEREncoded(cert_->os_cert_handle(), &der_string))
-    return ERR_UNEXPECTED;
-
-  SECItem der_cert;
-  der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(
-      der_string.data()));
-  der_cert.len  = der_string.length();
-  der_cert.type = siDERCertBuffer;
-
-  // Parse into a CERTCertificate structure.
-  CERTCertificate* cert = CERT_NewTempCertificate(
-      CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
-  if (!cert) {
-    LogFailedNSSFunction(net_log_, "CERT_NewTempCertificate", "");
-    return MapNSSError(PORT_GetError());
-  }
-
-  // Get a key of SECKEYPrivateKey* structure.
-  std::vector<uint8_t> key_vector;
-  if (!key_->ExportPrivateKey(&key_vector)) {
-    CERT_DestroyCertificate(cert);
-    return ERR_UNEXPECTED;
-  }
-
-  SECKEYPrivateKeyStr* private_key = NULL;
-  PK11SlotInfo* slot = PK11_GetInternalSlot();
-  if (!slot) {
-    CERT_DestroyCertificate(cert);
-    return ERR_UNEXPECTED;
-  }
-
-  SECItem der_private_key_info;
-  der_private_key_info.data =
-      const_cast<unsigned char*>(&key_vector.front());
-  der_private_key_info.len = key_vector.size();
-  // The server's RSA private key must be imported into NSS with the
-  // following key usage bits:
-  // - KU_KEY_ENCIPHERMENT, required for the RSA key exchange algorithm.
-  // - KU_DIGITAL_SIGNATURE, required for the DHE_RSA and ECDHE_RSA key
-  //   exchange algorithms.
-  const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DIGITAL_SIGNATURE;
-  rv =  PK11_ImportDERPrivateKeyInfoAndReturnKey(
-      slot, &der_private_key_info, NULL, NULL, PR_FALSE, PR_FALSE,
-      key_usage, &private_key, NULL);
-  PK11_FreeSlot(slot);
-  if (rv != SECSuccess) {
-    CERT_DestroyCertificate(cert);
-    return ERR_UNEXPECTED;
-  }
-
-  // Assign server certificate and private key.
-  SSLKEAType cert_kea = NSS_FindCertKEAType(cert);
-  rv = SSL_ConfigSecureServer(nss_fd_, cert, private_key, cert_kea);
-  CERT_DestroyCertificate(cert);
-  SECKEY_DestroyPrivateKey(private_key);
-
-  if (rv != SECSuccess) {
-    PRErrorCode prerr = PR_GetError();
-    LOG(ERROR) << "Failed to config SSL server: " << prerr;
-    LogFailedNSSFunction(net_log_, "SSL_ConfigureSecureServer", "");
-    return ERR_UNEXPECTED;
-  }
-
-  // Tell SSL we're a server; needed if not letting NSPR do socket I/O
-  rv = SSL_ResetHandshake(nss_fd_, PR_TRUE);
-  if (rv != SECSuccess) {
-    LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", "");
-    return ERR_UNEXPECTED;
-  }
-
-  return OK;
-}
-
-void SSLServerSocketNSS::OnSendComplete(int result) {
-  if (next_handshake_state_ == STATE_HANDSHAKE) {
-    // In handshake phase.
-    OnHandshakeIOComplete(result);
-    return;
-  }
-
-  // TODO(byungchul): This state machine is not correct. Copy the state machine
-  // of SSLClientSocketNSS::OnSendComplete() which handles it better.
-  if (!completed_handshake_)
-    return;
-
-  if (user_write_buf_) {
-    int rv = DoWriteLoop(result);
-    if (rv != ERR_IO_PENDING)
-      DoWriteCallback(rv);
-  } else {
-    // Ensure that any queued ciphertext is flushed.
-    DoTransportIO();
-  }
-}
-
-void SSLServerSocketNSS::OnRecvComplete(int result) {
-  if (next_handshake_state_ == STATE_HANDSHAKE) {
-    // In handshake phase.
-    OnHandshakeIOComplete(result);
-    return;
-  }
-
-  // Network layer received some data, check if client requested to read
-  // decrypted data.
-  if (!user_read_buf_ || !completed_handshake_)
-    return;
-
-  int rv = DoReadLoop(result);
-  if (rv != ERR_IO_PENDING)
-    DoReadCallback(rv);
-}
-
-void SSLServerSocketNSS::OnHandshakeIOComplete(int result) {
-  int rv = DoHandshakeLoop(result);
-  if (rv == ERR_IO_PENDING)
-    return;
-
-  net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
-  if (!user_handshake_callback_.is_null())
-    DoHandshakeCallback(rv);
-}
-
-// Return 0 for EOF,
-// > 0 for bytes transferred immediately,
-// < 0 for error (or the non-error ERR_IO_PENDING).
-int SSLServerSocketNSS::BufferSend(void) {
-  if (transport_send_busy_)
-    return ERR_IO_PENDING;
-
-  const char* buf1;
-  const char* buf2;
-  unsigned int len1, len2;
-  if (memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2)) {
-    // The error code itself is ignored, so just return ERR_ABORTED.
-    return ERR_ABORTED;
-  }
-  const size_t len = len1 + len2;
-
-  int rv = 0;
-  if (len) {
-    scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
-    memcpy(send_buffer->data(), buf1, len1);
-    memcpy(send_buffer->data() + len1, buf2, len2);
-    rv = transport_socket_->Write(
-        send_buffer.get(), len,
-        base::Bind(&SSLServerSocketNSS::BufferSendComplete,
-                   base::Unretained(this)));
-    if (rv == ERR_IO_PENDING) {
-      transport_send_busy_ = true;
-    } else {
-      memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
-    }
-  }
-
-  return rv;
-}
-
-void SSLServerSocketNSS::BufferSendComplete(int result) {
-  memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
-  transport_send_busy_ = false;
-  OnSendComplete(result);
-}
-
-int SSLServerSocketNSS::BufferRecv(void) {
-  if (transport_recv_busy_) return ERR_IO_PENDING;
-
-  char* buf;
-  int nb = memio_GetReadParams(nss_bufs_, &buf);
-  int rv;
-  if (!nb) {
-    // buffer too full to read into, so no I/O possible at moment
-    rv = ERR_IO_PENDING;
-  } else {
-    recv_buffer_ = new IOBuffer(nb);
-    rv = transport_socket_->Read(
-        recv_buffer_.get(), nb,
-        base::Bind(&SSLServerSocketNSS::BufferRecvComplete,
-                   base::Unretained(this)));
-    if (rv == ERR_IO_PENDING) {
-      transport_recv_busy_ = true;
-    } else {
-      if (rv > 0)
-        memcpy(buf, recv_buffer_->data(), rv);
-      memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
-      recv_buffer_ = NULL;
-    }
-  }
-  return rv;
-}
-
-void SSLServerSocketNSS::BufferRecvComplete(int result) {
-  if (result > 0) {
-    char* buf;
-    memio_GetReadParams(nss_bufs_, &buf);
-    memcpy(buf, recv_buffer_->data(), result);
-  }
-  recv_buffer_ = NULL;
-  memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
-  transport_recv_busy_ = false;
-  OnRecvComplete(result);
-}
-
-// Do as much network I/O as possible between the buffer and the
-// transport socket. Return true if some I/O performed, false
-// otherwise (error or ERR_IO_PENDING).
-bool SSLServerSocketNSS::DoTransportIO() {
-  bool network_moved = false;
-  if (nss_bufs_ != NULL) {
-    int rv;
-    // Read and write as much data as we can. The loop is neccessary
-    // because Write() may return synchronously.
-    do {
-      rv = BufferSend();
-      if (rv > 0)
-        network_moved = true;
-    } while (rv > 0);
-    if (BufferRecv() >= 0)
-      network_moved = true;
-  }
-  return network_moved;
-}
-
-int SSLServerSocketNSS::DoPayloadRead() {
-  DCHECK(user_read_buf_);
-  DCHECK_GT(user_read_buf_len_, 0);
-  int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_);
-  if (rv >= 0)
-    return rv;
-  PRErrorCode prerr = PR_GetError();
-  if (prerr == PR_WOULD_BLOCK_ERROR) {
-    return ERR_IO_PENDING;
-  }
-  rv = MapNSSError(prerr);
-  net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
-                    CreateNetLogSSLErrorCallback(rv, prerr));
-  return rv;
-}
-
-int SSLServerSocketNSS::DoPayloadWrite() {
-  DCHECK(user_write_buf_);
-  int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
-  if (rv >= 0)
-    return rv;
-  PRErrorCode prerr = PR_GetError();
-  if (prerr == PR_WOULD_BLOCK_ERROR) {
-    return ERR_IO_PENDING;
-  }
-  rv = MapNSSError(prerr);
-  net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
-                    CreateNetLogSSLErrorCallback(rv, prerr));
-  return rv;
-}
-
-int SSLServerSocketNSS::DoHandshakeLoop(int last_io_result) {
-  int rv = last_io_result;
-  do {
-    // Default to STATE_NONE for next state.
-    // (This is a quirk carried over from the windows
-    // implementation.  It makes reading the logs a bit harder.)
-    // State handlers can and often do call GotoState just
-    // to stay in the current state.
-    State state = next_handshake_state_;
-    GotoState(STATE_NONE);
-    switch (state) {
-      case STATE_HANDSHAKE:
-        rv = DoHandshake();
-        break;
-      case STATE_NONE:
-      default:
-        rv = ERR_UNEXPECTED;
-        LOG(DFATAL) << "unexpected state " << state;
-        break;
-    }
-
-    // Do the actual network I/O
-    bool network_moved = DoTransportIO();
-    if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
-      // In general we exit the loop if rv is ERR_IO_PENDING.  In this
-      // special case we keep looping even if rv is ERR_IO_PENDING because
-      // the transport IO may allow DoHandshake to make progress.
-      rv = OK;  // This causes us to stay in the loop.
-    }
-  } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
-  return rv;
-}
-
-int SSLServerSocketNSS::DoReadLoop(int result) {
-  DCHECK(completed_handshake_);
-  DCHECK(next_handshake_state_ == STATE_NONE);
-
-  if (result < 0)
-    return result;
-
-  if (!nss_bufs_) {
-    LOG(DFATAL) << "!nss_bufs_";
-    int rv = ERR_UNEXPECTED;
-    net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
-                      CreateNetLogSSLErrorCallback(rv, 0));
-    return rv;
-  }
-
-  bool network_moved;
-  int rv;
-  do {
-    rv = DoPayloadRead();
-    network_moved = DoTransportIO();
-  } while (rv == ERR_IO_PENDING && network_moved);
-  return rv;
-}
-
-int SSLServerSocketNSS::DoWriteLoop(int result) {
-  DCHECK(completed_handshake_);
-  DCHECK_EQ(next_handshake_state_, STATE_NONE);
-
-  if (result < 0)
-    return result;
-
-  if (!nss_bufs_) {
-    LOG(DFATAL) << "!nss_bufs_";
-    int rv = ERR_UNEXPECTED;
-    net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
-                      CreateNetLogSSLErrorCallback(rv, 0));
-    return rv;
-  }
-
-  bool network_moved;
-  int rv;
-  do {
-    rv = DoPayloadWrite();
-    network_moved = DoTransportIO();
-  } while (rv == ERR_IO_PENDING && network_moved);
-  return rv;
-}
-
-int SSLServerSocketNSS::DoHandshake() {
-  int net_error = OK;
-  SECStatus rv = SSL_ForceHandshake(nss_fd_);
-
-  if (rv == SECSuccess) {
-    completed_handshake_ = true;
-  } else {
-    PRErrorCode prerr = PR_GetError();
-    net_error = MapNSSError(prerr);
-
-    // If not done, stay in this state
-    if (net_error == ERR_IO_PENDING) {
-      GotoState(STATE_HANDSHAKE);
-    } else {
-      LOG(ERROR) << "handshake failed; NSS error code " << prerr
-                 << ", net_error " << net_error;
-      net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
-                        CreateNetLogSSLErrorCallback(net_error, prerr));
-    }
-  }
-  return net_error;
-}
-
-void SSLServerSocketNSS::DoHandshakeCallback(int rv) {
-  DCHECK_NE(rv, ERR_IO_PENDING);
-  base::ResetAndReturn(&user_handshake_callback_).Run(rv > OK ? OK : rv);
-}
-
-void SSLServerSocketNSS::DoReadCallback(int rv) {
-  DCHECK(rv != ERR_IO_PENDING);
-  DCHECK(!user_read_callback_.is_null());
-
-  user_read_buf_ = NULL;
-  user_read_buf_len_ = 0;
-  base::ResetAndReturn(&user_read_callback_).Run(rv);
-}
-
-void SSLServerSocketNSS::DoWriteCallback(int rv) {
-  DCHECK(rv != ERR_IO_PENDING);
-  DCHECK(!user_write_callback_.is_null());
-
-  user_write_buf_ = NULL;
-  user_write_buf_len_ = 0;
-  base::ResetAndReturn(&user_write_callback_).Run(rv);
-}
-
-// static
-// NSS calls this if an incoming certificate needs to be verified.
-// Do nothing but return SECSuccess.
-// This is called only in full handshake mode.
-// Peer certificate is retrieved in HandshakeCallback() later, which is called
-// in full handshake mode or in resumption handshake mode.
-SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg,
-                                                 PRFileDesc* socket,
-                                                 PRBool checksig,
-                                                 PRBool is_server) {
-  // TODO(hclam): Implement.
-  // Tell NSS to not verify the certificate.
-  return SECSuccess;
-}
-
-// static
-// NSS calls this when handshake is completed.
-// After the SSL handshake is finished we need to verify the certificate.
-void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket, void* arg) {
-  // TODO(hclam): Implement.
-}
-
-int SSLServerSocketNSS::Init() {
-  // Initialize the NSS SSL library in a threadsafe way.  This also
-  // initializes the NSS base library.
-  EnsureNSSSSLInit();
-  if (!NSS_IsInitialized())
-    return ERR_UNEXPECTED;
-
-  EnableSSLServerSockets();
-  return OK;
-}
-
-}  // namespace
-
-std::unique_ptr<SSLServerContext> CreateSSLServerContext(
-    X509Certificate* certificate,
-    const crypto::RSAPrivateKey& key,
-    const SSLServerConfig& ssl_server_config) {
-  return std::unique_ptr<SSLServerContext>(
-      new SSLServerContextNSS(certificate, key, ssl_server_config));
-}
-
-SSLServerContextNSS::SSLServerContextNSS(
-    X509Certificate* certificate,
-    const crypto::RSAPrivateKey& key,
-    const SSLServerConfig& ssl_server_config)
-    : ssl_server_config_(ssl_server_config),
-      cert_(certificate),
-      key_(key.Copy()) {
-  CHECK(key_);
-}
-
-SSLServerContextNSS::~SSLServerContextNSS() {}
-
-std::unique_ptr<SSLServerSocket> SSLServerContextNSS::CreateSSLServerSocket(
-    std::unique_ptr<StreamSocket> socket) {
-  DCHECK(g_nss_server_sockets_init) << "EnableSSLServerSockets() has not been"
-                                    << " called yet!";
-
-  return std::unique_ptr<SSLServerSocket>(new SSLServerSocketNSS(
-      std::move(socket), cert_.get(), *key_, ssl_server_config_));
-}
-
-void EnableSSLServerSockets() {
-  g_nss_ssl_server_init_singleton.Get();
-}
-
-}  // namespace net
diff --git a/net/socket/ssl_server_socket_nss.h b/net/socket/ssl_server_socket_nss.h
deleted file mode 100644
index 9464cede..0000000
--- a/net/socket/ssl_server_socket_nss.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_SOCKET_SSL_SERVER_SOCKET_NSS_H_
-#define NET_SOCKET_SSL_SERVER_SOCKET_NSS_H_
-
-#include <certt.h>
-#include <keyt.h>
-#include <nspr.h>
-#include <nss.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/macros.h"
-#include "net/base/completion_callback.h"
-#include "net/base/host_port_pair.h"
-#include "net/base/nss_memio.h"
-#include "net/log/net_log.h"
-#include "net/socket/ssl_server_socket.h"
-#include "net/ssl/ssl_server_config.h"
-
-namespace net {
-
-class SSLServerContextNSS : public SSLServerContext {
- public:
-  SSLServerContextNSS(X509Certificate* certificate,
-                      const crypto::RSAPrivateKey& key,
-                      const SSLServerConfig& ssl_server_config);
-  ~SSLServerContextNSS() override;
-
-  std::unique_ptr<SSLServerSocket> CreateSSLServerSocket(
-      std::unique_ptr<StreamSocket> socket) override;
-
- private:
-  // Options for the SSL socket.
-  SSLServerConfig ssl_server_config_;
-
-  // Certificate for the server.
-  scoped_refptr<X509Certificate> cert_;
-
-  // Private key used by the server.
-  std::unique_ptr<crypto::RSAPrivateKey> key_;
-};
-
-}  // namespace net
-
-#endif  // NET_SOCKET_SSL_SERVER_SOCKET_NSS_H_
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc
index 74e06ab..32ecfc0 100644
--- a/net/socket/ssl_server_socket_unittest.cc
+++ b/net/socket/ssl_server_socket_unittest.cc
@@ -20,6 +20,10 @@
 #include <queue>
 #include <utility>
 
+#include <openssl/evp.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
 #include "base/callback_helpers.h"
 #include "base/compiler_specific.h"
 #include "base/files/file_path.h"
@@ -65,12 +69,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
-#if defined(USE_OPENSSL)
-#include <openssl/evp.h>
-#include <openssl/ssl.h>
-#include <openssl/x509.h>
-#endif
-
 namespace net {
 
 namespace {
@@ -397,7 +395,6 @@
     ASSERT_TRUE(server_socket_);
   }
 
-#if defined(USE_OPENSSL)
   void ConfigureClientCertsForClient(const char* cert_file_name,
                                      const char* private_key_file_name) {
     client_ssl_config_.send_client_cert = true;
@@ -458,7 +455,6 @@
         crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_vector));
     return key;
   }
-#endif
 
   std::unique_ptr<FakeDataChannel> channel_1_;
   std::unique_ptr<FakeDataChannel> channel_2_;
@@ -520,9 +516,6 @@
   EXPECT_TRUE(is_aead);
 }
 
-// NSS ports don't support client certificates and have a global session cache.
-#if defined(USE_OPENSSL)
-
 // This test makes sure the session cache is working.
 TEST_F(SSLServerSocketTest, HandshakeCached) {
   ASSERT_NO_FATAL_FAILURE(CreateContext());
@@ -865,7 +858,6 @@
   EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
             handshake_callback2.GetResult(server_ret2));
 }
-#endif  // defined(USE_OPENSSL)
 
 TEST_F(SSLServerSocketTest, DataTransfer) {
   ASSERT_NO_FATAL_FAILURE(CreateContext());
diff --git a/net/ssl/channel_id_service.cc b/net/ssl/channel_id_service.cc
index 163a56b..830a4a43 100644
--- a/net/ssl/channel_id_service.cc
+++ b/net/ssl/channel_id_service.cc
@@ -31,10 +31,6 @@
 #include "net/cert/x509_util.h"
 #include "url/gurl.h"
 
-#if !defined(USE_OPENSSL)
-#include <private/pprthred.h>  // PR_DetachThread
-#endif
-
 namespace net {
 
 namespace {
@@ -146,16 +142,6 @@
     int error = ERR_FAILED;
     std::unique_ptr<ChannelIDStore::ChannelID> channel_id =
         GenerateChannelID(server_identifier_, &error);
-#if !defined(USE_OPENSSL)
-    // Detach the thread from NSPR.
-    // Calling NSS functions attaches the thread to NSPR, which stores
-    // the NSPR thread ID in thread-specific data.
-    // The threads in our thread pool terminate after we have called
-    // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets
-    // segfaults on shutdown when the threads' thread-specific data
-    // destructors run.
-    PR_DetachThread();
-#endif
     origin_task_runner_->PostTask(
         FROM_HERE, base::Bind(callback_, server_identifier_, error,
                               base::Passed(&channel_id)));
diff --git a/net/ssl/ssl_cipher_suite_names.cc b/net/ssl/ssl_cipher_suite_names.cc
index 2bfe72a..f6b5460 100644
--- a/net/ssl/ssl_cipher_suite_names.cc
+++ b/net/ssl/ssl_cipher_suite_names.cc
@@ -4,11 +4,10 @@
 
 #include "net/ssl/ssl_cipher_suite_names.h"
 
-#if defined(USE_OPENSSL)
-#include <openssl/ssl.h>
-#endif
 #include <stdlib.h>
 
+#include <openssl/ssl.h>
+
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
@@ -424,7 +423,6 @@
 }
 
 const char* ECCurveName(uint16_t cipher_suite, int key_exchange_info) {
-#if defined(USE_OPENSSL)
   int key_exchange, cipher, mac;
   if (!GetCipherProperties(cipher_suite, &key_exchange, &cipher, &mac))
     return nullptr;
@@ -436,9 +434,6 @@
       return nullptr;
   }
   return SSL_get_curve_name(key_exchange_info);
-#else
-  return nullptr;
-#endif
 }
 
 }  // namespace net
diff --git a/net/ssl/token_binding_nss.cc b/net/ssl/token_binding_nss.cc
deleted file mode 100644
index aa2dd09..0000000
--- a/net/ssl/token_binding_nss.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "token_binding.h"
-
-#include "net/base/net_errors.h"
-
-namespace net {
-
-bool IsTokenBindingSupported() {
-  return false;
-}
-
-bool SignTokenBindingEkm(base::StringPiece ekm,
-                         crypto::ECPrivateKey* key,
-                         std::vector<uint8_t>* out) {
-  return false;
-}
-
-Error BuildTokenBindingMessageFromTokenBindings(
-    const std::vector<base::StringPiece>& token_bindings,
-    std::string* out) {
-  NOTREACHED();
-  return ERR_NOT_IMPLEMENTED;
-}
-
-Error BuildTokenBinding(TokenBindingType type,
-                        crypto::ECPrivateKey* key,
-                        const std::vector<uint8_t>& ekm,
-                        std::string* out) {
-  NOTREACHED();
-  return ERR_NOT_IMPLEMENTED;
-}
-
-TokenBinding::TokenBinding() {}
-
-bool ParseTokenBindingMessage(base::StringPiece token_binding_message,
-                              std::vector<TokenBinding>* token_bindings) {
-  NOTREACHED();
-  return false;
-}
-
-bool VerifyEKMSignature(base::StringPiece ec_point,
-                        base::StringPiece signature,
-                        base::StringPiece ekm) {
-  NOTREACHED();
-  return false;
-}
-
-}  // namespace net
diff --git a/net/test/embedded_test_server/embedded_test_server_unittest.cc b/net/test/embedded_test_server/embedded_test_server_unittest.cc
index d994b00..be9cb8a 100644
--- a/net/test/embedded_test_server/embedded_test_server_unittest.cc
+++ b/net/test/embedded_test_server/embedded_test_server_unittest.cc
@@ -31,7 +31,7 @@
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
 #include "net/cert_net/nss_ocsp.h"
 #endif
 
@@ -123,7 +123,7 @@
   }
 
   void SetUp() override {
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
     // This is needed so NSS's HTTP client functions are initialized on the
     // right thread. These tests create SSLClientSockets on a different thread.
     // TODO(davidben): Initialization can't be deferred to SSLClientSocket. See
@@ -146,7 +146,7 @@
   void TearDown() override {
     if (server_->Started())
       ASSERT_TRUE(server_->ShutdownAndWaitUntilComplete());
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
     ShutdownNSSHttpIO();
 #endif
   }
@@ -498,7 +498,7 @@
 class EmbeddedTestServerThreadingTest
     : public testing::TestWithParam<ThreadingTestParams> {
   void SetUp() override {
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
     // This is needed so NSS's HTTP client functions are initialized on the
     // right thread. These tests create SSLClientSockets on a different thread.
     // TODO(davidben): Initialization can't be deferred to SSLClientSocket. See
@@ -509,7 +509,7 @@
   }
 
   void TearDown() override {
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
     ShutdownNSSHttpIO();
 #endif
   }
diff --git a/net/test/net_test_suite.cc b/net/test/net_test_suite.cc
index 561f149..8b0942b 100644
--- a/net/test/net_test_suite.cc
+++ b/net/test/net_test_suite.cc
@@ -10,7 +10,7 @@
 #include "net/spdy/spdy_session.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
 #include "net/cert_net/nss_ocsp.h"
 #endif
 
@@ -33,7 +33,7 @@
 }
 
 void NetTestSuite::Shutdown() {
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
   net::ShutdownNSSHttpIO();
 #endif
 
diff --git a/net/test/run_all_unittests.cc b/net/test/run_all_unittests.cc
index 5d605092..20f5a68 100644
--- a/net/test/run_all_unittests.cc
+++ b/net/test/run_all_unittests.cc
@@ -59,11 +59,6 @@
   NetTestSuite test_suite(argc, argv);
   ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false);
 
-#if defined(OS_WIN) && !defined(USE_OPENSSL)
-  // We want to be sure to init NSPR on the main thread.
-  crypto::EnsureNSPRInit();
-#endif
-
   // Enable support for SSL server sockets, which must be done while
   // single-threaded.
   net::EnableSSLServerSockets();
diff --git a/net/third_party/nss/patches/applypatches.sh b/net/third_party/nss/patches/applypatches.sh
deleted file mode 100755
index 4724233..0000000
--- a/net/third_party/nss/patches/applypatches.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/sh
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Run this script in the nss/lib/ssl directory in a NSS source tree.
-#
-# Point patches_dir to the src/net/third_party/nss/patches directory in a
-# chromium source tree.
-patches_dir=/Users/sleevi/development/chromium/src/net/third_party/nss/patches
-
-patch -p2 < $patches_dir/cachecerts.patch
-
-patch -p2 < $patches_dir/didhandshakeresume.patch
-
-patch -p2 < $patches_dir/getrequestedclientcerttypes.patch
-
-patch -p2 < $patches_dir/restartclientauth.patch
-
-patch -p2 < $patches_dir/channelid.patch
-
-patch -p2 < $patches_dir/tlsunique.patch
-
-patch -p2 < $patches_dir/secretexporterlocks.patch
-
-patch -p2 < $patches_dir/cachelocks.patch
-
-patch -p2 < $patches_dir/cipherorder.patch
-
-patch -p2 < $patches_dir/sessioncache.patch
-
-patch -p2 < $patches_dir/reorderextensions.patch
-
-patch -p2 < $patches_dir/nobypass.patch
diff --git a/net/third_party/nss/patches/cachecerts.patch b/net/third_party/nss/patches/cachecerts.patch
deleted file mode 100644
index 196bb278..0000000
--- a/net/third_party/nss/patches/cachecerts.patch
+++ /dev/null
@@ -1,124 +0,0 @@
-diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index c3698f3..b8d4784 100644
---- a/lib/ssl/ssl3con.c
-+++ b/lib/ssl/ssl3con.c
-@@ -47,6 +47,7 @@
- 
- static SECStatus ssl3_AuthCertificate(sslSocket *ss);
- static void ssl3_CleanupPeerCerts(sslSocket *ss);
-+static void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid);
- static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec,
-                                        PK11SlotInfo *serverKeySlot);
- static SECStatus ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms);
-@@ -7102,6 +7103,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-             /* copy the peer cert from the SID */
-             if (sid->peerCert != NULL) {
-                 ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
-+                ssl3_CopyPeerCertsFromSID(ss, sid);
-             }
- 
-             /* NULL value for PMS because we are reusing the old MS */
-@@ -8266,6 +8268,44 @@ ssl3_KEAAllowsSessionTicket(SSL3KeyExchangeAlgorithm kea)
-     };
- }
- 
-+static void
-+ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid)
-+{
-+    PLArenaPool *arena;
-+    ssl3CertNode *lastCert = NULL;
-+    ssl3CertNode *certs = NULL;
-+    int i;
-+
-+    if (!sid->peerCertChain[0])
-+        return;
-+    PORT_Assert(!ss->ssl3.peerCertArena);
-+    PORT_Assert(!ss->ssl3.peerCertChain);
-+    ss->ssl3.peerCertArena = arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-+    for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) {
-+        ssl3CertNode *c = PORT_ArenaNew(arena, ssl3CertNode);
-+        c->cert = CERT_DupCertificate(sid->peerCertChain[i]);
-+        c->next = NULL;
-+        if (lastCert) {
-+            lastCert->next = c;
-+        } else {
-+            certs = c;
-+        }
-+        lastCert = c;
-+    }
-+    ss->ssl3.peerCertChain = certs;
-+}
-+
-+static void
-+ssl3_CopyPeerCertsToSID(ssl3CertNode *certs, sslSessionID *sid)
-+{
-+    int i = 0;
-+    ssl3CertNode *c = certs;
-+    for (; i < MAX_PEER_CERT_CHAIN_SIZE && c; i++, c = c->next) {
-+        PORT_Assert(!sid->peerCertChain[i]);
-+        sid->peerCertChain[i] = CERT_DupCertificate(c->cert);
-+    }
-+}
-+
- /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
-  * ssl3 Client Hello message.
-  * Caller must hold Handshake and RecvBuf locks.
-@@ -8886,6 +8926,7 @@ compression_found:
-             ss->sec.ci.sid = sid;
-             if (sid->peerCert != NULL) {
-                 ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
-+                ssl3_CopyPeerCertsFromSID(ss, sid);
-             }
- 
-             /*
-@@ -11240,6 +11281,7 @@ ssl3_AuthCertificate(sslSocket *ss)
-     }
- 
-     ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
-+    ssl3_CopyPeerCertsToSID(ss->ssl3.peerCertChain, ss->sec.ci.sid);
- 
-     if (!ss->sec.isServer) {
-         CERTCertificate *cert = ss->sec.peerCert;
-diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index bce9437..10361a0 100644
---- a/lib/ssl/sslimpl.h
-+++ b/lib/ssl/sslimpl.h
-@@ -614,6 +614,8 @@ typedef enum { never_cached,
-                invalid_cache /* no longer in any cache. */
- } Cached;
- 
-+#define MAX_PEER_CERT_CHAIN_SIZE 8
-+
- struct sslSessionIDStr {
-     /* The global cache lock must be held when accessing these members when the
-      * sid is in any cache.
-@@ -628,6 +630,7 @@ struct sslSessionIDStr {
-      */
- 
-     CERTCertificate *peerCert;
-+    CERTCertificate *peerCertChain[MAX_PEER_CERT_CHAIN_SIZE];
-     SECItemArray peerCertStatus; /* client only */
-     const char *peerID;          /* client only */
-     const char *urlSvrName;      /* client only */
-diff --git a/lib/ssl/sslnonce.c b/lib/ssl/sslnonce.c
-index 85031c4..3216892 100644
---- a/lib/ssl/sslnonce.c
-+++ b/lib/ssl/sslnonce.c
-@@ -167,6 +167,7 @@ lock_cache(void)
- static void
- ssl_DestroySID(sslSessionID *sid)
- {
-+    int i;
-     SSL_TRC(8, ("SSL: destroy sid: sid=0x%x cached=%d", sid, sid->cached));
-     PORT_Assert(sid->references == 0);
-     PORT_Assert(sid->cached != in_client_cache);
-@@ -200,6 +201,9 @@ ssl_DestroySID(sslSessionID *sid)
-     if (sid->peerCert) {
-         CERT_DestroyCertificate(sid->peerCert);
-     }
-+    for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) {
-+	CERT_DestroyCertificate(sid->peerCertChain[i]);
-+    }
-     if (sid->peerCertStatus.items) {
-         SECITEM_FreeArray(&sid->peerCertStatus, PR_FALSE);
-     }
diff --git a/net/third_party/nss/patches/cachelocks.patch b/net/third_party/nss/patches/cachelocks.patch
deleted file mode 100644
index 9ba646b..0000000
--- a/net/third_party/nss/patches/cachelocks.patch
+++ /dev/null
@@ -1,239 +0,0 @@
-diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index 1394542..d7d186a 100644
---- a/lib/ssl/ssl3con.c
-+++ b/lib/ssl/ssl3con.c
-@@ -6049,7 +6049,6 @@ SSL3_ShutdownServerCache(void)
-     }
- 
-     PZ_Unlock(symWrapKeysLock);
--    ssl_FreeSessionCacheLocks();
-     return SECSuccess;
- }
- 
-@@ -6102,7 +6101,7 @@ getWrappingKey(sslSocket *ss,
- 
-     pSymWrapKey = &symWrapKeys[symWrapMechIndex].symWrapKey[exchKeyType];
- 
--    ssl_InitSessionCacheLocks(PR_TRUE);
-+    ssl_InitSessionCacheLocks();
- 
-     PZ_Lock(symWrapKeysLock);
- 
-diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index d47eb28..c0e3a0b 100644
---- a/lib/ssl/sslimpl.h
-+++ b/lib/ssl/sslimpl.h
-@@ -2029,9 +2029,7 @@ extern SECStatus ssl_InitSymWrapKeysLock(void);
- 
- extern SECStatus ssl_FreeSymWrapKeysLock(void);
- 
--extern SECStatus ssl_InitSessionCacheLocks(PRBool lazyInit);
--
--extern SECStatus ssl_FreeSessionCacheLocks(void);
-+extern SECStatus ssl_InitSessionCacheLocks(void);
- 
- /**************** DTLS-specific functions **************/
- extern void dtls_FreeQueuedMessage(DTLSQueuedMessage *msg);
-diff --git a/lib/ssl/sslnonce.c b/lib/ssl/sslnonce.c
-index 4804cb8..99591cc 100644
---- a/lib/ssl/sslnonce.c
-+++ b/lib/ssl/sslnonce.c
-@@ -35,93 +35,55 @@ static PZLock *cacheLock = NULL;
- #define LOCK_CACHE lock_cache()
- #define UNLOCK_CACHE PZ_Unlock(cacheLock)
- 
--static SECStatus
--ssl_InitClientSessionCacheLock(void)
--{
--    cacheLock = PZ_NewLock(nssILockCache);
--    return cacheLock ? SECSuccess : SECFailure;
--}
--
--static SECStatus
--ssl_FreeClientSessionCacheLock(void)
--{
--    if (cacheLock) {
--        PZ_DestroyLock(cacheLock);
--        cacheLock = NULL;
--        return SECSuccess;
--    }
--    PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
--    return SECFailure;
--}
--
--static PRBool LocksInitializedEarly = PR_FALSE;
-+static PRCallOnceType lockOnce;
- 
-+/* FreeSessionCacheLocks is a callback from NSS_RegisterShutdown which destroys
-+ * the session cache locks on shutdown and resets them to their initial
-+ * state. */
- static SECStatus
--FreeSessionCacheLocks()
-+FreeSessionCacheLocks(void *appData, void *nssData)
- {
--    SECStatus rv1, rv2;
--    rv1 = ssl_FreeSymWrapKeysLock();
--    rv2 = ssl_FreeClientSessionCacheLock();
--    if ((SECSuccess == rv1) && (SECSuccess == rv2)) {
--        return SECSuccess;
--    }
--    return SECFailure;
--}
-+    static const PRCallOnceType pristineCallOnce;
-+    SECStatus rv;
- 
--static SECStatus
--InitSessionCacheLocks(void)
--{
--    SECStatus rv1, rv2;
--    PRErrorCode rc;
--    rv1 = ssl_InitSymWrapKeysLock();
--    rv2 = ssl_InitClientSessionCacheLock();
--    if ((SECSuccess == rv1) && (SECSuccess == rv2)) {
--        return SECSuccess;
--    }
--    rc = PORT_GetError();
--    FreeSessionCacheLocks();
--    PORT_SetError(rc);
--    return SECFailure;
--}
--
--/* free the session cache locks if they were initialized early */
--SECStatus
--ssl_FreeSessionCacheLocks()
--{
--    PORT_Assert(PR_TRUE == LocksInitializedEarly);
--    if (!LocksInitializedEarly) {
-+    if (!cacheLock) {
-         PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
-         return SECFailure;
-     }
--    FreeSessionCacheLocks();
--    LocksInitializedEarly = PR_FALSE;
--    return SECSuccess;
--}
- 
--static PRCallOnceType lockOnce;
-+    PZ_DestroyLock(cacheLock);
-+    cacheLock = NULL;
- 
--/* free the session cache locks if they were initialized lazily */
--static SECStatus
--ssl_ShutdownLocks(void *appData, void *nssData)
--{
--    PORT_Assert(PR_FALSE == LocksInitializedEarly);
--    if (LocksInitializedEarly) {
--        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
--        return SECFailure;
-+    rv = ssl_FreeSymWrapKeysLock();
-+    if (rv != SECSuccess) {
-+        return rv;
-     }
--    FreeSessionCacheLocks();
--    memset(&lockOnce, 0, sizeof(lockOnce));
-+
-+    lockOnce = pristineCallOnce;
-     return SECSuccess;
- }
- 
-+/* InitSessionCacheLocks is called, protected by lockOnce, to create the
-+ * session cache locks. */
- static PRStatus
--initSessionCacheLocksLazily(void)
-+InitSessionCacheLocks(void)
- {
--    SECStatus rv = InitSessionCacheLocks();
--    if (SECSuccess != rv) {
-+    SECStatus rv;
-+
-+    cacheLock = PZ_NewLock(nssILockCache);
-+    if (cacheLock == NULL) {
-         return PR_FAILURE;
-     }
--    rv = NSS_RegisterShutdown(ssl_ShutdownLocks, NULL);
-+    rv = ssl_InitSymWrapKeysLock();
-+    if (rv != SECSuccess) {
-+        PRErrorCode error = PORT_GetError();
-+        PZ_DestroyLock(cacheLock);
-+        cacheLock = NULL;
-+        PORT_SetError(error);
-+        return PR_FAILURE;
-+    }
-+
-+    rv = NSS_RegisterShutdown(FreeSessionCacheLocks, NULL);
-     PORT_Assert(SECSuccess == rv);
-     if (SECSuccess != rv) {
-         return PR_FAILURE;
-@@ -129,35 +91,19 @@ initSessionCacheLocksLazily(void)
-     return PR_SUCCESS;
- }
- 
--/* lazyInit means that the call is not happening during a 1-time
-- * initialization function, but rather during dynamic, lazy initialization
-- */
- SECStatus
--ssl_InitSessionCacheLocks(PRBool lazyInit)
-+ssl_InitSessionCacheLocks()
- {
--    if (LocksInitializedEarly) {
--        return SECSuccess;
--    }
--
--    if (lazyInit) {
--        return (PR_SUCCESS ==
--                PR_CallOnce(&lockOnce, initSessionCacheLocksLazily))
--                   ? SECSuccess
--                   : SECFailure;
--    }
--
--    if (SECSuccess == InitSessionCacheLocks()) {
--        LocksInitializedEarly = PR_TRUE;
--        return SECSuccess;
--    }
--
--    return SECFailure;
-+    return (PR_SUCCESS ==
-+            PR_CallOnce(&lockOnce, InitSessionCacheLocks))
-+               ? SECSuccess
-+               : SECFailure;
- }
- 
- static void
- lock_cache(void)
- {
--    ssl_InitSessionCacheLocks(PR_TRUE);
-+    ssl_InitSessionCacheLocks();
-     PZ_Lock(cacheLock);
- }
- 
-diff --git a/lib/ssl/sslsnce.c b/lib/ssl/sslsnce.c
-index da1f93f..e3f749e 100644
---- a/lib/ssl/sslsnce.c
-+++ b/lib/ssl/sslsnce.c
-@@ -1344,7 +1344,7 @@ SSL_ConfigServerSessionIDCache(int maxCacheEntries,
-                                PRUint32 ssl3_timeout,
-                                const char *directory)
- {
--    ssl_InitSessionCacheLocks(PR_FALSE);
-+    ssl_InitSessionCacheLocks();
-     return SSL_ConfigServerSessionIDCacheInstance(&globalCache,
-                                                   maxCacheEntries, ssl2_timeout, ssl3_timeout, directory, PR_FALSE);
- }
-@@ -1458,7 +1458,7 @@ SSL_ConfigServerSessionIDCacheWithOpt(
-     PRBool enableMPCache)
- {
-     if (!enableMPCache) {
--        ssl_InitSessionCacheLocks(PR_FALSE);
-+        ssl_InitSessionCacheLocks();
-         return ssl_ConfigServerSessionIDCacheInstanceWithOpt(&globalCache,
-                                                              ssl2_timeout, ssl3_timeout, directory, PR_FALSE,
-                                                              maxCacheEntries, maxCertCacheEntries, maxSrvNameCacheEntries);
-@@ -1502,7 +1502,7 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char *envString)
-         return SECSuccess; /* already done. */
-     }
- 
--    ssl_InitSessionCacheLocks(PR_FALSE);
-+    ssl_InitSessionCacheLocks();
- 
-     ssl_sid_lookup = ServerSessionIDLookup;
-     ssl_sid_cache = ServerSessionIDCache;
diff --git a/net/third_party/nss/patches/channelid.patch b/net/third_party/nss/patches/channelid.patch
deleted file mode 100644
index 674d4ee..0000000
--- a/net/third_party/nss/patches/channelid.patch
+++ /dev/null
@@ -1,704 +0,0 @@
-diff --git a/lib/ssl/SSLerrs.h b/lib/ssl/SSLerrs.h
-index 15bf0b4..555e629 100644
---- a/lib/ssl/SSLerrs.h
-+++ b/lib/ssl/SSLerrs.h
-@@ -465,3 +465,12 @@ ER3(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION, (SSL_ERROR_BASE + 145),
- 
- ER3(SSL_ERROR_RX_MALFORMED_ENCRYPTED_EXTENSIONS, (SSL_ERROR_BASE + 146),
-     "SSL received a malformed Encrypted Extensions handshake message.")
-+
-+ER3(SSL_ERROR_BAD_CHANNEL_ID_DATA, (SSL_ERROR_BASE + 147),
-+    "SSL received a malformed TLS Channel ID extension.")
-+
-+ER3(SSL_ERROR_INVALID_CHANNEL_ID_KEY, (SSL_ERROR_BASE + 148),
-+    "The application provided an invalid TLS Channel ID key.")
-+
-+ER3(SSL_ERROR_GET_CHANNEL_ID_FAILED, (SSL_ERROR_BASE + 149),
-+    "The application could not get a TLS Channel ID.")
-diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
-index aa4a3e5..870a8cc 100644
---- a/lib/ssl/ssl.h
-+++ b/lib/ssl/ssl.h
-@@ -1142,6 +1142,34 @@ SSL_IMPORT SECStatus SSL_HandshakeNegotiatedExtension(PRFileDesc *socket,
- SSL_IMPORT SECStatus SSL_HandshakeResumedSession(PRFileDesc *fd,
-                                                  PRBool *last_handshake_resumed);
- 
-+/* See SSL_SetClientChannelIDCallback for usage. If the callback returns
-+ * SECWouldBlock then SSL_RestartHandshakeAfterChannelIDReq should be called in
-+ * the future to restart the handshake.  On SECSuccess, the callback must have
-+ * written a P-256, EC key pair to |*out_public_key| and |*out_private_key|. */
-+typedef SECStatus(PR_CALLBACK *SSLClientChannelIDCallback)(
-+    void *arg,
-+    PRFileDesc *fd,
-+    SECKEYPublicKey **out_public_key,
-+    SECKEYPrivateKey **out_private_key);
-+
-+/* SSL_RestartHandshakeAfterChannelIDReq attempts to restart the handshake
-+ * after a ChannelID callback returned SECWouldBlock.
-+ *
-+ * This function takes ownership of |channelIDPub| and |channelID|. */
-+SSL_IMPORT SECStatus SSL_RestartHandshakeAfterChannelIDReq(
-+    PRFileDesc *fd,
-+    SECKEYPublicKey *channelIDPub,
-+    SECKEYPrivateKey *channelID);
-+
-+/* SSL_SetClientChannelIDCallback sets a callback function that will be called
-+ * once the server's ServerHello has been processed. This is only applicable to
-+ * a client socket and setting this callback causes the TLS Channel ID
-+ * extension to be advertised. */
-+SSL_IMPORT SECStatus SSL_SetClientChannelIDCallback(
-+    PRFileDesc *fd,
-+    SSLClientChannelIDCallback callback,
-+    void *arg);
-+
- /*
- ** How long should we wait before retransmitting the next flight of
- ** the DTLS handshake? Returns SECFailure if not DTLS or not in a
-diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index 2a2e644..a2beec2 100644
---- a/lib/ssl/ssl3con.c
-+++ b/lib/ssl/ssl3con.c
-@@ -57,6 +57,7 @@ static SECStatus ssl3_InitState(sslSocket *ss);
- 
- static SECStatus ssl3_SendCertificateRequest(sslSocket *ss);
- static SECStatus ssl3_SendNextProto(sslSocket *ss);
-+static SECStatus ssl3_SendChannelIDEncryptedExtensions(sslSocket *ss);
- static SECStatus ssl3_SendFinished(sslSocket *ss, PRInt32 flags);
- static SECStatus ssl3_SendServerHelloDone(sslSocket *ss);
- static SECStatus ssl3_SendServerKeyExchange(sslSocket *ss);
-@@ -6762,6 +6763,15 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-         ss->ssl3.clientPrivateKey = NULL;
-     }
- 
-+    if (ss->ssl3.channelID != NULL) {
-+        SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
-+        ss->ssl3.channelID = NULL;
-+    }
-+    if (ss->ssl3.channelIDPub != NULL) {
-+        SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
-+        ss->ssl3.channelIDPub = NULL;
-+    }
-+
-     temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
-     if (temp < 0) {
-         goto loser; /* alert has been sent */
-@@ -7111,7 +7121,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-             if (rv != SECSuccess) {
-                 goto alert_loser; /* err code was set */
-             }
--            return SECSuccess;
-+            goto winner;
-         } while (0);
- 
-     if (sid_match)
-@@ -7166,6 +7176,27 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-         PORT_Assert(ss->ssl3.hs.kea_def->ephemeral);
-         ss->ssl3.hs.ws = wait_server_key;
-     }
-+
-+winner:
-+    /* If we will need a ChannelID key then we make the callback now. This
-+     * allows the handshake to be restarted cleanly if the callback returns
-+     * SECWouldBlock. */
-+    if (ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)) {
-+        rv = ss->getChannelID(ss->getChannelIDArg, ss->fd,
-+                              &ss->ssl3.channelIDPub, &ss->ssl3.channelID);
-+        if (rv == SECWouldBlock) {
-+            ssl3_SetAlwaysBlock(ss);
-+            return rv;
-+        }
-+        if (rv != SECSuccess ||
-+            ss->ssl3.channelIDPub == NULL ||
-+            ss->ssl3.channelID == NULL) {
-+            PORT_SetError(SSL_ERROR_GET_CHANNEL_ID_FAILED);
-+            desc = internal_error;
-+            goto alert_loser;
-+        }
-+    }
-+
-     return SECSuccess;
- 
- alert_loser:
-@@ -8096,7 +8127,14 @@ ssl3_SendClientSecondRound(sslSocket *ss)
-         if (rv != SECSuccess) {
-             goto loser; /* err code was set. */
-         }
-+    }
- 
-+    rv = ssl3_SendChannelIDEncryptedExtensions(ss);
-+    if (rv != SECSuccess) {
-+        goto loser; /* err code was set. */
-+    }
-+
-+    if (!ss->firstHsDone) {
-         if (ss->opt.enableFalseStart) {
-             if (!ss->ssl3.hs.authCertificatePending) {
-                 /* When we fix bug 589047, we will need to know whether we are
-@@ -8133,6 +8171,33 @@ ssl3_SendClientSecondRound(sslSocket *ss)
- 
-     ssl_ReleaseXmitBufLock(ss); /*******************************/
- 
-+    if (!ss->ssl3.hs.isResuming &&
-+        ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)) {
-+        /* If we are negotiating ChannelID on a full handshake then we record
-+         * the handshake hashes in |sid| at this point. They will be needed in
-+         * the event that we resume this session and use ChannelID on the
-+         * resumption handshake. */
-+        SSL3Hashes hashes;
-+        SECItem *originalHandshakeHash =
-+            &ss->sec.ci.sid->u.ssl3.originalHandshakeHash;
-+        PORT_Assert(ss->sec.ci.sid->cached == never_cached);
-+
-+        ssl_GetSpecReadLock(ss);
-+        PORT_Assert(ss->version > SSL_LIBRARY_VERSION_3_0);
-+        rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.cwSpec, &hashes, 0);
-+        ssl_ReleaseSpecReadLock(ss);
-+        if (rv != SECSuccess) {
-+            return rv;
-+        }
-+
-+        PORT_Assert(originalHandshakeHash->len == 0);
-+        originalHandshakeHash->data = PORT_Alloc(hashes.len);
-+        if (!originalHandshakeHash->data)
-+            return SECFailure;
-+        originalHandshakeHash->len = hashes.len;
-+        memcpy(originalHandshakeHash->data, hashes.u.raw, hashes.len);
-+    }
-+
-     if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn))
-         ss->ssl3.hs.ws = wait_new_session_ticket;
-     else
-@@ -11763,6 +11828,184 @@ ssl3_RecordKeyLog(sslSocket *ss)
- }
- 
- /* called from ssl3_SendClientSecondRound
-+ *	     ssl3_HandleFinished
-+ */
-+static SECStatus
-+ssl3_SendChannelIDEncryptedExtensions(sslSocket *ss)
-+{
-+    static const char CHANNEL_ID_MAGIC[] = "TLS Channel ID signature";
-+    static const char CHANNEL_ID_RESUMPTION_MAGIC[] = "Resumption";
-+    /* This is the ASN.1 prefix for a P-256 public key. Specifically it's:
-+     * SEQUENCE
-+     *   SEQUENCE
-+     *     OID id-ecPublicKey
-+     *     OID prime256v1
-+     *   BIT STRING, length 66, 0 trailing bits: 0x04
-+     *
-+     * The 0x04 in the BIT STRING is the prefix for an uncompressed, X9.62
-+     * public key. Following that are the two field elements as 32-byte,
-+     * big-endian numbers, as required by the Channel ID. */
-+    static const unsigned char P256_SPKI_PREFIX[] = {
-+        0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
-+        0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
-+        0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
-+        0x42, 0x00, 0x04
-+    };
-+    /* ChannelIDs are always 128 bytes long: 64 bytes of P-256 public key and 64
-+     * bytes of ECDSA signature. */
-+    static const int CHANNEL_ID_PUBLIC_KEY_LENGTH = 64;
-+    static const int CHANNEL_ID_LENGTH = 128;
-+
-+    SECStatus rv = SECFailure;
-+    SECItem *spki = NULL;
-+    SSL3Hashes hashes;
-+    const unsigned char *pub_bytes;
-+    unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) +
-+                              sizeof(CHANNEL_ID_RESUMPTION_MAGIC) +
-+                              sizeof(SSL3Hashes) * 2];
-+    size_t signed_data_len;
-+    unsigned char digest[SHA256_LENGTH];
-+    SECItem digest_item;
-+    unsigned char signature[64];
-+    SECItem signature_item;
-+
-+    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-+    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-+
-+    if (ss->ssl3.channelID == NULL)
-+        return SECSuccess;
-+
-+    PORT_Assert(ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn));
-+
-+    if (SECKEY_GetPrivateKeyType(ss->ssl3.channelID) != ecKey ||
-+        PK11_SignatureLen(ss->ssl3.channelID) != sizeof(signature)) {
-+        PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY);
-+        rv = SECFailure;
-+        goto loser;
-+    }
-+
-+    ssl_GetSpecReadLock(ss);
-+    rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.cwSpec, &hashes, 0);
-+    ssl_ReleaseSpecReadLock(ss);
-+
-+    if (rv != SECSuccess)
-+        goto loser;
-+
-+    rv = ssl3_AppendHandshakeHeader(ss, channelid_encrypted_extensions,
-+                                    2 + 2 + CHANNEL_ID_LENGTH);
-+    if (rv != SECSuccess)
-+        goto loser; /* error code set by AppendHandshakeHeader */
-+    rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2);
-+    if (rv != SECSuccess)
-+        goto loser; /* error code set by AppendHandshake */
-+    rv = ssl3_AppendHandshakeNumber(ss, CHANNEL_ID_LENGTH, 2);
-+    if (rv != SECSuccess)
-+        goto loser; /* error code set by AppendHandshake */
-+
-+    spki = SECKEY_EncodeDERSubjectPublicKeyInfo(ss->ssl3.channelIDPub);
-+
-+    if (spki->len != sizeof(P256_SPKI_PREFIX) + CHANNEL_ID_PUBLIC_KEY_LENGTH ||
-+        memcmp(spki->data, P256_SPKI_PREFIX, sizeof(P256_SPKI_PREFIX)) != 0) {
-+        PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY);
-+        rv = SECFailure;
-+        goto loser;
-+    }
-+
-+    pub_bytes = spki->data + sizeof(P256_SPKI_PREFIX);
-+
-+    signed_data_len = 0;
-+    memcpy(signed_data + signed_data_len, CHANNEL_ID_MAGIC,
-+           sizeof(CHANNEL_ID_MAGIC));
-+    signed_data_len += sizeof(CHANNEL_ID_MAGIC);
-+    if (ss->ssl3.hs.isResuming) {
-+        SECItem *originalHandshakeHash =
-+            &ss->sec.ci.sid->u.ssl3.originalHandshakeHash;
-+        PORT_Assert(originalHandshakeHash->len > 0);
-+
-+        memcpy(signed_data + signed_data_len, CHANNEL_ID_RESUMPTION_MAGIC,
-+               sizeof(CHANNEL_ID_RESUMPTION_MAGIC));
-+        signed_data_len += sizeof(CHANNEL_ID_RESUMPTION_MAGIC);
-+        memcpy(signed_data + signed_data_len, originalHandshakeHash->data,
-+               originalHandshakeHash->len);
-+        signed_data_len += originalHandshakeHash->len;
-+    }
-+    memcpy(signed_data + signed_data_len, hashes.u.raw, hashes.len);
-+    signed_data_len += hashes.len;
-+
-+    rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data, signed_data_len);
-+    if (rv != SECSuccess)
-+        goto loser;
-+
-+    digest_item.data = digest;
-+    digest_item.len = sizeof(digest);
-+
-+    signature_item.data = signature;
-+    signature_item.len = sizeof(signature);
-+
-+    rv = PK11_Sign(ss->ssl3.channelID, &signature_item, &digest_item);
-+    if (rv != SECSuccess)
-+        goto loser;
-+
-+    rv = ssl3_AppendHandshake(ss, pub_bytes, CHANNEL_ID_PUBLIC_KEY_LENGTH);
-+    if (rv != SECSuccess)
-+        goto loser;
-+    rv = ssl3_AppendHandshake(ss, signature, sizeof(signature));
-+
-+loser:
-+    if (spki)
-+        SECITEM_FreeItem(spki, PR_TRUE);
-+    if (ss->ssl3.channelID) {
-+        SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
-+        ss->ssl3.channelID = NULL;
-+    }
-+    if (ss->ssl3.channelIDPub) {
-+        SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
-+        ss->ssl3.channelIDPub = NULL;
-+    }
-+
-+    return rv;
-+}
-+
-+/* ssl3_RestartHandshakeAfterChannelIDReq is called to restart a handshake
-+ * after a ChannelID callback returned SECWouldBlock. At this point we have
-+ * processed the server's ServerHello but not yet any further messages. We will
-+ * always get a message from the server after a ServerHello so either they are
-+ * waiting in the buffer or we'll get network I/O. */
-+SECStatus
-+ssl3_RestartHandshakeAfterChannelIDReq(sslSocket *ss,
-+                                       SECKEYPublicKey *channelIDPub,
-+                                       SECKEYPrivateKey *channelID)
-+{
-+    if (ss->handshake == 0) {
-+        SECKEY_DestroyPublicKey(channelIDPub);
-+        SECKEY_DestroyPrivateKey(channelID);
-+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-+        return SECFailure;
-+    }
-+
-+    if (channelIDPub == NULL ||
-+        channelID == NULL) {
-+        if (channelIDPub)
-+            SECKEY_DestroyPublicKey(channelIDPub);
-+        if (channelID)
-+            SECKEY_DestroyPrivateKey(channelID);
-+        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-+        return SECFailure;
-+    }
-+
-+    if (ss->ssl3.channelID)
-+        SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
-+    if (ss->ssl3.channelIDPub)
-+        SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
-+
-+    ss->handshake = ssl_GatherRecord1stHandshake;
-+    ss->ssl3.channelID = channelID;
-+    ss->ssl3.channelIDPub = channelIDPub;
-+
-+    return SECSuccess;
-+}
-+
-+/* called from ssl3_SendClientSecondRound
-  *             ssl3_HandleClientHello
-  *             ssl3_HandleFinished
-  */
-@@ -12030,11 +12273,16 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
-             flags = ssl_SEND_FLAG_FORCE_INTO_BUFFER;
-         }
- 
--        if (!isServer && !ss->firstHsDone) {
--            rv = ssl3_SendNextProto(ss);
--            if (rv != SECSuccess) {
--                goto xmit_loser; /* err code was set. */
-+        if (!isServer) {
-+            if (!ss->firstHsDone) {
-+                rv = ssl3_SendNextProto(ss);
-+                if (rv != SECSuccess) {
-+                    goto xmit_loser; /* err code was set. */
-+                }
-             }
-+            rv = ssl3_SendChannelIDEncryptedExtensions(ss);
-+            if (rv != SECSuccess)
-+                goto xmit_loser; /* err code was set. */
-         }
- 
-         if (IS_DTLS(ss)) {
-@@ -13658,6 +13906,11 @@ ssl3_DestroySSL3Info(sslSocket *ss)
-     if (ss->ssl3.clientPrivateKey != NULL)
-         SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
- 
-+    if (ss->ssl3.channelID)
-+        SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
-+    if (ss->ssl3.channelIDPub)
-+        SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
-+
-     if (ss->ssl3.peerCertArena != NULL)
-         ssl3_CleanupPeerCerts(ss);
- 
-diff --git a/lib/ssl/ssl3ext.c b/lib/ssl/ssl3ext.c
-index 2e99a40..2ffe77b 100644
---- a/lib/ssl/ssl3ext.c
-+++ b/lib/ssl/ssl3ext.c
-@@ -73,6 +73,10 @@ static SECStatus ssl3_ClientHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type,
-                                              SECItem *data);
- static SECStatus ssl3_ServerHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type,
-                                              SECItem *data);
-+static SECStatus ssl3_ClientHandleChannelIDXtn(sslSocket *ss,
-+                                               PRUint16 ex_type, SECItem *data);
-+static PRInt32 ssl3_ClientSendChannelIDXtn(sslSocket *ss, PRBool append,
-+                                           PRUint32 maxBytes);
- static PRInt32 ssl3_ServerSendStatusRequestXtn(sslSocket *ss,
-                                                PRBool append, PRUint32 maxBytes);
- static SECStatus ssl3_ServerHandleStatusRequestXtn(sslSocket *ss,
-@@ -298,6 +302,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
-     { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
-     { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn },
-     { ssl_use_srtp_xtn, &ssl3_ClientHandleUseSRTPXtn },
-+    { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
-     { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
-     { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn },
-     { ssl_signed_cert_timestamp_xtn, &ssl3_ClientHandleSignedCertTimestampXtn },
-@@ -329,6 +334,7 @@ static const ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS]
-       { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn },
-       { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn },
-       { ssl_use_srtp_xtn, &ssl3_ClientSendUseSRTPXtn },
-+      { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
-       { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
-       { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
-       { ssl_tls13_draft_version_xtn, &ssl3_ClientSendDraftVersionXtn },
-@@ -981,6 +987,61 @@ ssl3_ServerSendAppProtoXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
- }
- 
- static SECStatus
-+ssl3_ClientHandleChannelIDXtn(sslSocket *ss, PRUint16 ex_type,
-+                              SECItem *data)
-+{
-+    PORT_Assert(ss->getChannelID != NULL);
-+
-+    if (data->len) {
-+        PORT_SetError(SSL_ERROR_BAD_CHANNEL_ID_DATA);
-+        return SECFailure;
-+    }
-+    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-+    return SECSuccess;
-+}
-+
-+static PRInt32
-+ssl3_ClientSendChannelIDXtn(sslSocket *ss, PRBool append,
-+                            PRUint32 maxBytes)
-+{
-+    PRInt32 extension_length = 4;
-+
-+    if (!ss->getChannelID)
-+        return 0;
-+
-+    if (maxBytes < extension_length) {
-+        PORT_Assert(0);
-+        return 0;
-+    }
-+
-+    if (ss->sec.ci.sid->cached != never_cached &&
-+        ss->sec.ci.sid->u.ssl3.originalHandshakeHash.len == 0) {
-+        /* We can't do ChannelID on a connection if we're resuming and didn't
-+         * do ChannelID on the original connection: without ChannelID on the
-+         * original connection we didn't record the handshake hashes needed for
-+         * the signature. */
-+        return 0;
-+    }
-+
-+    if (append) {
-+        SECStatus rv;
-+        rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2);
-+        if (rv != SECSuccess)
-+            goto loser;
-+        rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
-+        if (rv != SECSuccess)
-+            goto loser;
-+        ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
-+            ssl_channel_id_xtn;
-+    }
-+
-+    return extension_length;
-+
-+loser:
-+    return -1;
-+}
-+
-+static SECStatus
- ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type,
-                                   SECItem *data)
- {
-diff --git a/lib/ssl/ssl3prot.h b/lib/ssl/ssl3prot.h
-index e637d11..928d059 100644
---- a/lib/ssl/ssl3prot.h
-+++ b/lib/ssl/ssl3prot.h
-@@ -140,7 +140,8 @@ typedef enum {
-     client_key_exchange = 16,
-     finished = 20,
-     certificate_status = 22,
--    next_proto = 67
-+    next_proto = 67,
-+    channelid_encrypted_extensions = 203
- } SSL3HandshakeType;
- 
- typedef struct {
-diff --git a/lib/ssl/sslauth.c b/lib/ssl/sslauth.c
-index 7fb4dc5..e78a513 100644
---- a/lib/ssl/sslauth.c
-+++ b/lib/ssl/sslauth.c
-@@ -221,6 +221,25 @@ SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func,
-     return SECSuccess;
- }
- 
-+SECStatus
-+SSL_SetClientChannelIDCallback(PRFileDesc *fd,
-+                               SSLClientChannelIDCallback callback,
-+                               void *arg)
-+{
-+    sslSocket *ss = ssl_FindSocket(fd);
-+
-+    if (!ss) {
-+        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetClientChannelIDCallback",
-+                 SSL_GETPID(), fd));
-+        return SECFailure;
-+    }
-+
-+    ss->getChannelID = callback;
-+    ss->getChannelIDArg = arg;
-+
-+    return SECSuccess;
-+}
-+
- /* NEED LOCKS IN HERE.  */
- SECStatus
- SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg)
-diff --git a/lib/ssl/sslerr.h b/lib/ssl/sslerr.h
-index f806359..299951c 100644
---- a/lib/ssl/sslerr.h
-+++ b/lib/ssl/sslerr.h
-@@ -220,6 +220,11 @@ typedef enum {
-     SSL_ERROR_KEY_EXCHANGE_FAILURE          = (SSL_ERROR_BASE + 144),
-     SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION = (SSL_ERROR_BASE + 145),
-     SSL_ERROR_RX_MALFORMED_ENCRYPTED_EXTENSIONS = (SSL_ERROR_BASE + 146),
-+
-+ SSL_ERROR_BAD_CHANNEL_ID_DATA           = (SSL_ERROR_BASE + 147),
-+ SSL_ERROR_INVALID_CHANNEL_ID_KEY        = (SSL_ERROR_BASE + 148),
-+ SSL_ERROR_GET_CHANNEL_ID_FAILED         = (SSL_ERROR_BASE + 149),
-+
-     SSL_ERROR_END_OF_LIST   /* let the c compiler determine the value of this. */
- } SSLErrorCodes;
- #endif /* NO_SECURITY_ERROR_ENUM */
-diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index dad75b2..4607655 100644
---- a/lib/ssl/sslimpl.h
-+++ b/lib/ssl/sslimpl.h
-@@ -710,6 +710,14 @@ struct sslSessionIDStr {
- 
-             SECItem srvName;
- 
-+            /* originalHandshakeHash contains the hash of the original, full
-+             * handshake prior to the server's final flow. This is either a
-+             * SHA-1/MD5 combination (for TLS < 1.2) or the TLS PRF hash (for
-+             * TLS 1.2). This is recorded and used only when ChannelID is
-+             * negotiated as it's used to bind the ChannelID signature on the
-+             * resumption handshake to the original handshake. */
-+            SECItem originalHandshakeHash;
-+
-             /* Signed certificate timestamps received in a TLS extension.
-             ** (used only in client).
-             */
-@@ -1025,6 +1033,9 @@ struct ssl3StateStr {
-     CERTCertificateList *clientCertChain; /* used by client */
-     PRBool sendEmptyCert;                 /* used by client */
- 
-+    SECKEYPrivateKey *channelID;   /* used by client */
-+    SECKEYPublicKey *channelIDPub; /* used by client */
-+
-     int policy;
-     /* This says what cipher suites we can do, and should
-      * be either SSL_ALLOWED or SSL_RESTRICTED
-@@ -1322,6 +1333,9 @@ struct sslSocketStr {
-     SSLNextProtoCallback nextProtoCallback;
-     void *nextProtoArg;
- 
-+    SSLClientChannelIDCallback getChannelID;
-+    void *getChannelIDArg;
-+
-     PRIntervalTime rTimeout; /* timeout for NSPR I/O */
-     PRIntervalTime wTimeout; /* timeout for NSPR I/O */
-     PRIntervalTime cTimeout; /* timeout for NSPR I/O */
-@@ -1712,6 +1726,12 @@ extern SECStatus ssl3_RestartHandshakeAfterCertReq(struct sslSocketStr *ss,
-                                                    CERTCertificate *cert,
-                                                    SECKEYPrivateKey *key,
-                                                    CERTCertificateList *certChain);
-+
-+extern SECStatus ssl3_RestartHandshakeAfterChannelIDReq(
-+    sslSocket *ss,
-+    SECKEYPublicKey *channelIDPub,
-+    SECKEYPrivateKey *channelID);
-+
- extern SECStatus ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error);
- 
- /*
-diff --git a/lib/ssl/sslnonce.c b/lib/ssl/sslnonce.c
-index 3216892..4804cb8 100644
---- a/lib/ssl/sslnonce.c
-+++ b/lib/ssl/sslnonce.c
-@@ -186,6 +186,9 @@ ssl_DestroySID(sslSessionID *sid)
-         if (sid->u.ssl3.signedCertTimestamps.data) {
-             SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE);
-         }
-+        if (sid->u.ssl3.originalHandshakeHash.data) {
-+            SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE);
-+        }
- 
-         if (sid->u.ssl3.lock) {
-             PR_DestroyRWLock(sid->u.ssl3.lock);
-diff --git a/lib/ssl/sslsecur.c b/lib/ssl/sslsecur.c
-index a087ffc..7ff0a2c 100644
---- a/lib/ssl/sslsecur.c
-+++ b/lib/ssl/sslsecur.c
-@@ -1601,6 +1601,41 @@ SSL_RestartHandshakeAfterCertReq(PRFileDesc *fd,
-     return ret;
- }
- 
-+SECStatus
-+SSL_RestartHandshakeAfterChannelIDReq(PRFileDesc *fd,
-+                                      SECKEYPublicKey *channelIDPub,
-+                                      SECKEYPrivateKey *channelID)
-+{
-+    sslSocket *ss = ssl_FindSocket(fd);
-+    SECStatus ret;
-+
-+    if (!ss) {
-+        SSL_DBG(("%d: SSL[%d]: bad socket in"
-+                 " SSL_RestartHandshakeAfterChannelIDReq",
-+                 SSL_GETPID(), fd));
-+        goto loser;
-+    }
-+
-+    ssl_Get1stHandshakeLock(ss);
-+
-+    if (ss->version < SSL_LIBRARY_VERSION_3_0) {
-+        PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
-+        ssl_Release1stHandshakeLock(ss);
-+        goto loser;
-+    }
-+
-+    ret = ssl3_RestartHandshakeAfterChannelIDReq(ss, channelIDPub,
-+                                                 channelID);
-+    ssl_Release1stHandshakeLock(ss);
-+
-+    return ret;
-+
-+loser:
-+    SECKEY_DestroyPublicKey(channelIDPub);
-+    SECKEY_DestroyPrivateKey(channelID);
-+    return SECFailure;
-+}
-+
- /* DO NOT USE. This function was exported in ssl.def with the wrong signature;
-  * this implementation exists to maintain link-time compatibility.
-  */
-diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
-index 7f97b14..84c78b3 100644
---- a/lib/ssl/sslsock.c
-+++ b/lib/ssl/sslsock.c
-@@ -315,6 +315,8 @@ ssl_DupSocket(sslSocket *os)
-             ss->canFalseStartCallback = os->canFalseStartCallback;
-             ss->canFalseStartCallbackData = os->canFalseStartCallbackData;
-             ss->pkcs11PinArg = os->pkcs11PinArg;
-+            ss->getChannelID = os->getChannelID;
-+            ss->getChannelIDArg = os->getChannelIDArg;
- 
-             /* Create security data */
-             rv = ssl_CopySecurityInfo(ss, os);
-@@ -2155,6 +2157,10 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
-         ss->handshakeCallbackData = sm->handshakeCallbackData;
-     if (sm->pkcs11PinArg)
-         ss->pkcs11PinArg = sm->pkcs11PinArg;
-+    if (sm->getChannelID)
-+        ss->getChannelID = sm->getChannelID;
-+    if (sm->getChannelIDArg)
-+        ss->getChannelIDArg = sm->getChannelIDArg;
-     return fd;
- loser:
-     return NULL;
-@@ -3643,6 +3649,8 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
-         ss->badCertArg = NULL;
-         ss->pkcs11PinArg = NULL;
-         ss->ephemeralECDHKeyPair = NULL;
-+        ss->getChannelID = NULL;
-+        ss->getChannelIDArg = NULL;
- 
-         ssl_ChooseOps(ss);
-         ssl2_InitSocketPolicy(ss);
-diff --git a/lib/ssl/sslt.h b/lib/ssl/sslt.h
-index bf722b5..6f26e5f 100644
---- a/lib/ssl/sslt.h
-+++ b/lib/ssl/sslt.h
-@@ -249,11 +249,12 @@ typedef enum {
-     ssl_session_ticket_xtn = 35,
-     ssl_tls13_key_share_xtn = 40, /* unofficial TODO(ekr) */
-     ssl_next_proto_nego_xtn = 13172,
-+    ssl_channel_id_xtn = 30032,
-     ssl_renegotiation_info_xtn = 0xff01,
-     ssl_tls13_draft_version_xtn = 0xff02 /* experimental number */
- } SSLExtensionType;
- 
--#define SSL_MAX_EXTENSIONS 14 /* doesn't include ssl_padding_xtn. */
-+#define SSL_MAX_EXTENSIONS 15 /* doesn't include ssl_padding_xtn. */
- 
- typedef enum {
-     ssl_dhe_group_none = 0,
diff --git a/net/third_party/nss/patches/cipherorder.patch b/net/third_party/nss/patches/cipherorder.patch
deleted file mode 100644
index 26e8326..0000000
--- a/net/third_party/nss/patches/cipherorder.patch
+++ /dev/null
@@ -1,106 +0,0 @@
-diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
-index 3550580..70665a1 100644
---- a/lib/ssl/ssl.h
-+++ b/lib/ssl/ssl.h
-@@ -387,6 +387,13 @@ SSL_IMPORT SECStatus SSL_DHEGroupPrefSet(PRFileDesc *fd,
- */
- SSL_IMPORT SECStatus SSL_EnableWeakDHEPrimeGroup(PRFileDesc *fd, PRBool enabled);
- 
-+/* SSL_CipherOrderSet sets the cipher suite preference order from |ciphers|,
-+ * which must be an array of cipher suite ids of length |len|. All the given
-+ * cipher suite ids must appear in the array that is returned by
-+ * |SSL_GetImplementedCiphers| and may only appear once, at most. */
-+SSL_IMPORT SECStatus SSL_CipherOrderSet(PRFileDesc *fd, const PRUint16 *ciphers,
-+                                        unsigned int len);
-+
- /* SSLChannelBindingType enumerates the types of supported channel binding
-  * values. See RFC 5929. */
- typedef enum SSLChannelBindingType {
-diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index d7d186a..b100b9b 100644
---- a/lib/ssl/ssl3con.c
-+++ b/lib/ssl/ssl3con.c
-@@ -13797,6 +13797,46 @@ SSL_SignatureMaxCount()
-     return MAX_SIGNATURE_ALGORITHMS;
- }
- 
-+SECStatus
-+ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *ciphers, unsigned int len)
-+{
-+    /* |i| iterates over |ciphers| while |done| and |j| iterate over
-+     * |ss->cipherSuites|. */
-+    unsigned int i, done;
-+
-+    for (i = done = 0; i < len; i++) {
-+        PRUint16 id = ciphers[i];
-+        unsigned int existingIndex, j;
-+        PRBool found = PR_FALSE;
-+
-+        for (j = done; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
-+            if (ss->cipherSuites[j].cipher_suite == id) {
-+                existingIndex = j;
-+                found = PR_TRUE;
-+                break;
-+            }
-+        }
-+
-+        if (!found) {
-+            continue;
-+        }
-+
-+        if (existingIndex != done) {
-+            const ssl3CipherSuiteCfg temp = ss->cipherSuites[done];
-+            ss->cipherSuites[done] = ss->cipherSuites[existingIndex];
-+            ss->cipherSuites[existingIndex] = temp;
-+        }
-+        done++;
-+    }
-+
-+    /* Disable all cipher suites that weren't included. */
-+    for (; done < ssl_V3_SUITES_IMPLEMENTED; done++) {
-+        ss->cipherSuites[done].enabled = 0;
-+    }
-+
-+    return SECSuccess;
-+}
-+
- /* copy global default policy into socket. */
- void
- ssl3_InitSocketPolicy(sslSocket *ss)
-diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index c0e3a0b..f56ab53 100644
---- a/lib/ssl/sslimpl.h
-+++ b/lib/ssl/sslimpl.h
-@@ -1835,6 +1835,8 @@ extern SECStatus ssl3_CipherPrefSet(sslSocket *ss, ssl3CipherSuite which, PRBool
- extern SECStatus ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *on);
- extern SECStatus ssl2_CipherPrefSet(sslSocket *ss, PRInt32 which, PRBool enabled);
- extern SECStatus ssl2_CipherPrefGet(sslSocket *ss, PRInt32 which, PRBool *enabled);
-+extern SECStatus ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *cipher,
-+                                     unsigned int len);
- 
- extern SECStatus ssl3_SetPolicy(ssl3CipherSuite which, PRInt32 policy);
- extern SECStatus ssl3_GetPolicy(ssl3CipherSuite which, PRInt32 *policy);
-diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
-index e312d82..e82c916 100644
---- a/lib/ssl/sslsock.c
-+++ b/lib/ssl/sslsock.c
-@@ -1500,6 +1500,19 @@ SSL_CipherPrefSet(PRFileDesc *fd, PRInt32 which, PRBool enabled)
- }
- 
- SECStatus
-+SSL_CipherOrderSet(PRFileDesc *fd, const PRUint16 *ciphers, unsigned int len)
-+{
-+    sslSocket *ss = ssl_FindSocket(fd);
-+
-+    if (!ss) {
-+        SSL_DBG(("%d: SSL[%d]: bad socket in CipherOrderSet", SSL_GETPID(),
-+                 fd));
-+        return SECFailure;
-+    }
-+    return ssl3_CipherOrderSet(ss, ciphers, len);
-+}
-+
-+SECStatus
- SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled)
- {
-     SECStatus rv;
diff --git a/net/third_party/nss/patches/didhandshakeresume.patch b/net/third_party/nss/patches/didhandshakeresume.patch
deleted file mode 100644
index 8acb6e71..0000000
--- a/net/third_party/nss/patches/didhandshakeresume.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
-index 3974ee8..e905aab 100644
---- a/lib/ssl/ssl.h
-+++ b/lib/ssl/ssl.h
-@@ -1123,6 +1123,9 @@ SSL_IMPORT SECStatus SSL_HandshakeNegotiatedExtension(PRFileDesc *socket,
-                                                       SSLExtensionType extId,
-                                                       PRBool *yes);
- 
-+SSL_IMPORT SECStatus SSL_HandshakeResumedSession(PRFileDesc *fd,
-+                                                 PRBool *last_handshake_resumed);
-+
- /*
- ** How long should we wait before retransmitting the next flight of
- ** the DTLS handshake? Returns SECFailure if not DTLS or not in a
-diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
-index cc15406..601df2a 100644
---- a/lib/ssl/sslsock.c
-+++ b/lib/ssl/sslsock.c
-@@ -2481,6 +2481,21 @@ SSL_PeerStapledOCSPResponses(PRFileDesc *fd)
-     return &ss->sec.ci.sid->peerCertStatus;
- }
- 
-+SECStatus
-+SSL_HandshakeResumedSession(PRFileDesc *fd, PRBool *handshake_resumed)
-+{
-+    sslSocket *ss = ssl_FindSocket(fd);
-+
-+    if (!ss) {
-+        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_HandshakeResumedSession",
-+                 SSL_GETPID(), fd));
-+        return SECFailure;
-+    }
-+
-+    *handshake_resumed = ss->ssl3.hs.isResuming;
-+    return SECSuccess;
-+}
-+
- /************************************************************************/
- /* The following functions are the TOP LEVEL SSL functions.
- ** They all get called through the NSPRIOMethods table below.
diff --git a/net/third_party/nss/patches/getrequestedclientcerttypes.patch b/net/third_party/nss/patches/getrequestedclientcerttypes.patch
deleted file mode 100644
index d19c2280..0000000
--- a/net/third_party/nss/patches/getrequestedclientcerttypes.patch
+++ /dev/null
@@ -1,93 +0,0 @@
-diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
-index e905aab..9e57220 100644
---- a/lib/ssl/ssl.h
-+++ b/lib/ssl/ssl.h
-@@ -896,6 +896,17 @@ SSL_IMPORT SECStatus SSL_ReHandshakeWithTimeout(PRFileDesc *fd,
-                                                 PRBool flushCache,
-                                                 PRIntervalTime timeout);
- 
-+/* Returns a SECItem containing the certificate_types field of the
-+** CertificateRequest message.  Each byte of the data is a TLS
-+** ClientCertificateType value, and they are ordered from most preferred to
-+** least.  This function should only be called from the
-+** SSL_GetClientAuthDataHook callback, and will return NULL if called at any
-+** other time.  The returned value is valid only until the callback returns, and
-+** should not be freed.
-+*/
-+SSL_IMPORT const SECItem *
-+SSL_GetRequestedClientCertificateTypes(PRFileDesc *fd);
-+
- #ifdef SSL_DEPRECATED_FUNCTION
- /* deprecated!
- ** For the server, request a new handshake.  For the client, begin a new
-diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index b8d4784..784f59b 100644
---- a/lib/ssl/ssl3con.c
-+++ b/lib/ssl/ssl3con.c
-@@ -7674,6 +7674,9 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-     if (rv != SECSuccess)
-         goto loser; /* malformed, alert has been sent */
- 
-+    PORT_Assert(!ss->requestedCertTypes);
-+    ss->requestedCertTypes = &cert_types;
-+
-     if (isTLS12) {
-         rv = ssl3_ConsumeHandshakeVariable(ss, &algorithms, 2, &b, &length);
-         if (rv != SECSuccess)
-@@ -7723,6 +7726,7 @@ loser:
-     PORT_SetError(errCode);
-     rv = SECFailure;
- done:
-+    ss->requestedCertTypes = NULL;
-     if (arena != NULL)
-         PORT_FreeArena(arena, PR_FALSE);
-     return rv;
-diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index 10361a0..5f0e6c9 100644
---- a/lib/ssl/sslimpl.h
-+++ b/lib/ssl/sslimpl.h
-@@ -1296,6 +1296,10 @@ struct sslSocketStr {
-     unsigned int sizeCipherSpecs;
-     const unsigned char *preferredCipher;
- 
-+    /* TLS ClientCertificateTypes requested during HandleCertificateRequest. */
-+    /* Will be NULL at all other times. */
-+    const SECItem *requestedCertTypes;
-+
-     ssl3KeyPair *stepDownKeyPair; /* RSA step down keys */
- 
-     const ssl3DHParams *dheParams; /* DHE param */
-diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
-index 601df2a..7f97b14 100644
---- a/lib/ssl/sslsock.c
-+++ b/lib/ssl/sslsock.c
-@@ -2496,6 +2496,21 @@ SSL_HandshakeResumedSession(PRFileDesc *fd, PRBool *handshake_resumed)
-     return SECSuccess;
- }
- 
-+const SECItem *
-+SSL_GetRequestedClientCertificateTypes(PRFileDesc *fd)
-+{
-+    sslSocket *ss = ssl_FindSocket(fd);
-+
-+    if (!ss) {
-+        SSL_DBG(("%d: SSL[%d]: bad socket in "
-+                 "SSL_GetRequestedClientCertificateTypes",
-+                 SSL_GETPID(), fd));
-+        return NULL;
-+    }
-+
-+    return ss->requestedCertTypes;
-+}
-+
- /************************************************************************/
- /* The following functions are the TOP LEVEL SSL functions.
- ** They all get called through the NSPRIOMethods table below.
-@@ -3610,6 +3625,7 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
-             sc->serverKeyBits = 0;
-             ss->certStatusArray[i] = NULL;
-         }
-+        ss->requestedCertTypes = NULL;
-         ss->stepDownKeyPair = NULL;
- 
-         ss->dheParams = NULL;
diff --git a/net/third_party/nss/patches/ignorechangecipherspec.patch b/net/third_party/nss/patches/ignorechangecipherspec.patch
deleted file mode 100644
index b8e176d..0000000
--- a/net/third_party/nss/patches/ignorechangecipherspec.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-Index: ssl/ssl3con.c
-===================================================================
---- ssl/ssl3con.c	(revision 274314)
-+++ ssl/ssl3con.c	(working copy)
-@@ -3621,6 +3621,14 @@
- 		SSL_GETPID(), ss->fd));
- 
-     if (ws != wait_change_cipher) {
-+	if (IS_DTLS(ss)) {
-+	    /* Ignore this because it's out of order. */
-+	    SSL_TRC(3, ("%d: SSL3[%d]: discard out of order "
-+			"DTLS change_cipher_spec",
-+			SSL_GETPID(), ss->fd));
-+	    buf->len = 0;
-+	    return SECSuccess;
-+	}
- 	(void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- 	PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER);
- 	return SECFailure;
diff --git a/net/third_party/nss/patches/nobypass.patch b/net/third_party/nss/patches/nobypass.patch
deleted file mode 100644
index 8896d36..0000000
--- a/net/third_party/nss/patches/nobypass.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index 7649abe..b6f4987 100644
---- a/lib/ssl/ssl3con.c
-+++ b/lib/ssl/ssl3con.c
-@@ -2297,6 +2297,7 @@ fail:
-     return SECFailure;
- }
- 
-+#ifndef NO_PKCS11_BYPASS
- /* Returns whether we can bypass PKCS#11 for a given cipher algorithm.
-  *
-  * We do not support PKCS#11 bypass for ChaCha20/Poly1305.
-@@ -2311,6 +2312,7 @@ ssl3_CanBypassCipher(SSLCipherAlgorithm calg)
-             return PR_TRUE;
-     }
- }
-+#endif
- 
- /* Complete the initialization of all keys, ciphers, MACs and their contexts
-  * for the pending Cipher Spec.
diff --git a/net/third_party/nss/patches/reorderextensions.patch b/net/third_party/nss/patches/reorderextensions.patch
deleted file mode 100644
index 0779e69..0000000
--- a/net/third_party/nss/patches/reorderextensions.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-diff --git a/lib/ssl/ssl3ext.c b/lib/ssl/ssl3ext.c
-index 2ffe77b..3b48c9e 100644
---- a/lib/ssl/ssl3ext.c
-+++ b/lib/ssl/ssl3ext.c
-@@ -336,10 +336,14 @@ static const ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS]
-       { ssl_use_srtp_xtn, &ssl3_ClientSendUseSRTPXtn },
-       { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
-       { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
--      { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
-       { ssl_tls13_draft_version_xtn, &ssl3_ClientSendDraftVersionXtn },
-       { ssl_signed_cert_timestamp_xtn, &ssl3_ClientSendSignedCertTimestampXtn },
-       { ssl_tls13_key_share_xtn, &tls13_ClientSendKeyShareXtn },
-+      /* Some servers (e.g. WebSphere Application Server 7.0 and Tomcat) will
-+       * time out or terminate the connection if the last extension in the
-+       * client hello is empty. They are not intolerant of TLS 1.2, so list
-+       * signature_algorithms at the end. See bug 1243641. */
-+      { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
-       /* any extra entries will appear as { 0, NULL }    */
-     };
- 
-@@ -2690,9 +2694,11 @@ ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength)
-     }
- 
-     extensionLength = 512 - recordLength;
--    /* Extensions take at least four bytes to encode. */
--    if (extensionLength < 4) {
--        extensionLength = 4;
-+    /* Extensions take at least four bytes to encode. Always include at least
-+     * one byte of data if including the extension. WebSphere Application
-+     * Server 7.0 is intolerant to the last extension being zero-length. */
-+    if (extensionLength < 4 + 1) {
-+        extensionLength = 4 + 1;
-     }
- 
-     return extensionLength;
diff --git a/net/third_party/nss/patches/restartclientauth.patch b/net/third_party/nss/patches/restartclientauth.patch
deleted file mode 100644
index 811e98c..0000000
--- a/net/third_party/nss/patches/restartclientauth.patch
+++ /dev/null
@@ -1,213 +0,0 @@
-diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
-index 9e57220..aa4a3e5 100644
---- a/lib/ssl/ssl.h
-+++ b/lib/ssl/ssl.h
-@@ -516,6 +516,11 @@ SSL_IMPORT SECStatus SSL_ForceHandshake(PRFileDesc *fd);
- SSL_IMPORT SECStatus SSL_ForceHandshakeWithTimeout(PRFileDesc *fd,
-                                                    PRIntervalTime timeout);
- 
-+SSL_IMPORT SECStatus SSL_RestartHandshakeAfterCertReq(PRFileDesc *fd,
-+                                                      CERTCertificate *cert,
-+                                                      SECKEYPrivateKey *key,
-+                                                      CERTCertificateList *certChain);
-+
- /*
- ** Query security status of socket. *on is set to one if security is
- ** enabled. *keySize will contain the stream key size used. *issuer will
-diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index 784f59b..2a2e644 100644
---- a/lib/ssl/ssl3con.c
-+++ b/lib/ssl/ssl3con.c
-@@ -7803,6 +7803,85 @@ ssl3_CompleteHandleCertificateRequest(sslSocket *ss, SECItem *algorithms,
-     return rv;
- }
- 
-+/*
-+ * attempt to restart the handshake after asynchronously handling
-+ * a request for the client's certificate.
-+ *
-+ * inputs:
-+ *	cert	Client cert chosen by application.
-+ *		Note: ssl takes this reference, and does not bump the
-+ *		reference count.  The caller should drop its reference
-+ *		without calling CERT_DestroyCert after calling this function.
-+ *
-+ *	key	Private key associated with cert.  This function takes
-+ *		ownership of the private key, so the caller should drop its
-+ *		reference without destroying the private key after this
-+ *		function returns.
-+ *
-+ *	certChain  DER-encoded certs, client cert and its signers.
-+ *		Note: ssl takes this reference, and does not copy the chain.
-+ *		The caller should drop its reference without destroying the
-+ *		chain.  SSL will free the chain when it is done with it.
-+ *
-+ * Return value: XXX
-+ *
-+ * XXX This code only works on the initial handshake on a connection, XXX
-+ *     It does not work on a subsequent handshake (redo).
-+ *
-+ * Caller holds 1stHandshakeLock.
-+ */
-+SECStatus
-+ssl3_RestartHandshakeAfterCertReq(sslSocket *ss,
-+                                  CERTCertificate *cert,
-+                                  SECKEYPrivateKey *key,
-+                                  CERTCertificateList *certChain)
-+{
-+    SECStatus rv = SECSuccess;
-+
-+    /* XXX This code only works on the initial handshake on a connection,
-+    ** XXX It does not work on a subsequent handshake (redo).
-+    */
-+    if (ss->handshake != 0) {
-+        ss->handshake = ssl_GatherRecord1stHandshake;
-+        ss->ssl3.clientCertificate = cert;
-+        ss->ssl3.clientPrivateKey = key;
-+        ss->ssl3.clientCertChain = certChain;
-+        if (!cert || !key || !certChain) {
-+            /* we are missing the key, cert, or cert chain */
-+            if (ss->ssl3.clientCertificate) {
-+                CERT_DestroyCertificate(ss->ssl3.clientCertificate);
-+                ss->ssl3.clientCertificate = NULL;
-+            }
-+            if (ss->ssl3.clientPrivateKey) {
-+                SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
-+                ss->ssl3.clientPrivateKey = NULL;
-+            }
-+            if (ss->ssl3.clientCertChain != NULL) {
-+                CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
-+                ss->ssl3.clientCertChain = NULL;
-+            }
-+            if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0) {
-+                ss->ssl3.sendEmptyCert = PR_TRUE;
-+            } else {
-+                (void)SSL3_SendAlert(ss, alert_warning, no_certificate);
-+            }
-+        }
-+    } else {
-+        if (cert) {
-+            CERT_DestroyCertificate(cert);
-+        }
-+        if (key) {
-+            SECKEY_DestroyPrivateKey(key);
-+        }
-+        if (certChain) {
-+            CERT_DestroyCertificateList(certChain);
-+        }
-+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-+        rv = SECFailure;
-+    }
-+    return rv;
-+}
-+
- static SECStatus
- ssl3_CheckFalseStart(sslSocket *ss)
- {
-diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index 5f0e6c9..dad75b2 100644
---- a/lib/ssl/sslimpl.h
-+++ b/lib/ssl/sslimpl.h
-@@ -1702,16 +1702,16 @@ extern SECStatus ssl3_MasterSecretDeriveBypass(ssl3CipherSpec *pwSpec,
- /* These functions are called from secnav, even though they're "private". */
- 
- extern int ssl2_SendErrorMessage(struct sslSocketStr *ss, int error);
--extern int SSL_RestartHandshakeAfterCertReq(struct sslSocketStr *ss,
--                                            CERTCertificate *cert,
--                                            SECKEYPrivateKey *key,
--                                            CERTCertificateList *certChain);
- extern sslSocket *ssl_FindSocket(PRFileDesc *fd);
- extern void ssl_FreeSocket(struct sslSocketStr *ssl);
- extern SECStatus SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level,
-                                 SSL3AlertDescription desc);
- extern SECStatus ssl3_DecodeError(sslSocket *ss);
- 
-+extern SECStatus ssl3_RestartHandshakeAfterCertReq(struct sslSocketStr *ss,
-+                                                   CERTCertificate *cert,
-+                                                   SECKEYPrivateKey *key,
-+                                                   CERTCertificateList *certChain);
- extern SECStatus ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error);
- 
- /*
-diff --git a/lib/ssl/sslsecur.c b/lib/ssl/sslsecur.c
-index 5773748..a087ffc 100644
---- a/lib/ssl/sslsecur.c
-+++ b/lib/ssl/sslsecur.c
-@@ -1535,17 +1535,70 @@ SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHandle)
-     return SECSuccess;
- }
- 
--/* DO NOT USE. This function was exported in ssl.def with the wrong signature;
-- * this implementation exists to maintain link-time compatibility.
-- */
--int
--SSL_RestartHandshakeAfterCertReq(sslSocket *ss,
-+/*
-+ * attempt to restart the handshake after asynchronously handling
-+ * a request for the client's certificate.
-+ *
-+ * inputs:  
-+ *	cert	Client cert chosen by application.
-+ *		Note: ssl takes this reference, and does not bump the 
-+ *		reference count.  The caller should drop its reference
-+ *		without calling CERT_DestroyCertificate after calling this
-+ *		function.
-+ *
-+ *	key	Private key associated with cert.  This function takes
-+ *		ownership of the private key, so the caller should drop its
-+ *		reference without destroying the private key after this
-+ *		function returns.
-+ *
-+ *	certChain  Chain of signers for cert.  
-+ *		Note: ssl takes this reference, and does not copy the chain.
-+ *		The caller should drop its reference without destroying the 
-+ *		chain.  SSL will free the chain when it is done with it.
-+ *
-+ * Return value: XXX
-+ *
-+ * XXX This code only works on the initial handshake on a connection, XXX
-+ *     It does not work on a subsequent handshake (redo).
-+   */
-+SECStatus
-+SSL_RestartHandshakeAfterCertReq(PRFileDesc *fd,
-                                  CERTCertificate *cert,
-                                  SECKEYPrivateKey *key,
-                                  CERTCertificateList *certChain)
- {
--    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
--    return -1;
-+    sslSocket *ss = ssl_FindSocket(fd);
-+    SECStatus ret;
-+
-+    if (!ss) {
-+        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RestartHandshakeAfterCertReq",
-+                 SSL_GETPID(), fd));
-+        if (cert) {
-+            CERT_DestroyCertificate(cert);
-+        }
-+        if (key) {
-+            SECKEY_DestroyPrivateKey(key);
-+        }
-+        if (certChain) {
-+            CERT_DestroyCertificateList(certChain);
-+        }
-+        return SECFailure;
-+    }
-+
-+    ssl_Get1stHandshakeLock(ss); /************************************/
-+
-+    if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
-+        ret = ssl3_RestartHandshakeAfterCertReq(ss, cert, key, certChain);
-+    } else {
-+        if (certChain != NULL) {
-+            CERT_DestroyCertificateList(certChain);
-+        }
-+        PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
-+        ret = SECFailure;
-+    }
-+
-+    ssl_Release1stHandshakeLock(ss); /************************************/
-+    return ret;
- }
- 
- /* DO NOT USE. This function was exported in ssl.def with the wrong signature;
diff --git a/net/third_party/nss/patches/secretexporterlocks.patch b/net/third_party/nss/patches/secretexporterlocks.patch
deleted file mode 100644
index a95ef278..0000000
--- a/net/third_party/nss/patches/secretexporterlocks.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-diff --git a/lib/ssl/sslinfo.c b/lib/ssl/sslinfo.c
-index 527b1a4..c59879c 100644
---- a/lib/ssl/sslinfo.c
-+++ b/lib/ssl/sslinfo.c
-@@ -406,8 +406,13 @@ SSL_ExportKeyingMaterial(PRFileDesc *fd,
-         return SECFailure;
-     }
- 
-+    ssl_GetRecvBufLock(ss);
-+    ssl_GetSSL3HandshakeLock(ss);
-+
-     if (ss->version < SSL_LIBRARY_VERSION_3_1_TLS) {
-         PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION);
-+        ssl_ReleaseSSL3HandshakeLock(ss);
-+        ssl_ReleaseRecvBufLock(ss);
-         return SECFailure;
-     }
- 
-@@ -418,6 +423,8 @@ SSL_ExportKeyingMaterial(PRFileDesc *fd,
-     }
-     val = PORT_Alloc(valLen);
-     if (!val) {
-+        ssl_ReleaseSSL3HandshakeLock(ss);
-+        ssl_ReleaseRecvBufLock(ss);
-         return SECFailure;
-     }
-     i = 0;
-@@ -445,6 +452,8 @@ SSL_ExportKeyingMaterial(PRFileDesc *fd,
-                                          valLen, out, outLen);
-     }
-     ssl_ReleaseSpecReadLock(ss);
-+    ssl_ReleaseSSL3HandshakeLock(ss);
-+    ssl_ReleaseRecvBufLock(ss);
- 
-     PORT_ZFree(val, valLen);
-     return rv;
diff --git a/net/third_party/nss/patches/sessioncache.patch b/net/third_party/nss/patches/sessioncache.patch
deleted file mode 100644
index 6e100c6..0000000
--- a/net/third_party/nss/patches/sessioncache.patch
+++ /dev/null
@@ -1,90 +0,0 @@
-diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
-index 70665a1..de5078b 100644
---- a/lib/ssl/ssl.h
-+++ b/lib/ssl/ssl.h
-@@ -973,6 +973,18 @@ SSL_IMPORT int SSL_DataPending(PRFileDesc *fd);
- SSL_IMPORT SECStatus SSL_InvalidateSession(PRFileDesc *fd);
- 
- /*
-+** Cache the SSL session associated with fd, if it has not already been cached.
-+*/
-+SSL_IMPORT SECStatus SSL_CacheSession(PRFileDesc *fd);
-+
-+/*
-+** Cache the SSL session associated with fd, if it has not already been cached.
-+** This function may only be called when processing within a callback assigned
-+** via SSL_HandshakeCallback
-+*/
-+SSL_IMPORT SECStatus SSL_CacheSessionUnlocked(PRFileDesc *fd);
-+
-+/*
- ** Return a SECItem containing the SSL session ID associated with the fd.
- */
- SSL_IMPORT SECItem *SSL_GetSessionID(PRFileDesc *fd);
-diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index b100b9b..7649abe 100644
---- a/lib/ssl/ssl3con.c
-+++ b/lib/ssl/ssl3con.c
-@@ -12397,7 +12397,7 @@ ssl3_FinishHandshake(sslSocket *ss)
-         ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE;
-     }
- 
--    if (ss->ssl3.hs.cacheSID) {
-+    if (ss->ssl3.hs.cacheSID && ss->sec.isServer) {
-         PORT_Assert(ss->sec.ci.sid->cached == never_cached);
-         (*ss->sec.cache)(ss->sec.ci.sid);
-         ss->ssl3.hs.cacheSID = PR_FALSE;
-diff --git a/lib/ssl/sslsecur.c b/lib/ssl/sslsecur.c
-index 7ff0a2c..129f1f3 100644
---- a/lib/ssl/sslsecur.c
-+++ b/lib/ssl/sslsecur.c
-@@ -1486,6 +1486,49 @@ SSL_InvalidateSession(PRFileDesc *fd)
-     return rv;
- }
- 
-+static void
-+ssl3_CacheSessionUnlocked(sslSocket *ss)
-+{
-+    PORT_Assert(!ss->sec.isServer);
-+
-+    if (ss->ssl3.hs.cacheSID) {
-+        ss->sec.cache(ss->sec.ci.sid);
-+        ss->ssl3.hs.cacheSID = PR_FALSE;
-+    }
-+}
-+
-+SECStatus
-+SSL_CacheSession(PRFileDesc *fd)
-+{
-+    sslSocket *ss = ssl_FindSocket(fd);
-+    SECStatus rv = SECFailure;
-+
-+    if (ss) {
-+        ssl_Get1stHandshakeLock(ss);
-+        ssl_GetSSL3HandshakeLock(ss);
-+
-+        ssl3_CacheSessionUnlocked(ss);
-+        rv = SECSuccess;
-+
-+        ssl_ReleaseSSL3HandshakeLock(ss);
-+        ssl_Release1stHandshakeLock(ss);
-+    }
-+    return rv;
-+}
-+
-+SECStatus
-+SSL_CacheSessionUnlocked(PRFileDesc *fd)
-+{
-+    sslSocket *ss = ssl_FindSocket(fd);
-+    SECStatus rv = SECFailure;
-+
-+    if (ss) {
-+        ssl3_CacheSessionUnlocked(ss);
-+        rv = SECSuccess;
-+    }
-+    return rv;
-+}
-+
- SECItem *
- SSL_GetSessionID(PRFileDesc *fd)
- {
diff --git a/net/third_party/nss/patches/tlsunique.patch b/net/third_party/nss/patches/tlsunique.patch
deleted file mode 100644
index d004ca7..0000000
--- a/net/third_party/nss/patches/tlsunique.patch
+++ /dev/null
@@ -1,156 +0,0 @@
-diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
-index 870a8cc..3550580 100644
---- a/lib/ssl/ssl.h
-+++ b/lib/ssl/ssl.h
-@@ -387,6 +387,27 @@ SSL_IMPORT SECStatus SSL_DHEGroupPrefSet(PRFileDesc *fd,
- */
- SSL_IMPORT SECStatus SSL_EnableWeakDHEPrimeGroup(PRFileDesc *fd, PRBool enabled);
- 
-+/* SSLChannelBindingType enumerates the types of supported channel binding
-+ * values. See RFC 5929. */
-+typedef enum SSLChannelBindingType {
-+    SSL_CHANNEL_BINDING_TLS_UNIQUE = 1,
-+} SSLChannelBindingType;
-+
-+/* SSL_GetChannelBinding copies the requested channel binding value, as defined
-+ * in RFC 5929, into |out|. The full length of the binding value is written
-+ * into |*outLen|.
-+ *
-+ * At most |outLenMax| bytes of data are copied. If |outLenMax| is
-+ * insufficient then the function returns SECFailure and sets the error to
-+ * SEC_ERROR_OUTPUT_LEN, but |*outLen| is still set.
-+ *
-+ * This call will fail if made during a renegotiation. */
-+SSL_IMPORT SECStatus SSL_GetChannelBinding(PRFileDesc *fd,
-+                                           SSLChannelBindingType binding_type,
-+                                           unsigned char *out,
-+                                           unsigned int *outLen,
-+                                           unsigned int outLenMax);
-+
- /* SSL Version Range API
- **
- ** This API should be used to control SSL 3.0 & TLS support instead of the
-diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index a2beec2..1394542 100644
---- a/lib/ssl/ssl3con.c
-+++ b/lib/ssl/ssl3con.c
-@@ -13808,6 +13808,69 @@ ssl3_InitSocketPolicy(sslSocket *ss)
-     ss->ssl3.signatureAlgorithmCount = PR_ARRAY_SIZE(defaultSignatureAlgorithms);
- }
- 
-+SECStatus
-+ssl3_GetTLSUniqueChannelBinding(sslSocket *ss,
-+                                unsigned char *out,
-+                                unsigned int *outLen,
-+                                unsigned int outLenMax)
-+{
-+    PRBool isTLS;
-+    int index = 0;
-+    unsigned int len;
-+    SECStatus rv = SECFailure;
-+
-+    *outLen = 0;
-+
-+    ssl_GetSSL3HandshakeLock(ss);
-+
-+    ssl_GetSpecReadLock(ss);
-+    isTLS = (PRBool)(ss->ssl3.cwSpec->version > SSL_LIBRARY_VERSION_3_0);
-+    ssl_ReleaseSpecReadLock(ss);
-+
-+    /* The tls-unique channel binding is the first Finished structure in the
-+     * handshake. In the case of a resumption, that's the server's Finished.
-+     * Otherwise, it's the client's Finished. */
-+    len = ss->ssl3.hs.finishedBytes;
-+
-+    /* Sending or receiving a Finished message will set finishedBytes to a
-+     * non-zero value. */
-+    if (len == 0) {
-+        PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
-+        goto loser;
-+    }
-+
-+    /* If we are in the middle of a renegotiation then the channel binding
-+     * value is poorly defined and depends on the direction that it will be
-+     * used on. Therefore we simply return an error in this case. */
-+    if (ss->firstHsDone && ss->ssl3.hs.ws != idle_handshake) {
-+        PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
-+        goto loser;
-+    }
-+
-+    /* If resuming, then we want the second Finished value in the array, which
-+     * is the server's */
-+    if (ss->ssl3.hs.isResuming)
-+        index = 1;
-+
-+    *outLen = len;
-+    if (outLenMax < len) {
-+        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
-+        goto loser;
-+    }
-+
-+    if (isTLS) {
-+        memcpy(out, &ss->ssl3.hs.finishedMsgs.tFinished[index], len);
-+    } else {
-+        memcpy(out, &ss->ssl3.hs.finishedMsgs.sFinished[index], len);
-+    }
-+
-+    rv = SECSuccess;
-+
-+loser:
-+    ssl_ReleaseSSL3HandshakeLock(ss);
-+    return rv;
-+}
-+
- /* ssl3_config_match_init must have already been called by
-  * the caller of this function.
-  */
-diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index 4607655..d47eb28 100644
---- a/lib/ssl/sslimpl.h
-+++ b/lib/ssl/sslimpl.h
-@@ -1981,6 +1981,11 @@ extern PRBool ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey *svrPrivKey,
- extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char *data,
-                                             unsigned int length);
- 
-+extern SECStatus ssl3_GetTLSUniqueChannelBinding(sslSocket *ss,
-+                                                 unsigned char *out,
-+                                                 unsigned int *outLen,
-+                                                 unsigned int outLenMax);
-+
- /* Construct a new NSPR socket for the app to use */
- extern PRFileDesc *ssl_NewPRSocket(sslSocket *ss, PRFileDesc *fd);
- extern void ssl_FreePRSocket(PRFileDesc *fd);
-diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
-index 84c78b3..e312d82 100644
---- a/lib/ssl/sslsock.c
-+++ b/lib/ssl/sslsock.c
-@@ -1700,6 +1700,29 @@ SSL_EnableWeakDHEPrimeGroup(PRFileDesc *fd, PRBool enabled)
-     return SECSuccess;
- }
- 
-+SECStatus
-+SSL_GetChannelBinding(PRFileDesc *fd,
-+                      SSLChannelBindingType binding_type,
-+                      unsigned char *out,
-+                      unsigned int *outLen,
-+                      unsigned int outLenMax)
-+{
-+    sslSocket *ss = ssl_FindSocket(fd);
-+
-+    if (!ss) {
-+        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelBinding",
-+                 SSL_GETPID(), fd));
-+        return SECFailure;
-+    }
-+
-+    if (binding_type != SSL_CHANNEL_BINDING_TLS_UNIQUE) {
-+        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-+        return SECFailure;
-+    }
-+
-+    return ssl3_GetTLSUniqueChannelBinding(ss, out, outLen, outLenMax);
-+}
-+
- #include "dhe-param.c"
- 
- static const SSLDHEGroupType ssl_default_dhe_groups[] = {
diff --git a/net/third_party/nss/ssl.gyp b/net/third_party/nss/ssl.gyp
deleted file mode 100644
index 4abf713..0000000
--- a/net/third_party/nss/ssl.gyp
+++ /dev/null
@@ -1,114 +0,0 @@
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
-  'targets': [
-    {
-      'target_name': 'libssl',
-      'type': '<(component)',
-      'product_name': 'crssl',  # Don't conflict with OpenSSL's libssl
-      'sources': [
-        'ssl/SSLerrs.h',
-        'ssl/authcert.c',
-        'ssl/cmpcert.c',
-        'ssl/derive.c',
-        'ssl/dtlscon.c',
-        'ssl/preenc.h',
-        'ssl/prelib.c',
-        'ssl/ssl.h',
-        'ssl/ssl3con.c',
-        'ssl/ssl3ecc.c',
-        'ssl/ssl3ext.c',
-        'ssl/ssl3gthr.c',
-        'ssl/ssl3prot.h',
-        'ssl/sslauth.c',
-        'ssl/sslcon.c',
-        'ssl/ssldef.c',
-        'ssl/sslenum.c',
-        'ssl/sslerr.c',
-        'ssl/sslerr.h',
-        'ssl/sslerrstrs.c',
-        'ssl/sslgathr.c',
-        'ssl/sslimpl.h',
-        'ssl/sslinfo.c',
-        'ssl/sslinit.c',
-        'ssl/sslmutex.c',
-        'ssl/sslmutex.h',
-        'ssl/sslnonce.c',
-        'ssl/sslproto.h',
-        'ssl/sslreveal.c',
-        'ssl/sslsecur.c',
-        'ssl/sslsnce.c',
-        'ssl/sslsock.c',
-        'ssl/sslt.h',
-        'ssl/ssltrace.c',
-        'ssl/sslver.c',
-        'ssl/tls13con.c',
-        'ssl/tls13con.h',
-        'ssl/tls13hkdf.c',
-        'ssl/tls13hkdf.h',
-        'ssl/unix_err.c',
-        'ssl/unix_err.h',
-      ],
-      'defines': [
-        'NO_PKCS11_BYPASS',
-        'NSS_ENABLE_ECC',
-        'USE_UTIL_DIRECTLY',
-      ],
-      'variables': {
-        'clang_warning_flags_unset': [
-          # ssl uses PR_ASSERT(!"foo") instead of PR_ASSERT(false && "foo")
-          '-Wstring-conversion',
-        ],
-      },
-      'conditions': [
-        ['component == "shared_library"', {
-          'conditions': [
-            ['OS == "ios"', {
-              'xcode_settings': {
-                'GCC_SYMBOLS_PRIVATE_EXTERN': 'NO',
-              },
-            }],
-          ],
-        }],
-        [ 'clang == 1', {
-          'cflags': [
-            # There is a broken header guard in /usr/include/nss/secmod.h:
-            # https://bugzilla.mozilla.org/show_bug.cgi?id=884072
-            '-Wno-header-guard',
-          ],
-        }],
-        [ 'OS == "ios"', {
-          'defines': [
-            'XP_UNIX',
-            'DARWIN',
-            'XP_MACOSX',
-          ],
-        }],
-        [ 'OS == "ios"', {
-          'dependencies': [
-            '../../../third_party/nss/nss.gyp:nspr',
-            '../../../third_party/nss/nss.gyp:nss',
-          ],
-          'export_dependent_settings': [
-            '../../../third_party/nss/nss.gyp:nspr',
-            '../../../third_party/nss/nss.gyp:nss',
-          ],
-          'direct_dependent_settings': {
-            'include_dirs': [
-              'ssl',
-            ],
-          },
-        }],
-      ],
-      'configurations': {
-        'Debug_Base': {
-          'defines': [
-            'DEBUG',
-          ],
-        },
-      },
-    },
-  ],
-}
diff --git a/net/third_party/nss/ssl/BUILD.gn b/net/third_party/nss/ssl/BUILD.gn
deleted file mode 100644
index 06a113d2..0000000
--- a/net/third_party/nss/ssl/BUILD.gn
+++ /dev/null
@@ -1,105 +0,0 @@
-# Copyright (c) 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-config("ssl_config") {
-  include_dirs = [ "." ]
-
-  if (is_mac || is_win) {
-    defines = [ "NSS_PLATFORM_CLIENT_AUTH" ]
-  }
-}
-
-component("libssl") {
-  output_name = "crssl"
-
-  sources = [
-    "SSLerrs.h",
-    "authcert.c",
-    "cmpcert.c",
-    "derive.c",
-    "dtlscon.c",
-    "preenc.h",
-    "prelib.c",
-    "ssl.h",
-    "ssl3con.c",
-    "ssl3ecc.c",
-    "ssl3ext.c",
-    "ssl3gthr.c",
-    "ssl3prot.h",
-    "sslauth.c",
-    "sslcon.c",
-    "ssldef.c",
-    "sslenum.c",
-    "sslerr.c",
-    "sslerr.h",
-    "sslerrstrs.c",
-    "sslgathr.c",
-    "sslimpl.h",
-    "sslinfo.c",
-    "sslinit.c",
-    "sslmutex.c",
-    "sslmutex.h",
-    "sslnonce.c",
-    "sslproto.h",
-    "sslreveal.c",
-    "sslsecur.c",
-    "sslsnce.c",
-    "sslsock.c",
-    "sslt.h",
-    "ssltrace.c",
-    "sslver.c",
-    "tls13con.c",
-    "tls13con.h",
-    "tls13hkdf.c",
-    "tls13hkdf.h",
-    "unix_err.c",
-    "unix_err.h",
-  ]
-
-  public_configs = [ ":ssl_config" ]
-
-  cflags = []
-  defines = [
-    "NO_PKCS11_BYPASS",
-    "NSS_ENABLE_ECC",
-    "USE_UTIL_DIRECTLY",
-  ]
-
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-
-  if (is_clang) {
-    # SSL triggers some of these Clang warnings.
-    configs -= [ "//build/config/clang:extra_warnings" ]
-
-    # There is a broken header guard in /usr/include/nss/secmod.h:
-    # https://bugzilla.mozilla.org/show_bug.cgi?id=884072
-    cflags = [ "-Wno-header-guard" ]
-
-    if (is_ios) {
-      # libssl uses routines deprecated on iOS (sem_init/sem_destroy).
-      # https://bugzilla.mozilla.org/show_bug.cgi?id=1192500
-      cflags += [ "-Wno-deprecated-declarations" ]
-    }
-  }
-
-  if (is_ios) {
-    defines += [
-      "XP_UNIX",
-      "DARWIN",
-      "XP_MACOSX",
-    ]
-  }
-
-  if (is_ios) {
-    public_deps = [
-      "//third_party/nss:nspr",
-      "//third_party/nss:nss",
-    ]
-  }
-
-  if (is_debug) {
-    defines += [ "DEBUG" ]
-  }
-}
diff --git a/net/third_party/nss/ssl/Makefile b/net/third_party/nss/ssl/Makefile
deleted file mode 100644
index d56cbf2..0000000
--- a/net/third_party/nss/ssl/Makefile
+++ /dev/null
@@ -1,63 +0,0 @@
-#! gmake
-#
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#######################################################################
-# (1) Include initial platform-independent assignments (MANDATORY).   #
-#######################################################################
-
-include manifest.mn
-
-#######################################################################
-# (2) Include "global" configuration information. (OPTIONAL)          #
-#######################################################################
-
-include $(CORE_DEPTH)/coreconf/config.mk
-
-#######################################################################
-# (3) Include "component" configuration information. (OPTIONAL)       #
-#######################################################################
-
-
-
-#######################################################################
-# (4) Include "local" platform-dependent assignments (OPTIONAL).      #
-#######################################################################
-
-include config.mk
-
-ifeq (,$(filter-out WIN%,$(OS_TARGET)))
-CSRCS	+= win32err.c
-DEFINES += -DIN_LIBSSL
-else
-ifeq ($(OS_TARGET),OS2)
-CSRCS	+= os2_err.c
-else
-CSRCS	+= unix_err.c
-endif
-endif
-
-#######################################################################
-# (5) Execute "global" rules. (OPTIONAL)                              #
-#######################################################################
-
-include $(CORE_DEPTH)/coreconf/rules.mk
-
-#######################################################################
-# (6) Execute "component" rules. (OPTIONAL)                           #
-#######################################################################
-
-
-
-#######################################################################
-# (7) Execute "local" rules. (OPTIONAL).                              #
-#######################################################################
-
-export:: private_export
-
-ifndef NSS_NO_PKCS11_BYPASS
-# indicates dependency on freebl static lib
-$(SHARED_LIBRARY): $(CRYPTOLIB)
-endif
diff --git a/net/third_party/nss/ssl/SSLerrs.h b/net/third_party/nss/ssl/SSLerrs.h
deleted file mode 100644
index 555e629..0000000
--- a/net/third_party/nss/ssl/SSLerrs.h
+++ /dev/null
@@ -1,476 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* SSL-specific security error codes  */
-/* caller must include "sslerr.h" */
-
-ER3(SSL_ERROR_EXPORT_ONLY_SERVER, SSL_ERROR_BASE + 0,
-    "Unable to communicate securely.  Peer does not support high-grade encryption.")
-
-ER3(SSL_ERROR_US_ONLY_SERVER, SSL_ERROR_BASE + 1,
-    "Unable to communicate securely.  Peer requires high-grade encryption which is not supported.")
-
-ER3(SSL_ERROR_NO_CYPHER_OVERLAP, SSL_ERROR_BASE + 2,
-    "Cannot communicate securely with peer: no common encryption algorithm(s).")
-
-ER3(SSL_ERROR_NO_CERTIFICATE, SSL_ERROR_BASE + 3,
-    "Unable to find the certificate or key necessary for authentication.")
-
-ER3(SSL_ERROR_BAD_CERTIFICATE, SSL_ERROR_BASE + 4,
-    "Unable to communicate securely with peer: peers's certificate was rejected.")
-
-ER3(SSL_ERROR_UNUSED_5, SSL_ERROR_BASE + 5,
-    "Unrecognized SSL error code.")
-
-ER3(SSL_ERROR_BAD_CLIENT, SSL_ERROR_BASE + 6,
-    "The server has encountered bad data from the client.")
-
-ER3(SSL_ERROR_BAD_SERVER, SSL_ERROR_BASE + 7,
-    "The client has encountered bad data from the server.")
-
-ER3(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE, SSL_ERROR_BASE + 8,
-    "Unsupported certificate type.")
-
-ER3(SSL_ERROR_UNSUPPORTED_VERSION, SSL_ERROR_BASE + 9,
-    "Peer using unsupported version of security protocol.")
-
-ER3(SSL_ERROR_UNUSED_10, SSL_ERROR_BASE + 10,
-    "Unrecognized SSL error code.")
-
-ER3(SSL_ERROR_WRONG_CERTIFICATE, SSL_ERROR_BASE + 11,
-    "Client authentication failed: private key in key database does not match public key in certificate database.")
-
-ER3(SSL_ERROR_BAD_CERT_DOMAIN, SSL_ERROR_BASE + 12,
-    "Unable to communicate securely with peer: requested domain name does not match the server's certificate.")
-
-ER3(SSL_ERROR_POST_WARNING, SSL_ERROR_BASE + 13,
-    "Unrecognized SSL error code.")
-
-ER3(SSL_ERROR_SSL2_DISABLED, (SSL_ERROR_BASE + 14),
-    "Peer only supports SSL version 2, which is locally disabled.")
-
-ER3(SSL_ERROR_BAD_MAC_READ, (SSL_ERROR_BASE + 15),
-    "SSL received a record with an incorrect Message Authentication Code.")
-
-ER3(SSL_ERROR_BAD_MAC_ALERT, (SSL_ERROR_BASE + 16),
-    "SSL peer reports incorrect Message Authentication Code.")
-
-ER3(SSL_ERROR_BAD_CERT_ALERT, (SSL_ERROR_BASE + 17),
-    "SSL peer cannot verify your certificate.")
-
-ER3(SSL_ERROR_REVOKED_CERT_ALERT, (SSL_ERROR_BASE + 18),
-    "SSL peer rejected your certificate as revoked.")
-
-ER3(SSL_ERROR_EXPIRED_CERT_ALERT, (SSL_ERROR_BASE + 19),
-    "SSL peer rejected your certificate as expired.")
-
-ER3(SSL_ERROR_SSL_DISABLED, (SSL_ERROR_BASE + 20),
-    "Cannot connect: SSL is disabled.")
-
-ER3(SSL_ERROR_FORTEZZA_PQG, (SSL_ERROR_BASE + 21),
-    "Cannot connect: SSL peer is in another FORTEZZA domain.")
-
-ER3(SSL_ERROR_UNKNOWN_CIPHER_SUITE, (SSL_ERROR_BASE + 22),
-    "An unknown SSL cipher suite has been requested.")
-
-ER3(SSL_ERROR_NO_CIPHERS_SUPPORTED, (SSL_ERROR_BASE + 23),
-    "No cipher suites are present and enabled in this program.")
-
-ER3(SSL_ERROR_BAD_BLOCK_PADDING, (SSL_ERROR_BASE + 24),
-    "SSL received a record with bad block padding.")
-
-ER3(SSL_ERROR_RX_RECORD_TOO_LONG, (SSL_ERROR_BASE + 25),
-    "SSL received a record that exceeded the maximum permissible length.")
-
-ER3(SSL_ERROR_TX_RECORD_TOO_LONG, (SSL_ERROR_BASE + 26),
-    "SSL attempted to send a record that exceeded the maximum permissible length.")
-
-/*
- * Received a malformed (too long or short or invalid content) SSL handshake.
- */
-ER3(SSL_ERROR_RX_MALFORMED_HELLO_REQUEST, (SSL_ERROR_BASE + 27),
-    "SSL received a malformed Hello Request handshake message.")
-
-ER3(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, (SSL_ERROR_BASE + 28),
-    "SSL received a malformed Client Hello handshake message.")
-
-ER3(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, (SSL_ERROR_BASE + 29),
-    "SSL received a malformed Server Hello handshake message.")
-
-ER3(SSL_ERROR_RX_MALFORMED_CERTIFICATE, (SSL_ERROR_BASE + 30),
-    "SSL received a malformed Certificate handshake message.")
-
-ER3(SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH, (SSL_ERROR_BASE + 31),
-    "SSL received a malformed Server Key Exchange handshake message.")
-
-ER3(SSL_ERROR_RX_MALFORMED_CERT_REQUEST, (SSL_ERROR_BASE + 32),
-    "SSL received a malformed Certificate Request handshake message.")
-
-ER3(SSL_ERROR_RX_MALFORMED_HELLO_DONE, (SSL_ERROR_BASE + 33),
-    "SSL received a malformed Server Hello Done handshake message.")
-
-ER3(SSL_ERROR_RX_MALFORMED_CERT_VERIFY, (SSL_ERROR_BASE + 34),
-    "SSL received a malformed Certificate Verify handshake message.")
-
-ER3(SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH, (SSL_ERROR_BASE + 35),
-    "SSL received a malformed Client Key Exchange handshake message.")
-
-ER3(SSL_ERROR_RX_MALFORMED_FINISHED, (SSL_ERROR_BASE + 36),
-    "SSL received a malformed Finished handshake message.")
-
-/*
- * Received a malformed (too long or short) SSL record.
- */
-ER3(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER, (SSL_ERROR_BASE + 37),
-    "SSL received a malformed Change Cipher Spec record.")
-
-ER3(SSL_ERROR_RX_MALFORMED_ALERT, (SSL_ERROR_BASE + 38),
-    "SSL received a malformed Alert record.")
-
-ER3(SSL_ERROR_RX_MALFORMED_HANDSHAKE, (SSL_ERROR_BASE + 39),
-    "SSL received a malformed Handshake record.")
-
-ER3(SSL_ERROR_RX_MALFORMED_APPLICATION_DATA, (SSL_ERROR_BASE + 40),
-    "SSL received a malformed Application Data record.")
-
-/*
- * Received an SSL handshake that was inappropriate for the state we're in.
- * E.g. Server received message from server, or wrong state in state machine.
- */
-ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST, (SSL_ERROR_BASE + 41),
-    "SSL received an unexpected Hello Request handshake message.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO, (SSL_ERROR_BASE + 42),
-    "SSL received an unexpected Client Hello handshake message.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO, (SSL_ERROR_BASE + 43),
-    "SSL received an unexpected Server Hello handshake message.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_CERTIFICATE, (SSL_ERROR_BASE + 44),
-    "SSL received an unexpected Certificate handshake message.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH, (SSL_ERROR_BASE + 45),
-    "SSL received an unexpected Server Key Exchange handshake message.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST, (SSL_ERROR_BASE + 46),
-    "SSL received an unexpected Certificate Request handshake message.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE, (SSL_ERROR_BASE + 47),
-    "SSL received an unexpected Server Hello Done handshake message.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY, (SSL_ERROR_BASE + 48),
-    "SSL received an unexpected Certificate Verify handshake message.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH, (SSL_ERROR_BASE + 49),
-    "SSL received an unexpected Client Key Exchange handshake message.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_FINISHED, (SSL_ERROR_BASE + 50),
-    "SSL received an unexpected Finished handshake message.")
-
-/*
- * Received an SSL record that was inappropriate for the state we're in.
- */
-ER3(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER, (SSL_ERROR_BASE + 51),
-    "SSL received an unexpected Change Cipher Spec record.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_ALERT, (SSL_ERROR_BASE + 52),
-    "SSL received an unexpected Alert record.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE, (SSL_ERROR_BASE + 53),
-    "SSL received an unexpected Handshake record.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA, (SSL_ERROR_BASE + 54),
-    "SSL received an unexpected Application Data record.")
-
-/*
- * Received record/message with unknown discriminant.
- */
-ER3(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE, (SSL_ERROR_BASE + 55),
-    "SSL received a record with an unknown content type.")
-
-ER3(SSL_ERROR_RX_UNKNOWN_HANDSHAKE, (SSL_ERROR_BASE + 56),
-    "SSL received a handshake message with an unknown message type.")
-
-ER3(SSL_ERROR_RX_UNKNOWN_ALERT, (SSL_ERROR_BASE + 57),
-    "SSL received an alert record with an unknown alert description.")
-
-/*
- * Received an alert reporting what we did wrong.  (more alerts above)
- */
-ER3(SSL_ERROR_CLOSE_NOTIFY_ALERT, (SSL_ERROR_BASE + 58),
-    "SSL peer has closed this connection.")
-
-ER3(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT, (SSL_ERROR_BASE + 59),
-    "SSL peer was not expecting a handshake message it received.")
-
-ER3(SSL_ERROR_DECOMPRESSION_FAILURE_ALERT, (SSL_ERROR_BASE + 60),
-    "SSL peer was unable to successfully decompress an SSL record it received.")
-
-ER3(SSL_ERROR_HANDSHAKE_FAILURE_ALERT, (SSL_ERROR_BASE + 61),
-    "SSL peer was unable to negotiate an acceptable set of security parameters.")
-
-ER3(SSL_ERROR_ILLEGAL_PARAMETER_ALERT, (SSL_ERROR_BASE + 62),
-    "SSL peer rejected a handshake message for unacceptable content.")
-
-ER3(SSL_ERROR_UNSUPPORTED_CERT_ALERT, (SSL_ERROR_BASE + 63),
-    "SSL peer does not support certificates of the type it received.")
-
-ER3(SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT, (SSL_ERROR_BASE + 64),
-    "SSL peer had some unspecified issue with the certificate it received.")
-
-ER3(SSL_ERROR_GENERATE_RANDOM_FAILURE, (SSL_ERROR_BASE + 65),
-    "SSL experienced a failure of its random number generator.")
-
-ER3(SSL_ERROR_SIGN_HASHES_FAILURE, (SSL_ERROR_BASE + 66),
-    "Unable to digitally sign data required to verify your certificate.")
-
-ER3(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE, (SSL_ERROR_BASE + 67),
-    "SSL was unable to extract the public key from the peer's certificate.")
-
-ER3(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE, (SSL_ERROR_BASE + 68),
-    "Unspecified failure while processing SSL Server Key Exchange handshake.")
-
-ER3(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE, (SSL_ERROR_BASE + 69),
-    "Unspecified failure while processing SSL Client Key Exchange handshake.")
-
-ER3(SSL_ERROR_ENCRYPTION_FAILURE, (SSL_ERROR_BASE + 70),
-    "Bulk data encryption algorithm failed in selected cipher suite.")
-
-ER3(SSL_ERROR_DECRYPTION_FAILURE, (SSL_ERROR_BASE + 71),
-    "Bulk data decryption algorithm failed in selected cipher suite.")
-
-ER3(SSL_ERROR_SOCKET_WRITE_FAILURE, (SSL_ERROR_BASE + 72),
-    "Attempt to write encrypted data to underlying socket failed.")
-
-ER3(SSL_ERROR_MD5_DIGEST_FAILURE, (SSL_ERROR_BASE + 73),
-    "MD5 digest function failed.")
-
-ER3(SSL_ERROR_SHA_DIGEST_FAILURE, (SSL_ERROR_BASE + 74),
-    "SHA-1 digest function failed.")
-
-ER3(SSL_ERROR_MAC_COMPUTATION_FAILURE, (SSL_ERROR_BASE + 75),
-    "MAC computation failed.")
-
-ER3(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE, (SSL_ERROR_BASE + 76),
-    "Failure to create Symmetric Key context.")
-
-ER3(SSL_ERROR_SYM_KEY_UNWRAP_FAILURE, (SSL_ERROR_BASE + 77),
-    "Failure to unwrap the Symmetric key in Client Key Exchange message.")
-
-ER3(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED, (SSL_ERROR_BASE + 78),
-    "SSL Server attempted to use domestic-grade public key with export cipher suite.")
-
-ER3(SSL_ERROR_IV_PARAM_FAILURE, (SSL_ERROR_BASE + 79),
-    "PKCS11 code failed to translate an IV into a param.")
-
-ER3(SSL_ERROR_INIT_CIPHER_SUITE_FAILURE, (SSL_ERROR_BASE + 80),
-    "Failed to initialize the selected cipher suite.")
-
-ER3(SSL_ERROR_SESSION_KEY_GEN_FAILURE, (SSL_ERROR_BASE + 81),
-    "Client failed to generate session keys for SSL session.")
-
-ER3(SSL_ERROR_NO_SERVER_KEY_FOR_ALG, (SSL_ERROR_BASE + 82),
-    "Server has no key for the attempted key exchange algorithm.")
-
-ER3(SSL_ERROR_TOKEN_INSERTION_REMOVAL, (SSL_ERROR_BASE + 83),
-    "PKCS#11 token was inserted or removed while operation was in progress.")
-
-ER3(SSL_ERROR_TOKEN_SLOT_NOT_FOUND, (SSL_ERROR_BASE + 84),
-    "No PKCS#11 token could be found to do a required operation.")
-
-ER3(SSL_ERROR_NO_COMPRESSION_OVERLAP, (SSL_ERROR_BASE + 85),
-    "Cannot communicate securely with peer: no common compression algorithm(s).")
-
-ER3(SSL_ERROR_HANDSHAKE_NOT_COMPLETED, (SSL_ERROR_BASE + 86),
-    "Cannot perform the operation until the handshake is complete.")
-
-ER3(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE, (SSL_ERROR_BASE + 87),
-    "Received incorrect handshakes hash values from peer.")
-
-ER3(SSL_ERROR_CERT_KEA_MISMATCH, (SSL_ERROR_BASE + 88),
-    "The certificate provided cannot be used with the selected key exchange algorithm.")
-
-ER3(SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA, (SSL_ERROR_BASE + 89),
-    "No certificate authority is trusted for SSL client authentication.")
-
-ER3(SSL_ERROR_SESSION_NOT_FOUND, (SSL_ERROR_BASE + 90),
-    "Client's SSL session ID not found in server's session cache.")
-
-ER3(SSL_ERROR_DECRYPTION_FAILED_ALERT, (SSL_ERROR_BASE + 91),
-    "Peer was unable to decrypt an SSL record it received.")
-
-ER3(SSL_ERROR_RECORD_OVERFLOW_ALERT, (SSL_ERROR_BASE + 92),
-    "Peer received an SSL record that was longer than is permitted.")
-
-ER3(SSL_ERROR_UNKNOWN_CA_ALERT, (SSL_ERROR_BASE + 93),
-    "Peer does not recognize and trust the CA that issued your certificate.")
-
-ER3(SSL_ERROR_ACCESS_DENIED_ALERT, (SSL_ERROR_BASE + 94),
-    "Peer received a valid certificate, but access was denied.")
-
-ER3(SSL_ERROR_DECODE_ERROR_ALERT, (SSL_ERROR_BASE + 95),
-    "Peer could not decode an SSL handshake message.")
-
-ER3(SSL_ERROR_DECRYPT_ERROR_ALERT, (SSL_ERROR_BASE + 96),
-    "Peer reports failure of signature verification or key exchange.")
-
-ER3(SSL_ERROR_EXPORT_RESTRICTION_ALERT, (SSL_ERROR_BASE + 97),
-    "Peer reports negotiation not in compliance with export regulations.")
-
-ER3(SSL_ERROR_PROTOCOL_VERSION_ALERT, (SSL_ERROR_BASE + 98),
-    "Peer reports incompatible or unsupported protocol version.")
-
-ER3(SSL_ERROR_INSUFFICIENT_SECURITY_ALERT, (SSL_ERROR_BASE + 99),
-    "Server requires ciphers more secure than those supported by client.")
-
-ER3(SSL_ERROR_INTERNAL_ERROR_ALERT, (SSL_ERROR_BASE + 100),
-    "Peer reports it experienced an internal error.")
-
-ER3(SSL_ERROR_USER_CANCELED_ALERT, (SSL_ERROR_BASE + 101),
-    "Peer user canceled handshake.")
-
-ER3(SSL_ERROR_NO_RENEGOTIATION_ALERT, (SSL_ERROR_BASE + 102),
-    "Peer does not permit renegotiation of SSL security parameters.")
-
-ER3(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED, (SSL_ERROR_BASE + 103),
-    "SSL server cache not configured and not disabled for this socket.")
-
-ER3(SSL_ERROR_UNSUPPORTED_EXTENSION_ALERT, (SSL_ERROR_BASE + 104),
-    "SSL peer does not support requested TLS hello extension.")
-
-ER3(SSL_ERROR_CERTIFICATE_UNOBTAINABLE_ALERT, (SSL_ERROR_BASE + 105),
-    "SSL peer could not obtain your certificate from the supplied URL.")
-
-ER3(SSL_ERROR_UNRECOGNIZED_NAME_ALERT, (SSL_ERROR_BASE + 106),
-    "SSL peer has no certificate for the requested DNS name.")
-
-ER3(SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT, (SSL_ERROR_BASE + 107),
-    "SSL peer was unable to get an OCSP response for its certificate.")
-
-ER3(SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT, (SSL_ERROR_BASE + 108),
-    "SSL peer reported bad certificate hash value.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET, (SSL_ERROR_BASE + 109),
-    "SSL received an unexpected New Session Ticket handshake message.")
-
-ER3(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET, (SSL_ERROR_BASE + 110),
-    "SSL received a malformed New Session Ticket handshake message.")
-
-ER3(SSL_ERROR_DECOMPRESSION_FAILURE, (SSL_ERROR_BASE + 111),
-    "SSL received a compressed record that could not be decompressed.")
-
-ER3(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED, (SSL_ERROR_BASE + 112),
-    "Renegotiation is not allowed on this SSL socket.")
-
-ER3(SSL_ERROR_UNSAFE_NEGOTIATION, (SSL_ERROR_BASE + 113),
-    "Peer attempted old style (potentially vulnerable) handshake.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD, (SSL_ERROR_BASE + 114),
-    "SSL received an unexpected uncompressed record.")
-
-ER3(SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY, (SSL_ERROR_BASE + 115),
-    "SSL received a weak ephemeral Diffie-Hellman key in Server Key Exchange handshake message.")
-
-ER3(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID, (SSL_ERROR_BASE + 116),
-    "SSL received invalid NPN extension data.")
-
-ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2, (SSL_ERROR_BASE + 117),
-    "SSL feature not supported for SSL 2.0 connections.")
-
-ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS, (SSL_ERROR_BASE + 118),
-    "SSL feature not supported for servers.")
-
-ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_CLIENTS, (SSL_ERROR_BASE + 119),
-    "SSL feature not supported for clients.")
-
-ER3(SSL_ERROR_INVALID_VERSION_RANGE, (SSL_ERROR_BASE + 120),
-    "SSL version range is not valid.")
-
-ER3(SSL_ERROR_CIPHER_DISALLOWED_FOR_VERSION, (SSL_ERROR_BASE + 121),
-    "SSL peer selected a cipher suite disallowed for the selected protocol version.")
-
-ER3(SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST, (SSL_ERROR_BASE + 122),
-    "SSL received a malformed Hello Verify Request handshake message.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST, (SSL_ERROR_BASE + 123),
-    "SSL received an unexpected Hello Verify Request handshake message.")
-
-ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION, (SSL_ERROR_BASE + 124),
-    "SSL feature not supported for the protocol version.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_CERT_STATUS, (SSL_ERROR_BASE + 125),
-    "SSL received an unexpected Certificate Status handshake message.")
-
-ER3(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM, (SSL_ERROR_BASE + 126),
-    "Unsupported hash algorithm used by TLS peer.")
-
-ER3(SSL_ERROR_DIGEST_FAILURE, (SSL_ERROR_BASE + 127),
-    "Digest function failed.")
-
-ER3(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM, (SSL_ERROR_BASE + 128),
-    "Incorrect signature algorithm specified in a digitally-signed element.")
-
-ER3(SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK, (SSL_ERROR_BASE + 129),
-    "The next protocol negotiation extension was enabled, but the callback was cleared prior to being needed.")
-
-ER3(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL, (SSL_ERROR_BASE + 130),
-    "The server supports no protocols that the client advertises in the ALPN extension.")
-
-ER3(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT, (SSL_ERROR_BASE + 131),
-    "The server rejected the handshake because the client downgraded to a lower "
-    "TLS version than the server supports.")
-
-ER3(SSL_ERROR_WEAK_SERVER_CERT_KEY, (SSL_ERROR_BASE + 132),
-    "The server certificate included a public key that was too weak.")
-
-ER3(SSL_ERROR_RX_SHORT_DTLS_READ, (SSL_ERROR_BASE + 133),
-    "Not enough room in buffer for DTLS record.")
-
-ER3(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM, (SSL_ERROR_BASE + 134),
-    "No supported TLS signature algorithm was configured.")
-
-ER3(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM, (SSL_ERROR_BASE + 135),
-    "The peer used an unsupported combination of signature and hash algorithm.")
-
-ER3(SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET, (SSL_ERROR_BASE + 136),
-    "The peer tried to resume without a correct extended_master_secret extension")
-
-ER3(SSL_ERROR_UNEXPECTED_EXTENDED_MASTER_SECRET, (SSL_ERROR_BASE + 137),
-    "The peer tried to resume with an unexpected extended_master_secret extension")
-
-ER3(SSL_ERROR_RX_MALFORMED_KEY_SHARE, (SSL_ERROR_BASE + 138),
-    "SSL received a malformed Key Share extension.")
-
-ER3(SSL_ERROR_MISSING_KEY_SHARE, (SSL_ERROR_BASE + 139),
-    "SSL expected a Key Share extension.")
-
-ER3(SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE, (SSL_ERROR_BASE + 140),
-    "SSL received a malformed ECDHE key share handshake extension.")
-
-ER3(SSL_ERROR_RX_MALFORMED_DHE_KEY_SHARE, (SSL_ERROR_BASE + 141),
-    "SSL received a malformed DHE key share handshake extension.")
-
-ER3(SSL_ERROR_RX_UNEXPECTED_ENCRYPTED_EXTENSIONS, (SSL_ERROR_BASE + 142),
-    "SSL received an unexpected Encrypted Extensions handshake message.")
-
-ER3(SSL_ERROR_MISSING_EXTENSION_ALERT, (SSL_ERROR_BASE + 143),
-    "SSL received a missing_extenson alert.")
-
-ER3(SSL_ERROR_KEY_EXCHANGE_FAILURE, (SSL_ERROR_BASE + 144),
-    "SSL had an error performing key exchange.")
-
-ER3(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION, (SSL_ERROR_BASE + 145),
-    "SSL received an extension that is not permitted for this version.")
-
-ER3(SSL_ERROR_RX_MALFORMED_ENCRYPTED_EXTENSIONS, (SSL_ERROR_BASE + 146),
-    "SSL received a malformed Encrypted Extensions handshake message.")
-
-ER3(SSL_ERROR_BAD_CHANNEL_ID_DATA, (SSL_ERROR_BASE + 147),
-    "SSL received a malformed TLS Channel ID extension.")
-
-ER3(SSL_ERROR_INVALID_CHANNEL_ID_KEY, (SSL_ERROR_BASE + 148),
-    "The application provided an invalid TLS Channel ID key.")
-
-ER3(SSL_ERROR_GET_CHANNEL_ID_FAILED, (SSL_ERROR_BASE + 149),
-    "The application could not get a TLS Channel ID.")
diff --git a/net/third_party/nss/ssl/authcert.c b/net/third_party/nss/ssl/authcert.c
deleted file mode 100644
index 88c7c084..0000000
--- a/net/third_party/nss/ssl/authcert.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * NSS utility functions
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <stdio.h>
-#include <string.h>
-#include "prerror.h"
-#include "secitem.h"
-#include "prnetdb.h"
-#include "cert.h"
-#include "nspr.h"
-#include "secder.h"
-#include "key.h"
-#include "nss.h"
-#include "ssl.h"
-#include "pk11func.h" /* for PK11_ function calls */
-
-/*
- * This callback used by SSL to pull client sertificate upon
- * server request
- */
-SECStatus
-NSS_GetClientAuthData(void *arg,
-                      PRFileDesc *socket,
-                      struct CERTDistNamesStr *caNames,
-                      struct CERTCertificateStr **pRetCert,
-                      struct SECKEYPrivateKeyStr **pRetKey)
-{
-    CERTCertificate *cert = NULL;
-    SECKEYPrivateKey *privkey = NULL;
-    char *chosenNickName = (char *)arg; /* CONST */
-    void *proto_win = NULL;
-    SECStatus rv = SECFailure;
-
-    proto_win = SSL_RevealPinArg(socket);
-
-    if (chosenNickName) {
-        cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
-                                        chosenNickName, certUsageSSLClient,
-                                        PR_FALSE, proto_win);
-        if (cert) {
-            privkey = PK11_FindKeyByAnyCert(cert, proto_win);
-            if (privkey) {
-                rv = SECSuccess;
-            } else {
-                CERT_DestroyCertificate(cert);
-            }
-        }
-    } else { /* no name given, automatically find the right cert. */
-        CERTCertNicknames *names;
-        int i;
-
-        names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
-                                      SEC_CERT_NICKNAMES_USER, proto_win);
-        if (names != NULL) {
-            for (i = 0; i < names->numnicknames; i++) {
-                cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
-                                                names->nicknames[i], certUsageSSLClient,
-                                                PR_FALSE, proto_win);
-                if (!cert)
-                    continue;
-                /* Only check unexpired certs */
-                if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_TRUE) !=
-                    secCertTimeValid) {
-                    CERT_DestroyCertificate(cert);
-                    continue;
-                }
-                rv = NSS_CmpCertChainWCANames(cert, caNames);
-                if (rv == SECSuccess) {
-                    privkey =
-                        PK11_FindKeyByAnyCert(cert, proto_win);
-                    if (privkey)
-                        break;
-                }
-                rv = SECFailure;
-                CERT_DestroyCertificate(cert);
-            }
-            CERT_FreeNicknames(names);
-        }
-    }
-    if (rv == SECSuccess) {
-        *pRetCert = cert;
-        *pRetKey = privkey;
-    }
-    return rv;
-}
diff --git a/net/third_party/nss/ssl/derive.c b/net/third_party/nss/ssl/derive.c
deleted file mode 100644
index 026dbd2..0000000
--- a/net/third_party/nss/ssl/derive.c
+++ /dev/null
@@ -1,896 +0,0 @@
-/*
- * Key Derivation that doesn't use PKCS11
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "ssl.h"    /* prereq to sslimpl.h */
-#include "certt.h"  /* prereq to sslimpl.h */
-#include "keythi.h" /* prereq to sslimpl.h */
-#include "sslimpl.h"
-#ifndef NO_PKCS11_BYPASS
-#include "blapi.h"
-#endif
-
-#include "keyhi.h"
-#include "pk11func.h"
-#include "secasn1.h"
-#include "cert.h"
-#include "secmodt.h"
-
-#include "sslproto.h"
-#include "sslerr.h"
-
-#ifndef NO_PKCS11_BYPASS
-/* make this a macro! */
-#ifdef NOT_A_MACRO
-static void
-buildSSLKey(unsigned char *keyBlock, unsigned int keyLen, SECItem *result,
-            const char *label)
-{
-    result->type = siBuffer;
-    result->data = keyBlock;
-    result->len = keyLen;
-    PRINT_BUF(100, (NULL, label, keyBlock, keyLen));
-}
-#else
-#define buildSSLKey(keyBlock, keyLen, result, label)     \
-    {                                                    \
-        (result)->type = siBuffer;                       \
-        (result)->data = keyBlock;                       \
-        (result)->len = keyLen;                          \
-        PRINT_BUF(100, (NULL, label, keyBlock, keyLen)); \
-    }
-#endif
-
-/*
- * SSL Key generation given pre master secret
- */
-#ifndef NUM_MIXERS
-#define NUM_MIXERS 9
-#endif
-static const char *const mixers[NUM_MIXERS] = {
-    "A",
-    "BB",
-    "CCC",
-    "DDDD",
-    "EEEEE",
-    "FFFFFF",
-    "GGGGGGG",
-    "HHHHHHHH",
-    "IIIIIIIII"
-};
-
-SECStatus
-ssl3_KeyAndMacDeriveBypass(
-    ssl3CipherSpec *pwSpec,
-    const unsigned char *cr,
-    const unsigned char *sr,
-    PRBool isTLS,
-    PRBool isExport)
-{
-    const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def;
-    unsigned char *key_block = pwSpec->key_block;
-    unsigned char *key_block2 = NULL;
-    unsigned int block_bytes = 0;
-    unsigned int block_needed = 0;
-    unsigned int i;
-    unsigned int keySize;    /* actual    size of cipher keys */
-    unsigned int effKeySize; /* effective size of cipher keys */
-    unsigned int macSize;    /* size of MAC secret */
-    unsigned int IVSize;     /* size of IV */
-    PRBool explicitIV = PR_FALSE;
-    SECStatus rv = SECFailure;
-    SECStatus status = SECSuccess;
-    PRBool isFIPS = PR_FALSE;
-    PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2;
-
-    SECItem srcr;
-    SECItem crsr;
-
-    unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
-    unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
-    PRUint64 md5buf[22];
-    PRUint64 shabuf[40];
-
-#define md5Ctx ((MD5Context *)md5buf)
-#define shaCtx ((SHA1Context *)shabuf)
-
-    static const SECItem zed = { siBuffer, NULL, 0 };
-
-    if (pwSpec->msItem.data == NULL ||
-        pwSpec->msItem.len != SSL3_MASTER_SECRET_LENGTH) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return rv;
-    }
-
-    PRINT_BUF(100, (NULL, "Master Secret", pwSpec->msItem.data,
-                    pwSpec->msItem.len));
-
-    /* figure out how much is needed */
-    macSize = pwSpec->mac_size;
-    keySize = cipher_def->key_size;
-    effKeySize = cipher_def->secret_key_size;
-    IVSize = cipher_def->iv_size;
-    if (keySize == 0) {
-        effKeySize = IVSize = 0; /* only MACing */
-    }
-    if (cipher_def->type == type_block &&
-        pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
-        /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */
-        explicitIV = PR_TRUE;
-    }
-    block_needed =
-        2 * (macSize + effKeySize + ((!isExport && !explicitIV) * IVSize));
-
-    /*
-     * clear out our returned keys so we can recover on failure
-     */
-    pwSpec->client.write_key_item = zed;
-    pwSpec->client.write_mac_key_item = zed;
-    pwSpec->server.write_key_item = zed;
-    pwSpec->server.write_mac_key_item = zed;
-
-    /* initialize the server random, client random block */
-    srcr.type = siBuffer;
-    srcr.data = srcrdata;
-    srcr.len = sizeof srcrdata;
-    PORT_Memcpy(srcrdata, sr, SSL3_RANDOM_LENGTH);
-    PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, cr, SSL3_RANDOM_LENGTH);
-
-    /* initialize the client random, server random block */
-    crsr.type = siBuffer;
-    crsr.data = crsrdata;
-    crsr.len = sizeof crsrdata;
-    PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH);
-    PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH);
-    PRINT_BUF(100, (NULL, "Key & MAC CRSR", crsr.data, crsr.len));
-
-    /*
-     * generate the key material:
-     */
-    if (isTLS) {
-        SECItem keyblk;
-
-        keyblk.type = siBuffer;
-        keyblk.data = key_block;
-        keyblk.len = block_needed;
-
-        if (isTLS12) {
-            status = TLS_P_hash(HASH_AlgSHA256, &pwSpec->msItem,
-                                "key expansion", &srcr, &keyblk, isFIPS);
-        } else {
-            status = TLS_PRF(&pwSpec->msItem, "key expansion", &srcr, &keyblk,
-                             isFIPS);
-        }
-        if (status != SECSuccess) {
-            goto key_and_mac_derive_fail;
-        }
-        block_bytes = keyblk.len;
-    } else {
-       /* key_block =
-        *     MD5(master_secret + SHA('A' + master_secret +
-        *                      ServerHello.random + ClientHello.random)) +
-        *     MD5(master_secret + SHA('BB' + master_secret +
-        *                      ServerHello.random + ClientHello.random)) +
-        *     MD5(master_secret + SHA('CCC' + master_secret +
-        *                      ServerHello.random + ClientHello.random)) +
-        *     [...];
-        */
-        unsigned int made = 0;
-        for (i = 0; made < block_needed && i < NUM_MIXERS; ++i) {
-            unsigned int outLen;
-            unsigned char sha_out[SHA1_LENGTH];
-
-            SHA1_Begin(shaCtx);
-            SHA1_Update(shaCtx, (unsigned char *)(mixers[i]), i + 1);
-            SHA1_Update(shaCtx, pwSpec->msItem.data, pwSpec->msItem.len);
-            SHA1_Update(shaCtx, srcr.data, srcr.len);
-            SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH);
-            PORT_Assert(outLen == SHA1_LENGTH);
-
-            MD5_Begin(md5Ctx);
-            MD5_Update(md5Ctx, pwSpec->msItem.data, pwSpec->msItem.len);
-            MD5_Update(md5Ctx, sha_out, outLen);
-            MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH);
-            PORT_Assert(outLen == MD5_LENGTH);
-            made += MD5_LENGTH;
-        }
-        block_bytes = made;
-    }
-    PORT_Assert(block_bytes >= block_needed);
-    PORT_Assert(block_bytes <= sizeof pwSpec->key_block);
-    PRINT_BUF(100, (NULL, "key block", key_block, block_bytes));
-
-    /*
-     * Put the key material where it goes.
-     */
-    key_block2 = key_block + block_bytes;
-    i = 0; /* now shows how much consumed */
-
-    /*
-     * The key_block is partitioned as follows:
-     * client_write_MAC_secret[CipherSpec.hash_size]
-     */
-    buildSSLKey(&key_block[i], macSize, &pwSpec->client.write_mac_key_item,
-                "Client Write MAC Secret");
-    i += macSize;
-
-    /*
-     * server_write_MAC_secret[CipherSpec.hash_size]
-     */
-    buildSSLKey(&key_block[i], macSize, &pwSpec->server.write_mac_key_item,
-                "Server Write MAC Secret");
-    i += macSize;
-
-    if (!keySize) {
-        /* only MACing */
-        buildSSLKey(NULL, 0, &pwSpec->client.write_key_item,
-                    "Client Write Key (MAC only)");
-        buildSSLKey(NULL, 0, &pwSpec->server.write_key_item,
-                    "Server Write Key (MAC only)");
-        buildSSLKey(NULL, 0, &pwSpec->client.write_iv_item,
-                    "Client Write IV (MAC only)");
-        buildSSLKey(NULL, 0, &pwSpec->server.write_iv_item,
-                    "Server Write IV (MAC only)");
-    } else if (!isExport) {
-        /*
-        ** Generate Domestic write keys and IVs.
-        ** client_write_key[CipherSpec.key_material]
-        */
-        buildSSLKey(&key_block[i], keySize, &pwSpec->client.write_key_item,
-                    "Domestic Client Write Key");
-        i += keySize;
-
-        /*
-        ** server_write_key[CipherSpec.key_material]
-        */
-        buildSSLKey(&key_block[i], keySize, &pwSpec->server.write_key_item,
-                    "Domestic Server Write Key");
-        i += keySize;
-
-        if (IVSize > 0) {
-            if (explicitIV) {
-                static unsigned char zero_block[32];
-                PORT_Assert(IVSize <= sizeof zero_block);
-                buildSSLKey(&zero_block[0], IVSize,
-                            &pwSpec->client.write_iv_item,
-                            "Domestic Client Write IV");
-                buildSSLKey(&zero_block[0], IVSize,
-                            &pwSpec->server.write_iv_item,
-                            "Domestic Server Write IV");
-            } else {
-                /*
-                ** client_write_IV[CipherSpec.IV_size]
-                */
-                buildSSLKey(&key_block[i], IVSize,
-                            &pwSpec->client.write_iv_item,
-                            "Domestic Client Write IV");
-                i += IVSize;
-
-                /*
-                ** server_write_IV[CipherSpec.IV_size]
-                */
-                buildSSLKey(&key_block[i], IVSize,
-                            &pwSpec->server.write_iv_item,
-                            "Domestic Server Write IV");
-                i += IVSize;
-            }
-        }
-        PORT_Assert(i <= block_bytes);
-    } else if (!isTLS) {
-        /*
-        ** Generate SSL3 Export write keys and IVs.
-        */
-        unsigned int outLen;
-
-        /*
-        ** client_write_key[CipherSpec.key_material]
-        ** final_client_write_key = MD5(client_write_key +
-        **                   ClientHello.random + ServerHello.random);
-        */
-        MD5_Begin(md5Ctx);
-        MD5_Update(md5Ctx, &key_block[i], effKeySize);
-        MD5_Update(md5Ctx, crsr.data, crsr.len);
-        MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
-        i += effKeySize;
-        buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item,
-                    "SSL3 Export Client Write Key");
-        key_block2 += keySize;
-
-        /*
-        ** server_write_key[CipherSpec.key_material]
-        ** final_server_write_key = MD5(server_write_key +
-        **                    ServerHello.random + ClientHello.random);
-        */
-        MD5_Begin(md5Ctx);
-        MD5_Update(md5Ctx, &key_block[i], effKeySize);
-        MD5_Update(md5Ctx, srcr.data, srcr.len);
-        MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
-        i += effKeySize;
-        buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item,
-                    "SSL3 Export Server Write Key");
-        key_block2 += keySize;
-        PORT_Assert(i <= block_bytes);
-
-        if (IVSize) {
-            /*
-            ** client_write_IV =
-            **  MD5(ClientHello.random + ServerHello.random);
-            */
-            MD5_Begin(md5Ctx);
-            MD5_Update(md5Ctx, crsr.data, crsr.len);
-            MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
-            buildSSLKey(key_block2, IVSize, &pwSpec->client.write_iv_item,
-                        "SSL3 Export Client Write IV");
-            key_block2 += IVSize;
-
-            /*
-            ** server_write_IV =
-            **  MD5(ServerHello.random + ClientHello.random);
-            */
-            MD5_Begin(md5Ctx);
-            MD5_Update(md5Ctx, srcr.data, srcr.len);
-            MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
-            buildSSLKey(key_block2, IVSize, &pwSpec->server.write_iv_item,
-                        "SSL3 Export Server Write IV");
-            key_block2 += IVSize;
-        }
-
-        PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block);
-    } else {
-        /*
-        ** Generate TLS Export write keys and IVs.
-        */
-        SECItem secret;
-        SECItem keyblk;
-
-        secret.type = siBuffer;
-        keyblk.type = siBuffer;
-        /*
-        ** client_write_key[CipherSpec.key_material]
-        ** final_client_write_key = PRF(client_write_key,
-        **                              "client write key",
-        **                              client_random + server_random);
-        */
-        secret.data = &key_block[i];
-        secret.len = effKeySize;
-        i += effKeySize;
-        keyblk.data = key_block2;
-        keyblk.len = keySize;
-        status = TLS_PRF(&secret, "client write key", &crsr, &keyblk, isFIPS);
-        if (status != SECSuccess) {
-            goto key_and_mac_derive_fail;
-        }
-        buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item,
-                    "TLS Export Client Write Key");
-        key_block2 += keySize;
-
-        /*
-        ** server_write_key[CipherSpec.key_material]
-        ** final_server_write_key = PRF(server_write_key,
-        **                              "server write key",
-        **                              client_random + server_random);
-        */
-        secret.data = &key_block[i];
-        secret.len = effKeySize;
-        i += effKeySize;
-        keyblk.data = key_block2;
-        keyblk.len = keySize;
-        status = TLS_PRF(&secret, "server write key", &crsr, &keyblk, isFIPS);
-        if (status != SECSuccess) {
-            goto key_and_mac_derive_fail;
-        }
-        buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item,
-                    "TLS Export Server Write Key");
-        key_block2 += keySize;
-
-        /*
-        ** iv_block = PRF("", "IV block", client_random + server_random);
-        ** client_write_IV[SecurityParameters.IV_size]
-        ** server_write_IV[SecurityParameters.IV_size]
-        */
-        if (IVSize) {
-            secret.data = NULL;
-            secret.len = 0;
-            keyblk.data = key_block2;
-            keyblk.len = 2 * IVSize;
-            status = TLS_PRF(&secret, "IV block", &crsr, &keyblk, isFIPS);
-            if (status != SECSuccess) {
-                goto key_and_mac_derive_fail;
-            }
-            buildSSLKey(key_block2, IVSize,
-                        &pwSpec->client.write_iv_item,
-                        "TLS Export Client Write IV");
-            buildSSLKey(key_block2 + IVSize, IVSize,
-                        &pwSpec->server.write_iv_item,
-                        "TLS Export Server Write IV");
-            key_block2 += 2 * IVSize;
-        }
-        PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block);
-    }
-    rv = SECSuccess;
-
-key_and_mac_derive_fail:
-
-    MD5_DestroyContext(md5Ctx, PR_FALSE);
-    SHA1_DestroyContext(shaCtx, PR_FALSE);
-
-    if (rv != SECSuccess) {
-        PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
-    }
-
-    return rv;
-}
-
-/* derive the Master Secret from the PMS */
-/* Presently, this is only done wtih RSA PMS, and only on the server side,
- * so isRSA is always true.
- */
-SECStatus
-ssl3_MasterSecretDeriveBypass(
-    ssl3CipherSpec *pwSpec,
-    const unsigned char *cr,
-    const unsigned char *sr,
-    const SECItem *pms,
-    PRBool isTLS,
-    PRBool isRSA)
-{
-    unsigned char *key_block = pwSpec->key_block;
-    SECStatus rv = SECSuccess;
-    PRBool isFIPS = PR_FALSE;
-    PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2;
-
-    SECItem crsr;
-
-    unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
-    PRUint64 md5buf[22];
-    PRUint64 shabuf[40];
-
-#define md5Ctx ((MD5Context *)md5buf)
-#define shaCtx ((SHA1Context *)shabuf)
-
-    /* first do the consistancy checks */
-    if (isRSA) {
-        PORT_Assert(pms->len == SSL3_RSA_PMS_LENGTH);
-        if (pms->len != SSL3_RSA_PMS_LENGTH) {
-            PORT_SetError(SEC_ERROR_INVALID_ARGS);
-            return SECFailure;
-        }
-        /* caller must test PMS version for rollback */
-    }
-
-    /* initialize the client random, server random block */
-    crsr.type = siBuffer;
-    crsr.data = crsrdata;
-    crsr.len = sizeof crsrdata;
-    PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH);
-    PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH);
-    PRINT_BUF(100, (NULL, "Master Secret CRSR", crsr.data, crsr.len));
-
-    /* finally do the key gen */
-    if (isTLS) {
-        SECItem master = { siBuffer, NULL, 0 };
-
-        master.data = key_block;
-        master.len = SSL3_MASTER_SECRET_LENGTH;
-
-        if (isTLS12) {
-            rv = TLS_P_hash(HASH_AlgSHA256, pms, "master secret", &crsr,
-                            &master, isFIPS);
-        } else {
-            rv = TLS_PRF(pms, "master secret", &crsr, &master, isFIPS);
-        }
-        if (rv != SECSuccess) {
-            PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
-        }
-    } else {
-        int i;
-        unsigned int made = 0;
-        for (i = 0; i < 3; i++) {
-            unsigned int outLen;
-            unsigned char sha_out[SHA1_LENGTH];
-
-            SHA1_Begin(shaCtx);
-            SHA1_Update(shaCtx, (unsigned char *)mixers[i], i + 1);
-            SHA1_Update(shaCtx, pms->data, pms->len);
-            SHA1_Update(shaCtx, crsr.data, crsr.len);
-            SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH);
-            PORT_Assert(outLen == SHA1_LENGTH);
-
-            MD5_Begin(md5Ctx);
-            MD5_Update(md5Ctx, pms->data, pms->len);
-            MD5_Update(md5Ctx, sha_out, outLen);
-            MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH);
-            PORT_Assert(outLen == MD5_LENGTH);
-            made += outLen;
-        }
-    }
-
-    /* store the results */
-    PORT_Memcpy(pwSpec->raw_master_secret, key_block,
-                SSL3_MASTER_SECRET_LENGTH);
-    pwSpec->msItem.data = pwSpec->raw_master_secret;
-    pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH;
-    PRINT_BUF(100, (NULL, "Master Secret", pwSpec->msItem.data,
-                    pwSpec->msItem.len));
-
-    return rv;
-}
-
-static SECStatus
-ssl_canExtractMS(PK11SymKey *pms, PRBool isTLS, PRBool isDH, PRBool *pcbp)
-{
-    SECStatus rv;
-    PK11SymKey *ms = NULL;
-    SECItem params = { siBuffer, NULL, 0 };
-    CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params;
-    unsigned char rand[SSL3_RANDOM_LENGTH];
-    CK_VERSION pms_version;
-    CK_MECHANISM_TYPE master_derive;
-    CK_MECHANISM_TYPE key_derive;
-    CK_FLAGS keyFlags;
-
-    if (pms == NULL)
-        return (SECFailure);
-
-    PORT_Memset(rand, 0, SSL3_RANDOM_LENGTH);
-
-    if (isTLS) {
-        if (isDH)
-            master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH;
-        else
-            master_derive = CKM_TLS_MASTER_KEY_DERIVE;
-        key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
-        keyFlags = CKF_SIGN | CKF_VERIFY;
-    } else {
-        if (isDH)
-            master_derive = CKM_SSL3_MASTER_KEY_DERIVE_DH;
-        else
-            master_derive = CKM_SSL3_MASTER_KEY_DERIVE;
-        key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE;
-        keyFlags = 0;
-    }
-
-    master_params.pVersion = &pms_version;
-    master_params.RandomInfo.pClientRandom = rand;
-    master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
-    master_params.RandomInfo.pServerRandom = rand;
-    master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;
-
-    params.data = (unsigned char *)&master_params;
-    params.len = sizeof master_params;
-
-    ms = PK11_DeriveWithFlags(pms, master_derive, &params, key_derive,
-                              CKA_DERIVE, 0, keyFlags);
-    if (ms == NULL)
-        return (SECFailure);
-
-    rv = PK11_ExtractKeyValue(ms);
-    *pcbp = (rv == SECSuccess);
-    PK11_FreeSymKey(ms);
-
-    return (rv);
-}
-#endif /* !NO_PKCS11_BYPASS */
-
-/* Check the key exchange algorithm for each cipher in the list to see if
- * a master secret key can be extracted. If the KEA will use keys from the
- * specified cert make sure the extract operation is attempted from the slot
- * where the private key resides.
- * If MS can be extracted for all ciphers, (*pcanbypass) is set to TRUE and
- * SECSuccess is returned. In all other cases but one (*pcanbypass) is
- * set to FALSE and SECFailure is returned.
- * In that last case Derive() has been called successfully but the MS is null,
- * CanBypass sets (*pcanbypass) to FALSE and returns SECSuccess indicating the
- * arguments were all valid but the slot cannot be bypassed.
- */
-
-/* XXX Add SSL_CBP_TLS1_1 and test it in protocolmask when setting isTLS. */
-
-SECStatus
-SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey,
-              PRUint32 protocolmask, PRUint16 *ciphersuites, int nsuites,
-              PRBool *pcanbypass, void *pwArg)
-{
-#ifdef NO_PKCS11_BYPASS
-    if (!pcanbypass) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-    *pcanbypass = PR_FALSE;
-    return SECSuccess;
-#else
-    SECStatus rv;
-    int i;
-    PRUint16 suite;
-    PK11SymKey *pms = NULL;
-    SECKEYPublicKey *srvPubkey = NULL;
-    KeyType privKeytype;
-    PK11SlotInfo *slot = NULL;
-    SECItem param;
-    CK_VERSION version;
-    CK_MECHANISM_TYPE mechanism_array[2];
-    SECItem enc_pms = { siBuffer, NULL, 0 };
-    PRBool isTLS = PR_FALSE;
-    SSLCipherSuiteInfo csdef;
-    PRBool testrsa = PR_FALSE;
-    PRBool testrsa_export = PR_FALSE;
-    PRBool testecdh = PR_FALSE;
-    PRBool testecdhe = PR_FALSE;
-#ifndef NSS_DISABLE_ECC
-    SECKEYECParams ecParams = { siBuffer, NULL, 0 };
-#endif
-
-    if (!cert || !srvPrivkey || !ciphersuites || !pcanbypass) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    srvPubkey = CERT_ExtractPublicKey(cert);
-    if (!srvPubkey)
-        return SECFailure;
-
-    *pcanbypass = PR_TRUE;
-    rv = SECFailure;
-
-    /* determine which KEAs to test */
-    /* 0 (TLS_NULL_WITH_NULL_NULL) is used as a list terminator because
-     * SSL3 and TLS specs forbid negotiating that cipher suite number.
-     */
-    for (i = 0; i < nsuites && (suite = *ciphersuites++) != 0; i++) {
-        /* skip SSL2 cipher suites and ones NSS doesn't support */
-        if (SSL_GetCipherSuiteInfo(suite, &csdef, sizeof(csdef)) != SECSuccess ||
-            SSL_IS_SSL2_CIPHER(suite))
-            continue;
-        switch (csdef.keaType) {
-            case ssl_kea_rsa:
-                switch (csdef.cipherSuite) {
-                    case TLS_RSA_EXPORT1024_WITH_RC4_56_SHA:
-                    case TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA:
-                    case TLS_RSA_EXPORT_WITH_RC4_40_MD5:
-                    case TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
-                        testrsa_export = PR_TRUE;
-                }
-                if (!testrsa_export)
-                    testrsa = PR_TRUE;
-                break;
-            case ssl_kea_ecdh:
-                if (strcmp(csdef.keaTypeName, "ECDHE") == 0) /* ephemeral? */
-                    testecdhe = PR_TRUE;
-                else
-                    testecdh = PR_TRUE;
-                break;
-            case ssl_kea_dh:
-            /* this is actually DHE */
-            default:
-                continue;
-        }
-    }
-
-    /* For each protocol try to derive and extract an MS.
-     * Failure of function any function except MS extract means
-     * continue with the next cipher test. Stop testing when the list is
-     * exhausted or when the first MS extract--not derive--fails.
-     */
-    privKeytype = SECKEY_GetPrivateKeyType(srvPrivkey);
-    protocolmask &= SSL_CBP_SSL3 | SSL_CBP_TLS1_0;
-    while (protocolmask) {
-        if (protocolmask & SSL_CBP_SSL3) {
-            isTLS = PR_FALSE;
-            protocolmask ^= SSL_CBP_SSL3;
-        } else {
-            isTLS = PR_TRUE;
-            protocolmask ^= SSL_CBP_TLS1_0;
-        }
-
-        if (privKeytype == rsaKey && testrsa_export) {
-            if (PK11_GetPrivateModulusLen(srvPrivkey) > EXPORT_RSA_KEY_LENGTH) {
-                *pcanbypass = PR_FALSE;
-                rv = SECSuccess;
-                break;
-            } else
-                testrsa = PR_TRUE;
-        }
-        for (; privKeytype == rsaKey && testrsa;) {
-            /* TLS_RSA */
-            unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH];
-            unsigned int outLen = 0;
-            CK_MECHANISM_TYPE target;
-            SECStatus irv;
-
-            mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN;
-            mechanism_array[1] = CKM_RSA_PKCS;
-
-            slot = PK11_GetBestSlotMultiple(mechanism_array, 2, pwArg);
-            if (slot == NULL) {
-                PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND);
-                break;
-            }
-
-            /* Generate the pre-master secret ...  (client side) */
-            version.major = 3 /*MSB(clientHelloVersion)*/;
-            version.minor = 0 /*LSB(clientHelloVersion)*/;
-            param.data = (unsigned char *)&version;
-            param.len = sizeof version;
-            pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, &param, 0, pwArg);
-            PK11_FreeSlot(slot);
-            if (!pms)
-                break;
-            /* now wrap it */
-            enc_pms.len = SECKEY_PublicKeyStrength(srvPubkey);
-            enc_pms.data = (unsigned char *)PORT_Alloc(enc_pms.len);
-            if (enc_pms.data == NULL) {
-                PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
-                break;
-            }
-            irv = PK11_PubWrapSymKey(CKM_RSA_PKCS, srvPubkey, pms, &enc_pms);
-            if (irv != SECSuccess)
-                break;
-            PK11_FreeSymKey(pms);
-            pms = NULL;
-            /* now do the server side--check the triple bypass first */
-            rv = PK11_PrivDecryptPKCS1(srvPrivkey, rsaPmsBuf, &outLen,
-                                       sizeof rsaPmsBuf,
-                                       (unsigned char *)enc_pms.data,
-                                       enc_pms.len);
-            /* if decrypt worked we're done with the RSA test */
-            if (rv == SECSuccess) {
-                *pcanbypass = PR_TRUE;
-                break;
-            }
-            /* check for fallback to double bypass */
-            target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE
-                           : CKM_SSL3_MASTER_KEY_DERIVE;
-            pms = PK11_PubUnwrapSymKey(srvPrivkey, &enc_pms,
-                                       target, CKA_DERIVE, 0);
-            rv = ssl_canExtractMS(pms, isTLS, PR_FALSE, pcanbypass);
-            if (rv == SECSuccess && *pcanbypass == PR_FALSE)
-                goto done;
-            break;
-        }
-
-        /* Check for NULL to avoid double free.
-         * SECItem_FreeItem sets data NULL in secitem.c#265
-         */
-        if (enc_pms.data != NULL) {
-            SECITEM_FreeItem(&enc_pms, PR_FALSE);
-        }
-#ifndef NSS_DISABLE_ECC
-        for (; (privKeytype == ecKey && (testecdh || testecdhe)) ||
-               (privKeytype == rsaKey && testecdhe);) {
-            CK_MECHANISM_TYPE target;
-            SECKEYPublicKey *keapub = NULL;
-            SECKEYPrivateKey *keapriv;
-            SECKEYPublicKey *cpub = NULL; /* client's ephemeral ECDH keys */
-            SECKEYPrivateKey *cpriv = NULL;
-            SECKEYECParams *pecParams = NULL;
-
-            if (privKeytype == ecKey && testecdhe) {
-                /* TLS_ECDHE_ECDSA */
-                pecParams = &srvPubkey->u.ec.DEREncodedParams;
-            } else if (privKeytype == rsaKey && testecdhe) {
-                /* TLS_ECDHE_RSA */
-                ECName ec_curve;
-                int serverKeyStrengthInBits;
-                int signatureKeyStrength;
-                int requiredECCbits;
-
-                /* find a curve of equivalent strength to the RSA key's */
-                requiredECCbits = PK11_GetPrivateModulusLen(srvPrivkey);
-                if (requiredECCbits < 0)
-                    break;
-                requiredECCbits *= BPB;
-                serverKeyStrengthInBits = srvPubkey->u.rsa.modulus.len;
-                if (srvPubkey->u.rsa.modulus.data[0] == 0) {
-                    serverKeyStrengthInBits--;
-                }
-                /* convert to strength in bits */
-                serverKeyStrengthInBits *= BPB;
-
-                signatureKeyStrength =
-                    SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits);
-
-                if (requiredECCbits > signatureKeyStrength)
-                    requiredECCbits = signatureKeyStrength;
-
-                ec_curve =
-                    ssl3_GetCurveWithECKeyStrength(
-                        ssl3_GetSupportedECCurveMask(NULL),
-                        requiredECCbits);
-                rv = ssl3_ECName2Params(NULL, ec_curve, &ecParams);
-                if (rv == SECFailure) {
-                    break;
-                }
-                pecParams = &ecParams;
-            }
-
-            if (testecdhe) {
-                /* generate server's ephemeral keys */
-                keapriv = SECKEY_CreateECPrivateKey(pecParams, &keapub, NULL);
-                if (!keapriv || !keapub) {
-                    if (keapriv)
-                        SECKEY_DestroyPrivateKey(keapriv);
-                    if (keapub)
-                        SECKEY_DestroyPublicKey(keapub);
-                    PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
-                    rv = SECFailure;
-                    break;
-                }
-            } else {
-                /* TLS_ECDH_ECDSA */
-                keapub = srvPubkey;
-                keapriv = srvPrivkey;
-                pecParams = &srvPubkey->u.ec.DEREncodedParams;
-            }
-
-            /* perform client side ops */
-            /* generate a pair of ephemeral keys using server's parms */
-            cpriv = SECKEY_CreateECPrivateKey(pecParams, &cpub, NULL);
-            if (!cpriv || !cpub) {
-                if (testecdhe) {
-                    SECKEY_DestroyPrivateKey(keapriv);
-                    SECKEY_DestroyPublicKey(keapub);
-                }
-                PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
-                rv = SECFailure;
-                break;
-            }
-            /* now do the server side */
-            /* determine the PMS using client's public value */
-            target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE_DH
-                           : CKM_SSL3_MASTER_KEY_DERIVE_DH;
-            pms = PK11_PubDeriveWithKDF(keapriv, cpub, PR_FALSE, NULL, NULL,
-                                        CKM_ECDH1_DERIVE,
-                                        target,
-                                        CKA_DERIVE, 0, CKD_NULL, NULL, NULL);
-            rv = ssl_canExtractMS(pms, isTLS, PR_TRUE, pcanbypass);
-            SECKEY_DestroyPrivateKey(cpriv);
-            SECKEY_DestroyPublicKey(cpub);
-            if (testecdhe) {
-                SECKEY_DestroyPrivateKey(keapriv);
-                SECKEY_DestroyPublicKey(keapub);
-            }
-            if (rv == SECSuccess && *pcanbypass == PR_FALSE)
-                goto done;
-            break;
-        }
-        /* Check for NULL to avoid double free. */
-        if (ecParams.data != NULL) {
-            PORT_Free(ecParams.data);
-            ecParams.data = NULL;
-        }
-#endif /* NSS_DISABLE_ECC */
-        if (pms)
-            PK11_FreeSymKey(pms);
-    }
-
-    /* *pcanbypass has been set */
-    rv = SECSuccess;
-
-done:
-    if (pms)
-        PK11_FreeSymKey(pms);
-
-    /* Check for NULL to avoid double free.
-     * SECItem_FreeItem sets data NULL in secitem.c#265
-     */
-    if (enc_pms.data != NULL) {
-        SECITEM_FreeItem(&enc_pms, PR_FALSE);
-    }
-#ifndef NSS_DISABLE_ECC
-    if (ecParams.data != NULL) {
-        PORT_Free(ecParams.data);
-        ecParams.data = NULL;
-    }
-#endif /* NSS_DISABLE_ECC */
-
-    if (srvPubkey) {
-        SECKEY_DestroyPublicKey(srvPubkey);
-        srvPubkey = NULL;
-    }
-
-    return rv;
-#endif /* NO_PKCS11_BYPASS */
-}
diff --git a/net/third_party/nss/ssl/dhe-param.c b/net/third_party/nss/ssl/dhe-param.c
deleted file mode 100644
index ac0942e..0000000
--- a/net/third_party/nss/ssl/dhe-param.c
+++ /dev/null
@@ -1,413 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-static const unsigned char ff_dhe_g2[] = { 2 };
-
-static const unsigned char ff_dhe_2048_p[] = {
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A,
-    0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
-    0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95,
-    0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
-    0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
-    0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8,
-    0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A,
-    0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
-    0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
-    0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3,
-    0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
-    0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77,
-    0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72,
-    0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
-    0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A,
-    0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61,
-    0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
-    0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68,
-    0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
-    0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
-    0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70,
-    0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC,
-    0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
-    0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
-    0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83,
-    0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
-    0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05,
-    0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2,
-    0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
-    0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97,
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-static const ssl3DHParams ff_dhe_2048 = {
-    { siBuffer, (unsigned char *)ff_dhe_2048_p, sizeof(ff_dhe_2048_p) },
-    { siBuffer, (unsigned char *)ff_dhe_g2, sizeof(ff_dhe_g2) },
-};
-
-static const unsigned char ff_dhe_3072_p[] = {
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A,
-    0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
-    0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95,
-    0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
-    0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
-    0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8,
-    0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A,
-    0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
-    0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
-    0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3,
-    0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
-    0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77,
-    0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72,
-    0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
-    0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A,
-    0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61,
-    0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
-    0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68,
-    0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
-    0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
-    0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70,
-    0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC,
-    0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
-    0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
-    0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83,
-    0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
-    0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05,
-    0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2,
-    0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
-    0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC,
-    0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B,
-    0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38,
-    0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07,
-    0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE,
-    0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C,
-    0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70,
-    0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44,
-    0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3,
-    0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF,
-    0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E,
-    0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D,
-    0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA,
-    0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E,
-    0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF,
-    0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C,
-    0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37,
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-static const ssl3DHParams ff_dhe_3072 = {
-    { siBuffer, (unsigned char *)ff_dhe_3072_p, sizeof(ff_dhe_3072_p) },
-    { siBuffer, (unsigned char *)ff_dhe_g2, sizeof(ff_dhe_g2) },
-};
-
-static const unsigned char ff_dhe_4096_p[] = {
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A,
-    0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
-    0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95,
-    0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
-    0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
-    0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8,
-    0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A,
-    0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
-    0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
-    0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3,
-    0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
-    0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77,
-    0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72,
-    0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
-    0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A,
-    0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61,
-    0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
-    0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68,
-    0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
-    0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
-    0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70,
-    0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC,
-    0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
-    0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
-    0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83,
-    0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
-    0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05,
-    0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2,
-    0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
-    0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC,
-    0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B,
-    0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38,
-    0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07,
-    0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE,
-    0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C,
-    0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70,
-    0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44,
-    0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3,
-    0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF,
-    0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E,
-    0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D,
-    0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA,
-    0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E,
-    0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF,
-    0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C,
-    0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1,
-    0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB,
-    0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6,
-    0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18,
-    0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04,
-    0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A,
-    0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A,
-    0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32,
-    0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4,
-    0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38,
-    0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A,
-    0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C,
-    0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC,
-    0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF,
-    0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B,
-    0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1,
-    0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A,
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-static const ssl3DHParams ff_dhe_4096 = {
-    { siBuffer, (unsigned char *)ff_dhe_4096_p, sizeof(ff_dhe_4096_p) },
-    { siBuffer, (unsigned char *)ff_dhe_g2, sizeof(ff_dhe_g2) },
-};
-
-static const unsigned char ff_dhe_6144_p[] = {
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A,
-    0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
-    0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95,
-    0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
-    0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
-    0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8,
-    0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A,
-    0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
-    0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
-    0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3,
-    0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
-    0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77,
-    0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72,
-    0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
-    0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A,
-    0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61,
-    0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
-    0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68,
-    0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
-    0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
-    0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70,
-    0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC,
-    0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
-    0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
-    0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83,
-    0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
-    0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05,
-    0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2,
-    0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
-    0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC,
-    0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B,
-    0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38,
-    0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07,
-    0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE,
-    0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C,
-    0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70,
-    0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44,
-    0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3,
-    0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF,
-    0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E,
-    0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D,
-    0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA,
-    0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E,
-    0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF,
-    0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C,
-    0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1,
-    0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB,
-    0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6,
-    0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18,
-    0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04,
-    0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A,
-    0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A,
-    0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32,
-    0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4,
-    0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38,
-    0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A,
-    0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C,
-    0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC,
-    0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF,
-    0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B,
-    0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1,
-    0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02,
-    0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A,
-    0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A,
-    0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6,
-    0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8,
-    0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C,
-    0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A,
-    0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71,
-    0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F,
-    0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77,
-    0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10,
-    0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8,
-    0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3,
-    0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E,
-    0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3,
-    0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4,
-    0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1,
-    0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92,
-    0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6,
-    0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82,
-    0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE,
-    0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C,
-    0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E,
-    0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46,
-    0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A,
-    0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17,
-    0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03,
-    0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04,
-    0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6,
-    0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69,
-    0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1,
-    0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4,
-    0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65,
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-static const ssl3DHParams ff_dhe_6144 = {
-    { siBuffer, (unsigned char *)ff_dhe_6144_p, sizeof(ff_dhe_6144_p) },
-    { siBuffer, (unsigned char *)ff_dhe_g2, sizeof(ff_dhe_g2) },
-};
-
-static const unsigned char ff_dhe_8192_p[] = {
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A,
-    0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
-    0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95,
-    0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
-    0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
-    0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8,
-    0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A,
-    0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
-    0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
-    0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3,
-    0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
-    0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77,
-    0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72,
-    0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
-    0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A,
-    0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61,
-    0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
-    0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68,
-    0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
-    0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
-    0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70,
-    0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC,
-    0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
-    0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
-    0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83,
-    0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
-    0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05,
-    0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2,
-    0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
-    0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC,
-    0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B,
-    0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38,
-    0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07,
-    0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE,
-    0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C,
-    0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70,
-    0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44,
-    0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3,
-    0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF,
-    0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E,
-    0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D,
-    0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA,
-    0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E,
-    0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF,
-    0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C,
-    0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1,
-    0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB,
-    0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6,
-    0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18,
-    0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04,
-    0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A,
-    0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A,
-    0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32,
-    0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4,
-    0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38,
-    0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A,
-    0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C,
-    0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC,
-    0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF,
-    0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B,
-    0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1,
-    0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02,
-    0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A,
-    0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A,
-    0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6,
-    0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8,
-    0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C,
-    0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A,
-    0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71,
-    0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F,
-    0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77,
-    0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10,
-    0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8,
-    0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3,
-    0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E,
-    0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3,
-    0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4,
-    0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1,
-    0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92,
-    0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6,
-    0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82,
-    0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE,
-    0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C,
-    0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E,
-    0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46,
-    0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A,
-    0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17,
-    0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03,
-    0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04,
-    0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6,
-    0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69,
-    0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1,
-    0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4,
-    0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA,
-    0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38,
-    0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64,
-    0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43,
-    0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E,
-    0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF,
-    0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29,
-    0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65,
-    0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02,
-    0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4,
-    0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82,
-    0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C,
-    0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51,
-    0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22,
-    0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74,
-    0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE,
-    0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C,
-    0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC,
-    0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B,
-    0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9,
-    0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0,
-    0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31,
-    0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57,
-    0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8,
-    0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E,
-    0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30,
-    0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E,
-    0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE,
-    0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D,
-    0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D,
-    0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E,
-    0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C,
-    0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C,
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-static const ssl3DHParams ff_dhe_8192 = {
-    { siBuffer, (unsigned char *)ff_dhe_8192_p, sizeof(ff_dhe_8192_p) },
-    { siBuffer, (unsigned char *)ff_dhe_g2, sizeof(ff_dhe_g2) },
-};
diff --git a/net/third_party/nss/ssl/dtlscon.c b/net/third_party/nss/ssl/dtlscon.c
deleted file mode 100644
index 35d995e..0000000
--- a/net/third_party/nss/ssl/dtlscon.c
+++ /dev/null
@@ -1,1195 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
- * DTLS Protocol
- */
-
-#include "ssl.h"
-#include "sslimpl.h"
-#include "sslproto.h"
-
-#ifndef PR_ARRAY_SIZE
-#define PR_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-#endif
-
-static SECStatus dtls_TransmitMessageFlight(sslSocket *ss);
-static void dtls_RetransmitTimerExpiredCb(sslSocket *ss);
-static SECStatus dtls_SendSavedWriteData(sslSocket *ss);
-
-/* -28 adjusts for the IP/UDP header */
-static const PRUint16 COMMON_MTU_VALUES[] = {
-    1500 - 28, /* Ethernet MTU */
-    1280 - 28, /* IPv6 minimum MTU */
-    576 - 28,  /* Common assumption */
-    256 - 28   /* We're in serious trouble now */
-};
-
-#define DTLS_COOKIE_BYTES 32
-
-/* List copied from ssl3con.c:cipherSuites */
-static const ssl3CipherSuite nonDTLSSuites[] = {
-#ifndef NSS_DISABLE_ECC
-    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
-    TLS_ECDHE_RSA_WITH_RC4_128_SHA,
-#endif /* NSS_DISABLE_ECC */
-    TLS_DHE_DSS_WITH_RC4_128_SHA,
-#ifndef NSS_DISABLE_ECC
-    TLS_ECDH_RSA_WITH_RC4_128_SHA,
-    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
-#endif /* NSS_DISABLE_ECC */
-    TLS_RSA_WITH_RC4_128_MD5,
-    TLS_RSA_WITH_RC4_128_SHA,
-    TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,
-    TLS_RSA_EXPORT_WITH_RC4_40_MD5,
-    0 /* End of list marker */
-};
-
-/* Map back and forth between TLS and DTLS versions in wire format.
- * Mapping table is:
- *
- * TLS             DTLS
- * 1.1 (0302)      1.0 (feff)
- * 1.2 (0303)      1.2 (fefd)
- * 1.3 (0304)      1.3 (fefc)
- */
-SSL3ProtocolVersion
-dtls_TLSVersionToDTLSVersion(SSL3ProtocolVersion tlsv)
-{
-    if (tlsv == SSL_LIBRARY_VERSION_TLS_1_1) {
-        return SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
-    }
-    if (tlsv == SSL_LIBRARY_VERSION_TLS_1_2) {
-        return SSL_LIBRARY_VERSION_DTLS_1_2_WIRE;
-    }
-    if (tlsv == SSL_LIBRARY_VERSION_TLS_1_3) {
-        return SSL_LIBRARY_VERSION_DTLS_1_3_WIRE;
-    }
-
-    /* Anything other than TLS 1.1 or 1.2 is an error, so return
-     * the invalid version 0xffff. */
-    return 0xffff;
-}
-
-/* Map known DTLS versions to known TLS versions.
- * - Invalid versions (< 1.0) return a version of 0
- * - Versions > known return a version one higher than we know of
- * to accomodate a theoretically newer version */
-SSL3ProtocolVersion
-dtls_DTLSVersionToTLSVersion(SSL3ProtocolVersion dtlsv)
-{
-    if (MSB(dtlsv) == 0xff) {
-        return 0;
-    }
-
-    if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_0_WIRE) {
-        return SSL_LIBRARY_VERSION_TLS_1_1;
-    }
-    /* Handle the skipped version of DTLS 1.1 by returning
-     * an error. */
-    if (dtlsv == ((~0x0101) & 0xffff)) {
-        return 0;
-    }
-    if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_2_WIRE) {
-        return SSL_LIBRARY_VERSION_TLS_1_2;
-    }
-    if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_3_WIRE) {
-        return SSL_LIBRARY_VERSION_TLS_1_3;
-    }
-
-    /* Return a fictional higher version than we know of */
-    return SSL_LIBRARY_VERSION_MAX_SUPPORTED + 1;
-}
-
-/* On this socket, Disable non-DTLS cipher suites in the argument's list */
-SECStatus
-ssl3_DisableNonDTLSSuites(sslSocket *ss)
-{
-    const ssl3CipherSuite *suite;
-
-    for (suite = nonDTLSSuites; *suite; ++suite) {
-        PORT_CheckSuccess(ssl3_CipherPrefSet(ss, *suite, PR_FALSE));
-    }
-    return SECSuccess;
-}
-
-/* Allocate a DTLSQueuedMessage.
- *
- * Called from dtls_QueueMessage()
- */
-static DTLSQueuedMessage *
-dtls_AllocQueuedMessage(PRUint16 epoch, SSL3ContentType type,
-                        const unsigned char *data, PRUint32 len)
-{
-    DTLSQueuedMessage *msg = NULL;
-
-    msg = PORT_ZAlloc(sizeof(DTLSQueuedMessage));
-    if (!msg)
-        return NULL;
-
-    msg->data = PORT_Alloc(len);
-    if (!msg->data) {
-        PORT_Free(msg);
-        return NULL;
-    }
-    PORT_Memcpy(msg->data, data, len);
-
-    msg->len = len;
-    msg->epoch = epoch;
-    msg->type = type;
-
-    return msg;
-}
-
-/*
- * Free a handshake message
- *
- * Called from dtls_FreeHandshakeMessages()
- */
-static void
-dtls_FreeHandshakeMessage(DTLSQueuedMessage *msg)
-{
-    if (!msg)
-        return;
-
-    PORT_ZFree(msg->data, msg->len);
-    PORT_Free(msg);
-}
-
-/*
- * Free a list of handshake messages
- *
- * Called from:
- *              dtls_HandleHandshake()
- *              ssl3_DestroySSL3Info()
- */
-void
-dtls_FreeHandshakeMessages(PRCList *list)
-{
-    PRCList *cur_p;
-
-    while (!PR_CLIST_IS_EMPTY(list)) {
-        cur_p = PR_LIST_TAIL(list);
-        PR_REMOVE_LINK(cur_p);
-        dtls_FreeHandshakeMessage((DTLSQueuedMessage *)cur_p);
-    }
-}
-
-/* Called only from ssl3_HandleRecord, for each (deciphered) DTLS record.
- * origBuf is the decrypted ssl record content and is expected to contain
- * complete handshake records
- * Caller must hold the handshake and RecvBuf locks.
- *
- * Note that this code uses msg_len for two purposes:
- *
- * (1) To pass the length to ssl3_HandleHandshakeMessage()
- * (2) To carry the length of a message currently being reassembled
- *
- * However, unlike ssl3_HandleHandshake(), it is not used to carry
- * the state of reassembly (i.e., whether one is in progress). That
- * is carried in recvdHighWater and recvdFragments.
- */
-#define OFFSET_BYTE(o) (o / 8)
-#define OFFSET_MASK(o) (1 << (o % 8))
-
-SECStatus
-dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
-{
-    /* XXX OK for now.
-     * This doesn't work properly with asynchronous certificate validation.
-     * because that returns a WOULDBLOCK error. The current DTLS
-     * applications do not need asynchronous validation, but in the
-     * future we will need to add this.
-     */
-    sslBuffer buf = *origBuf;
-    SECStatus rv = SECSuccess;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    while (buf.len > 0) {
-        PRUint8 type;
-        PRUint32 message_length;
-        PRUint16 message_seq;
-        PRUint32 fragment_offset;
-        PRUint32 fragment_length;
-        PRUint32 offset;
-
-        if (buf.len < 12) {
-            PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
-            rv = SECFailure;
-            break;
-        }
-
-        /* Parse the header */
-        type = buf.buf[0];
-        message_length = (buf.buf[1] << 16) | (buf.buf[2] << 8) | buf.buf[3];
-        message_seq = (buf.buf[4] << 8) | buf.buf[5];
-        fragment_offset = (buf.buf[6] << 16) | (buf.buf[7] << 8) | buf.buf[8];
-        fragment_length = (buf.buf[9] << 16) | (buf.buf[10] << 8) | buf.buf[11];
-
-#define MAX_HANDSHAKE_MSG_LEN 0x1ffff /* 128k - 1 */
-        if (message_length > MAX_HANDSHAKE_MSG_LEN) {
-            (void)ssl3_DecodeError(ss);
-            PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
-            return SECFailure;
-        }
-#undef MAX_HANDSHAKE_MSG_LEN
-
-        buf.buf += 12;
-        buf.len -= 12;
-
-        /* This fragment must be complete */
-        if (buf.len < fragment_length) {
-            PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
-            rv = SECFailure;
-            break;
-        }
-
-        /* Sanity check the packet contents */
-        if ((fragment_length + fragment_offset) > message_length) {
-            PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
-            rv = SECFailure;
-            break;
-        }
-
-        /* There are three ways we could not be ready for this packet.
-         *
-         * 1. It's a partial next message.
-         * 2. It's a partial or complete message beyond the next
-         * 3. It's a message we've already seen
-         *
-         * If it's the complete next message we accept it right away.
-         * This is the common case for short messages
-         */
-        if ((message_seq == ss->ssl3.hs.recvMessageSeq) &&
-            (fragment_offset == 0) &&
-            (fragment_length == message_length)) {
-            /* Complete next message. Process immediately */
-            ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
-            ss->ssl3.hs.msg_len = message_length;
-
-            /* At this point we are advancing our state machine, so
-             * we can free our last flight of messages */
-            dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
-            ss->ssl3.hs.recvdHighWater = -1;
-            dtls_CancelTimer(ss);
-
-            /* Reset the timer to the initial value if the retry counter
-             * is 0, per Sec. 4.2.4.1 */
-            if (ss->ssl3.hs.rtRetries == 0) {
-                ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
-            }
-
-            rv = ssl3_HandleHandshakeMessage(ss, buf.buf, ss->ssl3.hs.msg_len);
-            if (rv == SECFailure) {
-                /* Do not attempt to process rest of messages in this record */
-                break;
-            }
-        } else {
-            if (message_seq < ss->ssl3.hs.recvMessageSeq) {
-                /* Case 3: we do an immediate retransmit if we're
-                 * in a waiting state*/
-                if (ss->ssl3.hs.rtTimerCb == NULL) {
-                    /* Ignore */
-                } else if (ss->ssl3.hs.rtTimerCb ==
-                           dtls_RetransmitTimerExpiredCb) {
-                    SSL_TRC(30, ("%d: SSL3[%d]: Retransmit detected",
-                                 SSL_GETPID(), ss->fd));
-                    /* Check to see if we retransmitted recently. If so,
-                     * suppress the triggered retransmit. This avoids
-                     * retransmit wars after packet loss.
-                     * This is not in RFC 5346 but should be
-                     */
-                    if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
-                        (ss->ssl3.hs.rtTimeoutMs / 4)) {
-                        SSL_TRC(30,
-                                ("%d: SSL3[%d]: Shortcutting retransmit timer",
-                                 SSL_GETPID(), ss->fd));
-
-                        /* Cancel the timer and call the CB,
-                         * which re-arms the timer */
-                        dtls_CancelTimer(ss);
-                        dtls_RetransmitTimerExpiredCb(ss);
-                        rv = SECSuccess;
-                        break;
-                    } else {
-                        SSL_TRC(30,
-                                ("%d: SSL3[%d]: We just retransmitted. Ignoring.",
-                                 SSL_GETPID(), ss->fd));
-                        rv = SECSuccess;
-                        break;
-                    }
-                } else if (ss->ssl3.hs.rtTimerCb == dtls_FinishedTimerCb) {
-                    /* Retransmit the messages and re-arm the timer
-                     * Note that we are not backing off the timer here.
-                     * The spec isn't clear and my reasoning is that this
-                     * may be a re-ordered packet rather than slowness,
-                     * so let's be aggressive. */
-                    dtls_CancelTimer(ss);
-                    rv = dtls_TransmitMessageFlight(ss);
-                    if (rv == SECSuccess) {
-                        rv = dtls_StartTimer(ss, dtls_FinishedTimerCb);
-                    }
-                    if (rv != SECSuccess)
-                        return rv;
-                    break;
-                }
-            } else if (message_seq > ss->ssl3.hs.recvMessageSeq) {
-                /* Case 2
-                 *
-                 * Ignore this message. This means we don't handle out of
-                 * order complete messages that well, but we're still
-                 * compliant and this probably does not happen often
-                 *
-                 * XXX OK for now. Maybe do something smarter at some point?
-                 */
-            } else {
-                /* Case 1
-                 *
-                 * Buffer the fragment for reassembly
-                 */
-                /* Make room for the message */
-                if (ss->ssl3.hs.recvdHighWater == -1) {
-                    PRUint32 map_length = OFFSET_BYTE(message_length) + 1;
-
-                    rv = sslBuffer_Grow(&ss->ssl3.hs.msg_body, message_length);
-                    if (rv != SECSuccess)
-                        break;
-                    /* Make room for the fragment map */
-                    rv = sslBuffer_Grow(&ss->ssl3.hs.recvdFragments,
-                                        map_length);
-                    if (rv != SECSuccess)
-                        break;
-
-                    /* Reset the reassembly map */
-                    ss->ssl3.hs.recvdHighWater = 0;
-                    PORT_Memset(ss->ssl3.hs.recvdFragments.buf, 0,
-                                ss->ssl3.hs.recvdFragments.space);
-                    ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
-                    ss->ssl3.hs.msg_len = message_length;
-                }
-
-                /* If we have a message length mismatch, abandon the reassembly
-                 * in progress and hope that the next retransmit will give us
-                 * something sane
-                 */
-                if (message_length != ss->ssl3.hs.msg_len) {
-                    ss->ssl3.hs.recvdHighWater = -1;
-                    PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
-                    rv = SECFailure;
-                    break;
-                }
-
-                /* Now copy this fragment into the buffer */
-                PORT_Assert((fragment_offset + fragment_length) <=
-                            ss->ssl3.hs.msg_body.space);
-                PORT_Memcpy(ss->ssl3.hs.msg_body.buf + fragment_offset,
-                            buf.buf, fragment_length);
-
-                /* This logic is a bit tricky. We have two values for
-                 * reassembly state:
-                 *
-                 * - recvdHighWater contains the highest contiguous number of
-                 *   bytes received
-                 * - recvdFragments contains a bitmask of packets received
-                 *   above recvdHighWater
-                 *
-                 * This avoids having to fill in the bitmask in the common
-                 * case of adjacent fragments received in sequence
-                 */
-                if (fragment_offset <= (unsigned int)ss->ssl3.hs.recvdHighWater) {
-                    /* Either this is the adjacent fragment or an overlapping
-                     * fragment */
-                    ss->ssl3.hs.recvdHighWater = fragment_offset +
-                                                 fragment_length;
-                } else {
-                    for (offset = fragment_offset;
-                         offset < fragment_offset + fragment_length;
-                         offset++) {
-                        ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] |=
-                            OFFSET_MASK(offset);
-                    }
-                }
-
-                /* Now figure out the new high water mark if appropriate */
-                for (offset = ss->ssl3.hs.recvdHighWater;
-                     offset < ss->ssl3.hs.msg_len; offset++) {
-                    /* Note that this loop is not efficient, since it counts
-                     * bit by bit. If we have a lot of out-of-order packets,
-                     * we should optimize this */
-                    if (ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] &
-                        OFFSET_MASK(offset)) {
-                        ss->ssl3.hs.recvdHighWater++;
-                    } else {
-                        break;
-                    }
-                }
-
-                /* If we have all the bytes, then we are good to go */
-                if (ss->ssl3.hs.recvdHighWater == ss->ssl3.hs.msg_len) {
-                    ss->ssl3.hs.recvdHighWater = -1;
-
-                    rv = ssl3_HandleHandshakeMessage(ss,
-                                                     ss->ssl3.hs.msg_body.buf,
-                                                     ss->ssl3.hs.msg_len);
-                    if (rv == SECFailure)
-                        break; /* Skip rest of record */
-
-                    /* At this point we are advancing our state machine, so
-                     * we can free our last flight of messages */
-                    dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
-                    dtls_CancelTimer(ss);
-
-                    /* If there have been no retries this time, reset the
-                     * timer value to the default per Section 4.2.4.1 */
-                    if (ss->ssl3.hs.rtRetries == 0) {
-                        ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
-                    }
-                }
-            }
-        }
-
-        buf.buf += fragment_length;
-        buf.len -= fragment_length;
-    }
-
-    origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */
-
-    /* XXX OK for now. In future handle rv == SECWouldBlock safely in order
-     * to deal with asynchronous certificate verification */
-    return rv;
-}
-
-/* Enqueue a message (either handshake or CCS)
- *
- * Called from:
- *              dtls_StageHandshakeMessage()
- *              ssl3_SendChangeCipherSpecs()
- */
-SECStatus
-dtls_QueueMessage(sslSocket *ss, SSL3ContentType type,
-                  const SSL3Opaque *pIn, PRInt32 nIn)
-{
-    SECStatus rv = SECSuccess;
-    DTLSQueuedMessage *msg = NULL;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    msg = dtls_AllocQueuedMessage(ss->ssl3.cwSpec->epoch, type, pIn, nIn);
-
-    if (!msg) {
-        PORT_SetError(SEC_ERROR_NO_MEMORY);
-        rv = SECFailure;
-    } else {
-        PR_APPEND_LINK(&msg->link, &ss->ssl3.hs.lastMessageFlight);
-    }
-
-    return rv;
-}
-
-/* Add DTLS handshake message to the pending queue
- * Empty the sendBuf buffer.
- * This function returns SECSuccess or SECFailure, never SECWouldBlock.
- * Always set sendBuf.len to 0, even when returning SECFailure.
- *
- * Called from:
- *              ssl3_AppendHandshakeHeader()
- *              dtls_FlushHandshake()
- */
-SECStatus
-dtls_StageHandshakeMessage(sslSocket *ss)
-{
-    SECStatus rv = SECSuccess;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    /* This function is sometimes called when no data is actually to
-     * be staged, so just return SECSuccess. */
-    if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len)
-        return rv;
-
-    rv = dtls_QueueMessage(ss, content_handshake,
-                           ss->sec.ci.sendBuf.buf, ss->sec.ci.sendBuf.len);
-
-    /* Whether we succeeded or failed, toss the old handshake data. */
-    ss->sec.ci.sendBuf.len = 0;
-    return rv;
-}
-
-/* Enqueue the handshake message in sendBuf (if any) and then
- * transmit the resulting flight of handshake messages.
- *
- * Called from:
- *              ssl3_FlushHandshake()
- */
-SECStatus
-dtls_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
-{
-    SECStatus rv = SECSuccess;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    rv = dtls_StageHandshakeMessage(ss);
-    if (rv != SECSuccess)
-        return rv;
-
-    if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {
-        rv = dtls_TransmitMessageFlight(ss);
-        if (rv != SECSuccess)
-            return rv;
-
-        if (!(flags & ssl_SEND_FLAG_NO_RETRANSMIT)) {
-            ss->ssl3.hs.rtRetries = 0;
-            rv = dtls_StartTimer(ss, dtls_RetransmitTimerExpiredCb);
-        }
-    }
-
-    return rv;
-}
-
-/* The callback for when the retransmit timer expires
- *
- * Called from:
- *              dtls_CheckTimer()
- *              dtls_HandleHandshake()
- */
-static void
-dtls_RetransmitTimerExpiredCb(sslSocket *ss)
-{
-    SECStatus rv = SECFailure;
-
-    ss->ssl3.hs.rtRetries++;
-
-    if (!(ss->ssl3.hs.rtRetries % 3)) {
-        /* If one of the messages was potentially greater than > MTU,
-         * then downgrade. Do this every time we have retransmitted a
-         * message twice, per RFC 6347 Sec. 4.1.1 */
-        dtls_SetMTU(ss, ss->ssl3.hs.maxMessageSent - 1);
-    }
-
-    rv = dtls_TransmitMessageFlight(ss);
-    if (rv == SECSuccess) {
-
-        /* Re-arm the timer */
-        rv = dtls_RestartTimer(ss, PR_TRUE, dtls_RetransmitTimerExpiredCb);
-    }
-
-    if (rv == SECFailure) {
-        /* XXX OK for now. In future maybe signal the stack that we couldn't
-         * transmit. For now, let the read handle any real network errors */
-    }
-}
-
-/* Transmit a flight of handshake messages, stuffing them
- * into as few records as seems reasonable
- *
- * Called from:
- *             dtls_FlushHandshake()
- *             dtls_RetransmitTimerExpiredCb()
- */
-static SECStatus
-dtls_TransmitMessageFlight(sslSocket *ss)
-{
-    SECStatus rv = SECSuccess;
-    PRCList *msg_p;
-    PRUint16 room_left = ss->ssl3.mtu;
-    PRInt32 sent;
-
-    ssl_GetXmitBufLock(ss);
-    ssl_GetSpecReadLock(ss);
-
-    /* DTLS does not buffer its handshake messages in
-     * ss->pendingBuf, but rather in the lastMessageFlight
-     * structure. This is just a sanity check that
-     * some programming error hasn't inadvertantly
-     * stuffed something in ss->pendingBuf
-     */
-    PORT_Assert(!ss->pendingBuf.len);
-    for (msg_p = PR_LIST_HEAD(&ss->ssl3.hs.lastMessageFlight);
-         msg_p != &ss->ssl3.hs.lastMessageFlight;
-         msg_p = PR_NEXT_LINK(msg_p)) {
-        DTLSQueuedMessage *msg = (DTLSQueuedMessage *)msg_p;
-
-        /* The logic here is:
-         *
-         * 1. If this is a message that will not fit into the remaining
-         *    space, then flush.
-         * 2. If the message will now fit into the remaining space,
-         *    encrypt, buffer, and loop.
-         * 3. If the message will not fit, then fragment.
-         *
-         * At the end of the function, flush.
-         */
-        if ((msg->len + SSL3_BUFFER_FUDGE) > room_left) {
-            /* The message will not fit into the remaining space, so flush */
-            rv = dtls_SendSavedWriteData(ss);
-            if (rv != SECSuccess)
-                break;
-
-            room_left = ss->ssl3.mtu;
-        }
-
-        if ((msg->len + SSL3_BUFFER_FUDGE) <= room_left) {
-            /* The message will fit, so encrypt and then continue with the
-             * next packet */
-            sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
-                                   msg->data, msg->len,
-                                   ssl_SEND_FLAG_FORCE_INTO_BUFFER |
-                                       ssl_SEND_FLAG_USE_EPOCH);
-            if (sent != msg->len) {
-                rv = SECFailure;
-                if (sent != -1) {
-                    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-                }
-                break;
-            }
-
-            room_left = ss->ssl3.mtu - ss->pendingBuf.len;
-        } else {
-            /* The message will not fit, so fragment.
-             *
-             * XXX OK for now. Arrange to coalesce the last fragment
-             * of this message with the next message if possible.
-             * That would be more efficient.
-             */
-            PRUint32 fragment_offset = 0;
-            unsigned char fragment[DTLS_MAX_MTU]; /* >= than largest
-                                                   * plausible MTU */
-
-            /* Assert that we have already flushed */
-            PORT_Assert(room_left == ss->ssl3.mtu);
-
-            /* Case 3: We now need to fragment this message
-             * DTLS only supports fragmenting handshaking messages */
-            PORT_Assert(msg->type == content_handshake);
-
-            /* The headers consume 12 bytes so the smalles possible
-             *  message (i.e., an empty one) is 12 bytes
-             */
-            PORT_Assert(msg->len >= 12);
-
-            while ((fragment_offset + 12) < msg->len) {
-                PRUint32 fragment_len;
-                const unsigned char *content = msg->data + 12;
-                PRUint32 content_len = msg->len - 12;
-
-                /* The reason we use 8 here is that that's the length of
-                 * the new DTLS data that we add to the header */
-                fragment_len = PR_MIN((PRUint32)room_left - (SSL3_BUFFER_FUDGE + 8),
-                                      content_len - fragment_offset);
-                PORT_Assert(fragment_len < DTLS_MAX_MTU - 12);
-                /* Make totally sure that we are within the buffer.
-                 * Note that the only way that fragment len could get
-                 * adjusted here is if
-                 *
-                 * (a) we are in release mode so the PORT_Assert is compiled out
-                 * (b) either the MTU table is inconsistent with DTLS_MAX_MTU
-                 * or ss->ssl3.mtu has become corrupt.
-                 */
-                fragment_len = PR_MIN(fragment_len, DTLS_MAX_MTU - 12);
-
-                /* Construct an appropriate-sized fragment */
-                /* Type, length, sequence */
-                PORT_Memcpy(fragment, msg->data, 6);
-
-                /* Offset */
-                fragment[6] = (fragment_offset >> 16) & 0xff;
-                fragment[7] = (fragment_offset >> 8) & 0xff;
-                fragment[8] = (fragment_offset)&0xff;
-
-                /* Fragment length */
-                fragment[9] = (fragment_len >> 16) & 0xff;
-                fragment[10] = (fragment_len >> 8) & 0xff;
-                fragment[11] = (fragment_len)&0xff;
-
-                PORT_Memcpy(fragment + 12, content + fragment_offset,
-                            fragment_len);
-
-                /*
-                 *  Send the record. We do this in two stages
-                 * 1. Encrypt
-                 */
-                sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
-                                       fragment, fragment_len + 12,
-                                       ssl_SEND_FLAG_FORCE_INTO_BUFFER |
-                                           ssl_SEND_FLAG_USE_EPOCH);
-                if (sent != (fragment_len + 12)) {
-                    rv = SECFailure;
-                    if (sent != -1) {
-                        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-                    }
-                    break;
-                }
-
-                /* 2. Flush */
-                rv = dtls_SendSavedWriteData(ss);
-                if (rv != SECSuccess)
-                    break;
-
-                fragment_offset += fragment_len;
-            }
-        }
-    }
-
-    /* Finally, we need to flush */
-    if (rv == SECSuccess)
-        rv = dtls_SendSavedWriteData(ss);
-
-    /* Give up the locks */
-    ssl_ReleaseSpecReadLock(ss);
-    ssl_ReleaseXmitBufLock(ss);
-
-    return rv;
-}
-
-/* Flush the data in the pendingBuf and update the max message sent
- * so we can adjust the MTU estimate if we need to.
- * Wrapper for ssl_SendSavedWriteData.
- *
- * Called from dtls_TransmitMessageFlight()
- */
-static SECStatus
-dtls_SendSavedWriteData(sslSocket *ss)
-{
-    PRInt32 sent;
-
-    sent = ssl_SendSavedWriteData(ss);
-    if (sent < 0)
-        return SECFailure;
-
-    /* We should always have complete writes b/c datagram sockets
-     * don't really block */
-    if (ss->pendingBuf.len > 0) {
-        ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
-        return SECFailure;
-    }
-
-    /* Update the largest message sent so we can adjust the MTU
-     * estimate if necessary */
-    if (sent > ss->ssl3.hs.maxMessageSent)
-        ss->ssl3.hs.maxMessageSent = sent;
-
-    return SECSuccess;
-}
-
-/* Compress, MAC, encrypt a DTLS record. Allows specification of
- * the epoch using epoch value. If use_epoch is PR_TRUE then
- * we use the provided epoch. If use_epoch is PR_FALSE then
- * whatever the current value is in effect is used.
- *
- * Called from ssl3_SendRecord()
- */
-SECStatus
-dtls_CompressMACEncryptRecord(sslSocket *ss,
-                              DTLSEpoch epoch,
-                              PRBool use_epoch,
-                              SSL3ContentType type,
-                              const SSL3Opaque *pIn,
-                              PRUint32 contentLen,
-                              sslBuffer *wrBuf)
-{
-    SECStatus rv = SECFailure;
-    ssl3CipherSpec *cwSpec;
-
-    ssl_GetSpecReadLock(ss); /********************************/
-
-    /* The reason for this switch-hitting code is that we might have
-     * a flight of records spanning an epoch boundary, e.g.,
-     *
-     * ClientKeyExchange (epoch = 0)
-     * ChangeCipherSpec (epoch = 0)
-     * Finished (epoch = 1)
-     *
-     * Thus, each record needs a different cipher spec. The information
-     * about which epoch to use is carried with the record.
-     */
-    if (use_epoch) {
-        if (ss->ssl3.cwSpec->epoch == epoch)
-            cwSpec = ss->ssl3.cwSpec;
-        else if (ss->ssl3.pwSpec->epoch == epoch)
-            cwSpec = ss->ssl3.pwSpec;
-        else
-            cwSpec = NULL;
-    } else {
-        cwSpec = ss->ssl3.cwSpec;
-    }
-
-    if (cwSpec) {
-        if (ss->ssl3.cwSpec->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-            rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer, PR_TRUE,
-                                               PR_FALSE, type, pIn, contentLen,
-                                               wrBuf);
-        } else {
-            rv = tls13_ProtectRecord(ss, type, pIn, contentLen, wrBuf);
-        }
-    } else {
-        PR_NOT_REACHED("Couldn't find a cipher spec matching epoch");
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-    }
-    ssl_ReleaseSpecReadLock(ss); /************************************/
-
-    return rv;
-}
-
-/* Start a timer
- *
- * Called from:
- *             dtls_HandleHandshake()
- *             dtls_FlushHAndshake()
- *             dtls_RestartTimer()
- */
-SECStatus
-dtls_StartTimer(sslSocket *ss, DTLSTimerCb cb)
-{
-    PORT_Assert(ss->ssl3.hs.rtTimerCb == NULL);
-
-    ss->ssl3.hs.rtTimerStarted = PR_IntervalNow();
-    ss->ssl3.hs.rtTimerCb = cb;
-
-    return SECSuccess;
-}
-
-/* Restart a timer with optional backoff
- *
- * Called from dtls_RetransmitTimerExpiredCb()
- */
-SECStatus
-dtls_RestartTimer(sslSocket *ss, PRBool backoff, DTLSTimerCb cb)
-{
-    if (backoff) {
-        ss->ssl3.hs.rtTimeoutMs *= 2;
-        if (ss->ssl3.hs.rtTimeoutMs > MAX_DTLS_TIMEOUT_MS)
-            ss->ssl3.hs.rtTimeoutMs = MAX_DTLS_TIMEOUT_MS;
-    }
-
-    return dtls_StartTimer(ss, cb);
-}
-
-/* Cancel a pending timer
- *
- * Called from:
- *              dtls_HandleHandshake()
- *              dtls_CheckTimer()
- */
-void
-dtls_CancelTimer(sslSocket *ss)
-{
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-
-    ss->ssl3.hs.rtTimerCb = NULL;
-}
-
-/* Check the pending timer and fire the callback if it expired
- *
- * Called from ssl3_GatherCompleteHandshake()
- */
-void
-dtls_CheckTimer(sslSocket *ss)
-{
-    if (!ss->ssl3.hs.rtTimerCb)
-        return;
-
-    if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
-        PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs)) {
-        /* Timer has expired */
-        DTLSTimerCb cb = ss->ssl3.hs.rtTimerCb;
-
-        /* Cancel the timer so that we can call the CB safely */
-        dtls_CancelTimer(ss);
-
-        /* Now call the CB */
-        cb(ss);
-    }
-}
-
-/* The callback to fire when the holddown timer for the Finished
- * message expires and we can delete it
- *
- * Called from dtls_CheckTimer()
- */
-void
-dtls_FinishedTimerCb(sslSocket *ss)
-{
-    ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE);
-}
-
-/* Cancel the Finished hold-down timer and destroy the
- * pending cipher spec. Note that this means that
- * successive rehandshakes will fail if the Finished is
- * lost.
- *
- * XXX OK for now. Figure out how to handle the combination
- * of Finished lost and rehandshake
- */
-void
-dtls_RehandshakeCleanup(sslSocket *ss)
-{
-    dtls_CancelTimer(ss);
-    ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE);
-    ss->ssl3.hs.sendMessageSeq = 0;
-    ss->ssl3.hs.recvMessageSeq = 0;
-}
-
-/* Set the MTU to the next step less than or equal to the
- * advertised value. Also used to downgrade the MTU by
- * doing dtls_SetMTU(ss, biggest packet set).
- *
- * Passing 0 means set this to the largest MTU known
- * (effectively resetting the PMTU backoff value).
- *
- * Called by:
- *            ssl3_InitState()
- *            dtls_RetransmitTimerExpiredCb()
- */
-void
-dtls_SetMTU(sslSocket *ss, PRUint16 advertised)
-{
-    int i;
-
-    if (advertised == 0) {
-        ss->ssl3.mtu = COMMON_MTU_VALUES[0];
-        SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
-        return;
-    }
-
-    for (i = 0; i < PR_ARRAY_SIZE(COMMON_MTU_VALUES); i++) {
-        if (COMMON_MTU_VALUES[i] <= advertised) {
-            ss->ssl3.mtu = COMMON_MTU_VALUES[i];
-            SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
-            return;
-        }
-    }
-
-    /* Fallback */
-    ss->ssl3.mtu = COMMON_MTU_VALUES[PR_ARRAY_SIZE(COMMON_MTU_VALUES) - 1];
-    SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
-}
-
-/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a
- * DTLS hello_verify_request
- * Caller must hold Handshake and RecvBuf locks.
- */
-SECStatus
-dtls_HandleHelloVerifyRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    int errCode = SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST;
-    SECStatus rv;
-    PRInt32 temp;
-    SECItem cookie = { siBuffer, NULL, 0 };
-    SSL3AlertDescription desc = illegal_parameter;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: handle hello_verify_request handshake",
-                SSL_GETPID(), ss->fd));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if (ss->ssl3.hs.ws != wait_server_hello) {
-        errCode = SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST;
-        desc = unexpected_message;
-        goto alert_loser;
-    }
-
-    /* The version */
-    temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
-    if (temp < 0) {
-        goto loser; /* alert has been sent */
-    }
-
-    if (temp != SSL_LIBRARY_VERSION_DTLS_1_0_WIRE &&
-        temp != SSL_LIBRARY_VERSION_DTLS_1_2_WIRE) {
-        goto alert_loser;
-    }
-
-    /* The cookie */
-    rv = ssl3_ConsumeHandshakeVariable(ss, &cookie, 1, &b, &length);
-    if (rv != SECSuccess) {
-        goto loser; /* alert has been sent */
-    }
-    if (cookie.len > DTLS_COOKIE_BYTES) {
-        desc = decode_error;
-        goto alert_loser; /* malformed. */
-    }
-
-    PORT_Memcpy(ss->ssl3.hs.cookie, cookie.data, cookie.len);
-    ss->ssl3.hs.cookieLen = cookie.len;
-
-    ssl_GetXmitBufLock(ss); /*******************************/
-
-    /* Now re-send the client hello */
-    rv = ssl3_SendClientHello(ss, PR_TRUE);
-
-    ssl_ReleaseXmitBufLock(ss); /*******************************/
-
-    if (rv == SECSuccess)
-        return rv;
-
-alert_loser:
-    (void)SSL3_SendAlert(ss, alert_fatal, desc);
-
-loser:
-    ssl_MapLowLevelError(errCode);
-    return SECFailure;
-}
-
-/* Initialize the DTLS anti-replay window
- *
- * Called from:
- *              ssl3_SetupPendingCipherSpec()
- *              ssl3_InitCipherSpec()
- */
-void
-dtls_InitRecvdRecords(DTLSRecvdRecords *records)
-{
-    PORT_Memset(records->data, 0, sizeof(records->data));
-    records->left = 0;
-    records->right = DTLS_RECVD_RECORDS_WINDOW - 1;
-}
-
-/*
- * Has this DTLS record been received? Return values are:
- * -1 -- out of range to the left
- *  0 -- not received yet
- *  1 -- replay
- *
- *  Called from: ssl3_HandleRecord()
- */
-int
-dtls_RecordGetRecvd(const DTLSRecvdRecords *records, PRUint64 seq)
-{
-    PRUint64 offset;
-
-    /* Out of range to the left */
-    if (seq < records->left) {
-        return -1;
-    }
-
-    /* Out of range to the right; since we advance the window on
-     * receipt, that means that this packet has not been received
-     * yet */
-    if (seq > records->right)
-        return 0;
-
-    offset = seq % DTLS_RECVD_RECORDS_WINDOW;
-
-    return !!(records->data[offset / 8] & (1 << (offset % 8)));
-}
-
-/* Update the DTLS anti-replay window
- *
- * Called from ssl3_HandleRecord()
- */
-void
-dtls_RecordSetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
-{
-    PRUint64 offset;
-
-    if (seq < records->left)
-        return;
-
-    if (seq > records->right) {
-        PRUint64 new_left;
-        PRUint64 new_right;
-        PRUint64 right;
-
-        /* Slide to the right; this is the tricky part
-         *
-         * 1. new_top is set to have room for seq, on the
-         *    next byte boundary by setting the right 8
-         *    bits of seq
-         * 2. new_left is set to compensate.
-         * 3. Zero all bits between top and new_top. Since
-         *    this is a ring, this zeroes everything as-yet
-         *    unseen. Because we always operate on byte
-         *    boundaries, we can zero one byte at a time
-         */
-        new_right = seq | 0x07;
-        new_left = (new_right - DTLS_RECVD_RECORDS_WINDOW) + 1;
-
-        for (right = records->right + 8; right <= new_right; right += 8) {
-            offset = right % DTLS_RECVD_RECORDS_WINDOW;
-            records->data[offset / 8] = 0;
-        }
-
-        records->right = new_right;
-        records->left = new_left;
-    }
-
-    offset = seq % DTLS_RECVD_RECORDS_WINDOW;
-
-    records->data[offset / 8] |= (1 << (offset % 8));
-}
-
-SECStatus
-DTLS_GetHandshakeTimeout(PRFileDesc *socket, PRIntervalTime *timeout)
-{
-    sslSocket *ss = NULL;
-    PRIntervalTime elapsed;
-    PRIntervalTime desired;
-
-    ss = ssl_FindSocket(socket);
-
-    if (!ss)
-        return SECFailure;
-
-    if (!IS_DTLS(ss))
-        return SECFailure;
-
-    if (!ss->ssl3.hs.rtTimerCb)
-        return SECFailure;
-
-    elapsed = PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted;
-    desired = PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs);
-    if (elapsed > desired) {
-        /* Timer expired */
-        *timeout = PR_INTERVAL_NO_WAIT;
-    } else {
-        *timeout = desired - elapsed;
-    }
-
-    return SECSuccess;
-}
-
-/*
- * DTLS relevance checks:
- * Note that this code currently ignores all out-of-epoch packets,
- * which means we lose some in the case of rehandshake +
- * loss/reordering. Since DTLS is explicitly unreliable, this
- * seems like a good tradeoff for implementation effort and is
- * consistent with the guidance of RFC 6347 Sections 4.1 and 4.2.4.1.
- *
- * If the packet is not relevant, this function returns PR_FALSE.
- * If the packet is relevant, this function returns PR_TRUE
- * and sets |*seqNum| to the packet sequence number.
- */
-PRBool
-dtls_IsRelevant(sslSocket *ss, const ssl3CipherSpec *crSpec,
-                const SSL3Ciphertext *cText, PRUint64 *seqNum)
-{
-    DTLSEpoch epoch = cText->seq_num.high >> 16;
-    PRUint64 dtls_seq_num;
-
-    if (crSpec->epoch != epoch) {
-        SSL_DBG(("%d: SSL3[%d]: dtls_IsRelevant, received packet "
-                 "from irrelevant epoch %d",
-                 SSL_GETPID(), ss->fd, epoch));
-        return PR_FALSE;
-    }
-
-    dtls_seq_num = (((PRUint64)(cText->seq_num.high & 0xffff)) << 32) |
-                   ((PRUint64)cText->seq_num.low);
-
-    if (dtls_RecordGetRecvd(&crSpec->recvdRecords, dtls_seq_num) != 0) {
-        SSL_DBG(("%d: SSL3[%d]: dtls_IsRelevant, rejecting "
-                 "potentially replayed packet",
-                 SSL_GETPID(), ss->fd));
-        return PR_FALSE;
-    }
-
-    *seqNum = dtls_seq_num;
-    return PR_TRUE;
-}
diff --git a/net/third_party/nss/ssl/manifest.mn b/net/third_party/nss/ssl/manifest.mn
deleted file mode 100644
index 1366d15e..0000000
--- a/net/third_party/nss/ssl/manifest.mn
+++ /dev/null
@@ -1,55 +0,0 @@
-# 
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-CORE_DEPTH = ../..
-
-# DEFINES = -DTRACE
-
-EXPORTS = \
-	ssl.h \
-	sslt.h \
-	sslerr.h \
-	sslproto.h \
-	preenc.h \
-	$(NULL)
-
-MODULE = nss
-MAPFILE = $(OBJDIR)/ssl.def
-
-CSRCS = \
-	derive.c \
-	dtlscon.c \
-	prelib.c \
-	ssl3con.c \
-	ssl3gthr.c \
-	sslauth.c \
-	sslcon.c \
-	ssldef.c \
-	sslenum.c \
-	sslerr.c \
-	sslerrstrs.c \
-	sslinit.c \
-	ssl3ext.c \
-	sslgathr.c \
-	sslmutex.c \
-	sslnonce.c \
-	sslreveal.c \
-	sslsecur.c \
-	sslsnce.c \
-	sslsock.c \
-	ssltrace.c \
-	sslver.c \
-	authcert.c \
-	cmpcert.c \
-	sslinfo.c \
-	ssl3ecc.c \
-        tls13con.c \
-        tls13hkdf.c \
-	$(NULL)
-
-LIBRARY_NAME = ssl
-LIBRARY_VERSION = 3
-
-# This part of the code, including all sub-dirs, can be optimized for size
-export ALLOW_OPT_CODE_SIZE = 1
diff --git a/net/third_party/nss/ssl/notes.txt b/net/third_party/nss/ssl/notes.txt
deleted file mode 100644
index cf514ad2..0000000
--- a/net/third_party/nss/ssl/notes.txt
+++ /dev/null
@@ -1,134 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-SSL's Buffers: enumerated and explained.
-
----------------------------------------------------------------------------
-incoming:
-
-gs = ss->gather
-hs = ss->ssl3->hs
-
-gs->inbuf   SSL3 only: incoming (encrypted) ssl records are placed here,
-        and then decrypted (or copied) to gs->buf.
-
-gs->buf     SSL2: incoming SSL records are put here, and then decrypted
-        in place.
-        SSL3: ssl3_HandleHandshake puts decrypted ssl records here.
-
-hs.msg_body (SSL3 only) When an incoming handshake message spans more
-        than one ssl record, the first part(s) of it are accumulated
-        here until it all arrives.
-
-hs.msgState (SSL3 only) an alternative set of pointers/lengths for gs->buf.
-        Used only when a handleHandshake function returns SECWouldBlock.
-        ssl3_HandleHandshake remembers how far it previously got by
-        using these pointers instead of gs->buf when it is called
-        after a previous SECWouldBlock return.
-
----------------------------------------------------------------------------
-outgoing:
-
-sec = ss->sec
-ci  = ss->sec->ci   /* connect info */
-
-ci->sendBuf Outgoing handshake messages are appended to this buffer.
-        This buffer will then be sent as a single SSL record.
-
-sec->writeBuf   outgoing ssl records are constructed here and encrypted in
-        place before being written or copied to pendingBuf.
-
-ss->pendingBuf  contains outgoing ciphertext that was saved after a write
-        attempt to the socket failed, e.g. EWouldBlock.
-        Generally empty with blocking sockets (should be no incomplete
-        writes).
-
-ss->saveBuf Used only by socks code.  Intended to be used to buffer
-        outgoing data until a socks handshake completes.  However,
-        this buffer is always empty.  There is no code to put
-        anything into it.
-
----------------------------------------------------------------------------
-
-SECWouldBlock means that the function cannot make progress because it is
-waiting for some event OTHER THAN socket I/O completion (e.g. waiting for
-user dialog to finish).  It is not the same as EWOULDBLOCK.
-
----------------------------------------------------------------------------
-
-Rank (order) of locks
-
-recvLock ->\ firstHandshake -> recvbuf -> ssl3Handshake -> xmitbuf -> "spec"
-sendLock ->/
-
-crypto and hash Data that must be protected while turning plaintext into
-ciphertext:
-
-SSL2:   (in ssl2_Send*)
-    sec->hash*
-    sec->hashcx     (ptr and data)
-    sec->enc
-    sec->writecx*   (ptr and content)
-    sec->sendSecret*(ptr and content)
-    sec->sendSequence       locked by xmitBufLock
-    sec->blockSize
-    sec->writeBuf*  (ptr & content) locked by xmitBufLock
-    "in"                locked by xmitBufLock
-
-SSl3:   (in ssl3_SendPlainText)
-    ss->ssl3            (the pointer)
-    ss->ssl3->current_write*    (the pointer and the data in the spec
-                     and any data referenced by the spec.
-
-    ss->sec->isServer
-    ss->sec->writebuf* (ptr & content) locked by xmitBufLock
-    "buf"                  locked by xmitBufLock
-
-crypto and hash data that must be protected while turning ciphertext into
-plaintext:
-
-SSL2:   (in ssl2_GatherData)
-    gs->*               (locked by recvBufLock )
-    sec->dec
-    sec->readcx
-    sec->hash*      (ptr and data)
-    sec->hashcx         (ptr and data)
-
-SSL3:   (in ssl3_HandleRecord )
-    ssl3->current_read* (the pointer and all data refernced)
-    ss->sec->isServer
-
-
-Data that must be protected while being used by a "writer":
-
-ss->pendingBuf.*
-ss->saveBuf.*       (which is dead)
-
-in ssl3_sendPlainText
-
-ss->ssl3->current_write-> (spec)
-ss->sec->writeBuf.*
-ss->sec->isServer
-
-in SendBlock
-
-ss->sec->hash->length
-ss->sec->blockSize
-ss->sec->writeBuf.*
-ss->sec->sendSecret
-ss->sec->sendSequence
-ss->sec->writecx    *
-ss->pendingBuf
-
---------------------------------------------------------------------------
-
-Data variables (not const) protected by the "sslGlobalDataLock".
-Note, this really should be a reader/writer lock.
-
-allowedByPolicy     sslcon.c
-maybeAllowedByPolicy    sslcon.c
-chosenPreference    sslcon.c
-policyWasSet        sslcon.c
-
-cipherSuites[]      ssl3con.c
diff --git a/net/third_party/nss/ssl/os2_err.c b/net/third_party/nss/ssl/os2_err.c
deleted file mode 100644
index 6e3d423..0000000
--- a/net/third_party/nss/ssl/os2_err.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/*
- * This file essentially replicates NSPR's source for the functions that
- * map system-specific error codes to NSPR error codes.  We would use
- * NSPR's functions, instead of duplicating them, but they're private.
- * As long as SSL's server session cache code must do platform native I/O
- * to accomplish its job, and NSPR's error mapping functions remain private,
- * this code will continue to need to be replicated.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "prerror.h"
-#include "prlog.h"
-#include <errno.h>
-
-/*
- * Based on win32err.c
- * OS2TODO Stub everything for now to build. HCT
- */
-
-/* forward declaration. */
-void nss_MD_os2_map_default_error(PRInt32 err);
-
-void
-nss_MD_os2_map_opendir_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_closedir_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_readdir_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_delete_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-/* The error code for stat() is in errno. */
-void
-nss_MD_os2_map_stat_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_fstat_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_rename_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-/* The error code for access() is in errno. */
-void
-nss_MD_os2_map_access_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_mkdir_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_rmdir_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_read_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_transmitfile_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_write_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_lseek_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_fsync_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-/*
- * For both CloseHandle() and closesocket().
- */
-void
-nss_MD_os2_map_close_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_socket_error(PRInt32 err)
-{
-    //  PR_ASSERT(err != WSANOTINITIALISED);
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_recv_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_recvfrom_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_send_error(PRInt32 err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        //     case WSAEMSGSIZE:  prError = PR_INVALID_ARGUMENT_ERROR; break;
-        default:
-            nss_MD_os2_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_os2_map_sendto_error(PRInt32 err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        //    case WSAEMSGSIZE:     prError = PR_INVALID_ARGUMENT_ERROR; break;
-        default:
-            nss_MD_os2_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_os2_map_accept_error(PRInt32 err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        //    case WSAEOPNOTSUPP: prError = PR_NOT_TCP_SOCKET_ERROR; break;
-        //    case WSAEINVAL:   prError = PR_INVALID_STATE_ERROR; break;
-        default:
-            nss_MD_os2_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_os2_map_acceptex_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_connect_error(PRInt32 err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        //    case WSAEWOULDBLOCK: prError = PR_IN_PROGRESS_ERROR; break;
-        //    case WSAEINVAL:   prError = PR_ALREADY_INITIATED_ERROR; break;
-        //    case WSAETIMEDOUT:    prError = PR_IO_TIMEOUT_ERROR; break;
-        default:
-            nss_MD_os2_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_os2_map_bind_error(PRInt32 err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        //  case WSAEINVAL:     prError = PR_SOCKET_ADDRESS_IS_BOUND_ERROR; break;
-        default:
-            nss_MD_os2_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_os2_map_listen_error(PRInt32 err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        //    case WSAEOPNOTSUPP: prError = PR_NOT_TCP_SOCKET_ERROR; break;
-        //    case WSAEINVAL:   prError = PR_INVALID_STATE_ERROR; break;
-        default:
-            nss_MD_os2_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_os2_map_shutdown_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_getsockname_error(PRInt32 err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        //    case WSAEINVAL:   prError = PR_INVALID_STATE_ERROR; break;
-        default:
-            nss_MD_os2_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_os2_map_getpeername_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_getsockopt_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_setsockopt_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_open_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_gethostname_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-/* Win32 select() only works on sockets.  So in this
-** context, WSAENOTSOCK is equivalent to EBADF on Unix.
-*/
-void
-nss_MD_os2_map_select_error(PRInt32 err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        //    case WSAENOTSOCK: prError = PR_BAD_DESCRIPTOR_ERROR; break;
-        default:
-            nss_MD_os2_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_os2_map_lockf_error(PRInt32 err)
-{
-    nss_MD_os2_map_default_error(err);
-}
-
-void
-nss_MD_os2_map_default_error(PRInt32 err)
-{
-    PRErrorCode prError;
-
-    switch (err) {
-//    case ENOENT:      prError = PR_FILE_NOT_FOUND_ERROR; break;
-//    case ERROR_ACCESS_DENIED:     prError = PR_NO_ACCESS_RIGHTS_ERROR; break;
-//    case ERROR_ALREADY_EXISTS:    prError = PR_FILE_EXISTS_ERROR; break;
-//    case ERROR_DISK_CORRUPT:  prError = PR_IO_ERROR; break;
-//    case ERROR_DISK_FULL:     prError = PR_NO_DEVICE_SPACE_ERROR; break;
-//    case ERROR_DISK_OPERATION_FAILED: prError = PR_IO_ERROR; break;
-//    case ERROR_DRIVE_LOCKED:  prError = PR_FILE_IS_LOCKED_ERROR; break;
-//    case ERROR_FILENAME_EXCED_RANGE: prError = PR_NAME_TOO_LONG_ERROR; break;
-//    case ERROR_FILE_CORRUPT:  prError = PR_IO_ERROR; break;
-//    case ERROR_FILE_EXISTS:   prError = PR_FILE_EXISTS_ERROR; break;
-//    case ERROR_FILE_INVALID:  prError = PR_BAD_DESCRIPTOR_ERROR; break;
-#if ERROR_FILE_NOT_FOUND != ENOENT
-//    case ERROR_FILE_NOT_FOUND:    prError = PR_FILE_NOT_FOUND_ERROR; break;
-#endif
-        default:
-            prError = PR_UNKNOWN_ERROR;
-            break;
-    }
-    PR_SetError(prError, err);
-}
diff --git a/net/third_party/nss/ssl/os2_err.h b/net/third_party/nss/ssl/os2_err.h
deleted file mode 100644
index 15e4741..0000000
--- a/net/third_party/nss/ssl/os2_err.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * This file essentially replicates NSPR's source for the functions that
- * map system-specific error codes to NSPR error codes.  We would use
- * NSPR's functions, instead of duplicating them, but they're private.
- * As long as SSL's server session cache code must do platform native I/O
- * to accomplish its job, and NSPR's error mapping functions remain private,
- * This code will continue to need to be replicated.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*  NSPR doesn't make these functions public, so we have to duplicate
-**  them in NSS.
-*/
-
-//HCT  Based on Win32err.h
-extern void nss_MD_os2_map_accept_error(PRInt32 err);
-extern void nss_MD_os2_map_acceptex_error(PRInt32 err);
-extern void nss_MD_os2_map_access_error(PRInt32 err);
-extern void nss_MD_os2_map_bind_error(PRInt32 err);
-extern void nss_MD_os2_map_close_error(PRInt32 err);
-extern void nss_MD_os2_map_closedir_error(PRInt32 err);
-extern void nss_MD_os2_map_connect_error(PRInt32 err);
-extern void nss_MD_os2_map_default_error(PRInt32 err);
-extern void nss_MD_os2_map_delete_error(PRInt32 err);
-extern void nss_MD_os2_map_fstat_error(PRInt32 err);
-extern void nss_MD_os2_map_fsync_error(PRInt32 err);
-extern void nss_MD_os2_map_gethostname_error(PRInt32 err);
-extern void nss_MD_os2_map_getpeername_error(PRInt32 err);
-extern void nss_MD_os2_map_getsockname_error(PRInt32 err);
-extern void nss_MD_os2_map_getsockopt_error(PRInt32 err);
-extern void nss_MD_os2_map_listen_error(PRInt32 err);
-extern void nss_MD_os2_map_lockf_error(PRInt32 err);
-extern void nss_MD_os2_map_lseek_error(PRInt32 err);
-extern void nss_MD_os2_map_mkdir_error(PRInt32 err);
-extern void nss_MD_os2_map_open_error(PRInt32 err);
-extern void nss_MD_os2_map_opendir_error(PRInt32 err);
-extern void nss_MD_os2_map_read_error(PRInt32 err);
-extern void nss_MD_os2_map_readdir_error(PRInt32 err);
-extern void nss_MD_os2_map_recv_error(PRInt32 err);
-extern void nss_MD_os2_map_recvfrom_error(PRInt32 err);
-extern void nss_MD_os2_map_rename_error(PRInt32 err);
-extern void nss_MD_os2_map_rmdir_error(PRInt32 err);
-extern void nss_MD_os2_map_select_error(PRInt32 err);
-extern void nss_MD_os2_map_send_error(PRInt32 err);
-extern void nss_MD_os2_map_sendto_error(PRInt32 err);
-extern void nss_MD_os2_map_setsockopt_error(PRInt32 err);
-extern void nss_MD_os2_map_shutdown_error(PRInt32 err);
-extern void nss_MD_os2_map_socket_error(PRInt32 err);
-extern void nss_MD_os2_map_stat_error(PRInt32 err);
-extern void nss_MD_os2_map_transmitfile_error(PRInt32 err);
-extern void nss_MD_os2_map_write_error(PRInt32 err);
diff --git a/net/third_party/nss/ssl/preenc.h b/net/third_party/nss/ssl/preenc.h
deleted file mode 100644
index bebff89e..0000000
--- a/net/third_party/nss/ssl/preenc.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
-
-/*
- * Fortezza support is removed.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Fortezza support is removed.
- * This file remains so that old programs will continue to compile,
- * But this functionality is no longer supported or implemented.
- */
-
-#include "seccomon.h"
-#include "prio.h"
-
-typedef struct PEHeaderStr PEHeader;
-
-#define PE_MIME_TYPE "application/pre-encrypted"
-
-typedef struct PEFortezzaHeaderStr PEFortezzaHeader;
-typedef struct PEFortezzaGeneratedHeaderStr PEFortezzaGeneratedHeader;
-typedef struct PEFixedKeyHeaderStr PEFixedKeyHeader;
-typedef struct PERSAKeyHeaderStr PERSAKeyHeader;
-
-struct PEFortezzaHeaderStr {
-    unsigned char key[12];
-    unsigned char iv[24];
-    unsigned char hash[20];
-    unsigned char serial[8];
-};
-
-struct PEFortezzaGeneratedHeaderStr {
-    unsigned char key[12];
-    unsigned char iv[24];
-    unsigned char hash[20];
-    unsigned char Ra[128];
-    unsigned char Y[128];
-};
-
-struct PEFixedKeyHeaderStr {
-    unsigned char pkcs11Mech[4];
-    unsigned char labelLen[2];
-    unsigned char keyIDLen[2];
-    unsigned char ivLen[2];
-    unsigned char keyLen[2];
-    unsigned char data[1];
-};
-
-struct PERSAKeyHeaderStr {
-    unsigned char pkcs11Mech[4];
-    unsigned char issuerLen[2];
-    unsigned char serialLen[2];
-    unsigned char ivLen[2];
-    unsigned char keyLen[2];
-    unsigned char data[1];
-};
-
-#define PEFIXED_Label(header) (header->data)
-#define PEFIXED_KeyID(header) (&header->data[GetInt2(header->labelLen)])
-#define PEFIXED_IV(header) (&header->data[GetInt2(header->labelLen) + \
-                                          GetInt2(header->keyIDLen)])
-#define PEFIXED_Key(header) (&header->data[GetInt2(header->labelLen) + \
-                                           GetInt2(header->keyIDLen) + \
-                                           GetInt2(header->keyLen)])
-#define PERSA_Issuer(header) (header->data)
-#define PERSA_Serial(header) (&header->data[GetInt2(header->issuerLen)])
-#define PERSA_IV(header) (&header->data[GetInt2(header->issuerLen) + \
-                                        GetInt2(header->serialLen)])
-#define PERSA_Key(header) (&header->data[GetInt2(header->issuerLen) + \
-                                         GetInt2(header->serialLen) + \
-                                         GetInt2(header->keyLen)])
-struct PEHeaderStr {
-    unsigned char magic[2];
-    unsigned char len[2];
-    unsigned char type[2];
-    unsigned char version[2];
-    union {
-        PEFortezzaHeader fortezza;
-        PEFortezzaGeneratedHeader g_fortezza;
-        PEFixedKeyHeader fixed;
-        PERSAKeyHeader rsa;
-    } u;
-};
-
-#define PE_CRYPT_INTRO_LEN 8
-#define PE_INTRO_LEN 4
-#define PE_BASE_HEADER_LEN 8
-
-#define PRE_BLOCK_SIZE 8
-
-#define GetInt2(c) ((c[0] << 8) | c[1])
-#define GetInt4(c) (((unsigned long)c[0] << 24) | ((unsigned long)c[1] << 16) | \
-                    ((unsigned long)c[2] << 8) | ((unsigned long)c[3]))
-#define PutInt2(c, i) ((c[1] = (i)&0xff), (c[0] = ((i) >> 8) & 0xff))
-#define PutInt4(c, i) ((c[0] = ((i) >> 24) & 0xff), (c[1] = ((i) >> 16) & 0xff), \
-                       (c[2] = ((i) >> 8) & 0xff), (c[3] = (i)&0xff))
-
-#define PRE_MAGIC 0xc0de
-#define PRE_VERSION 0x1010
-#define PRE_FORTEZZA_FILE 0x00ff
-#define PRE_FORTEZZA_STREAM 0x00f5
-#define PRE_FORTEZZA_GEN_STREAM 0x00f6
-#define PRE_FIXED_FILE 0x000f
-#define PRE_RSA_FILE 0x001f
-#define PRE_FIXED_STREAM 0x0005
-
-PEHeader *SSL_PreencryptedStreamToFile(PRFileDesc *fd, PEHeader *,
-                                       int *headerSize);
-
-PEHeader *SSL_PreencryptedFileToStream(PRFileDesc *fd, PEHeader *,
-                                       int *headerSize);
diff --git a/net/third_party/nss/ssl/prelib.c b/net/third_party/nss/ssl/prelib.c
deleted file mode 100644
index 4db9ffe..0000000
--- a/net/third_party/nss/ssl/prelib.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
-
-/*
- * Functions used by https servers to send (download) pre-encrypted files
- * over SSL connections that use Fortezza ciphersuites.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "cert.h"
-#include "ssl.h"
-#include "keyhi.h"
-#include "secitem.h"
-#include "sslimpl.h"
-#include "pkcs11t.h"
-#include "preenc.h"
-#include "pk11func.h"
-
-PEHeader *
-SSL_PreencryptedStreamToFile(PRFileDesc *fd, PEHeader *inHeader,
-                             int *headerSize)
-{
-    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
-    return NULL;
-}
-
-PEHeader *
-SSL_PreencryptedFileToStream(PRFileDesc *fd, PEHeader *header,
-                             int *headerSize)
-{
-    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
-    return NULL;
-}
diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h
deleted file mode 100644
index de5078b..0000000
--- a/net/third_party/nss/ssl/ssl.h
+++ /dev/null
@@ -1,1302 +0,0 @@
-/*
- * This file contains prototypes for the public SSL functions.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef __ssl_h_
-#define __ssl_h_
-
-#include "prtypes.h"
-#include "prerror.h"
-#include "prio.h"
-#include "seccomon.h"
-#include "cert.h"
-#include "keyt.h"
-
-#include "sslt.h" /* public ssl data types */
-
-#if defined(_WIN32) && !defined(IN_LIBSSL) && !defined(NSS_USE_STATIC_LIBS)
-#define SSL_IMPORT extern __declspec(dllimport)
-#else
-#define SSL_IMPORT extern
-#endif
-
-SEC_BEGIN_PROTOS
-
-/* constant table enumerating all implemented SSL 2 and 3 cipher suites. */
-SSL_IMPORT const PRUint16 SSL_ImplementedCiphers[];
-
-/* the same as the above, but is a function */
-SSL_IMPORT const PRUint16 *SSL_GetImplementedCiphers(void);
-
-/* number of entries in the above table. */
-SSL_IMPORT const PRUint16 SSL_NumImplementedCiphers;
-
-/* the same as the above, but is a function */
-SSL_IMPORT PRUint16 SSL_GetNumImplementedCiphers(void);
-
-/* Macro to tell which ciphers in table are SSL2 vs SSL3/TLS. */
-#define SSL_IS_SSL2_CIPHER(which) (((which)&0xfff0) == 0xff00)
-
-/*
-** Imports fd into SSL, returning a new socket.  Copies SSL configuration
-** from model.
-*/
-SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd);
-
-/*
-** Imports fd into DTLS, returning a new socket.  Copies DTLS configuration
-** from model.
-*/
-SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
-
-/*
-** Enable/disable an ssl mode
-**
-**  SSL_SECURITY:
-**    enable/disable use of SSL security protocol before connect
-**
-**  SSL_SOCKS:
-**    enable/disable use of socks before connect
-**    (No longer supported).
-**
-**  SSL_REQUEST_CERTIFICATE:
-**    require a certificate during secure connect
-*/
-/* options */
-#define SSL_SECURITY 1            /* (on by default) */
-#define SSL_SOCKS 2               /* (off by default) */
-#define SSL_REQUEST_CERTIFICATE 3 /* (off by default) */
-#define SSL_HANDSHAKE_AS_CLIENT 5 /* force accept to hs as client */
-                                  /* (off by default) */
-#define SSL_HANDSHAKE_AS_SERVER 6 /* force connect to hs as server */
-                                  /* (off by default) */
-
-/* OBSOLETE: SSL v2 is obsolete and may be removed soon. */
-#define SSL_ENABLE_SSL2 7 /* enable ssl v2 (off by default) */
-
-/* OBSOLETE: See "SSL Version Range API" below for the replacement and a
-** description of the non-obvious semantics of using SSL_ENABLE_SSL3.
-*/
-#define SSL_ENABLE_SSL3 8 /* enable ssl v3 (on by default) */
-
-#define SSL_NO_CACHE 9             /* don't use the session cache */
-                                   /* (off by default) */
-#define SSL_REQUIRE_CERTIFICATE 10 /* (SSL_REQUIRE_FIRST_HANDSHAKE */
-                                   /* by default) */
-#define SSL_ENABLE_FDX 11          /* permit simultaneous read/write */
-                                   /* (off by default) */
-
-/* OBSOLETE: SSL v2 compatible hellos are not accepted by some TLS servers
-** and cannot negotiate extensions. SSL v2 is obsolete. This option may be
-** removed soon.
-*/
-#define SSL_V2_COMPATIBLE_HELLO 12 /* send v3 client hello in v2 fmt */
-                                   /* (off by default) */
-
-/* OBSOLETE: See "SSL Version Range API" below for the replacement and a
-** description of the non-obvious semantics of using SSL_ENABLE_TLS.
-*/
-#define SSL_ENABLE_TLS 13 /* enable TLS (on by default) */
-
-#define SSL_ROLLBACK_DETECTION 14       /* for compatibility, default: on */
-#define SSL_NO_STEP_DOWN 15             /* Disable export cipher suites   */
-                                        /* if step-down keys are needed.  */
-                                        /* default: off, generate         */
-                                        /* step-down keys if needed.      */
-#define SSL_BYPASS_PKCS11 16            /* use PKCS#11 for pub key only   */
-#define SSL_NO_LOCKS 17                 /* Don't use locks for protection */
-#define SSL_ENABLE_SESSION_TICKETS 18   /* Enable TLS SessionTicket       */
-                                        /* extension (off by default)     */
-#define SSL_ENABLE_DEFLATE 19           /* Enable TLS compression with    */
-                                        /* DEFLATE (off by default)       */
-#define SSL_ENABLE_RENEGOTIATION 20     /* Values below (default: never)  */
-#define SSL_REQUIRE_SAFE_NEGOTIATION 21 /* Peer must send Signaling       */
-                                        /* Cipher Suite Value (SCSV) or   */
-                                        /* Renegotiation  Info (RI)       */
-                                        /* extension in ALL handshakes.   */
-                                        /* default: off                   */
-#define SSL_ENABLE_FALSE_START 22       /* Enable SSL false start (off by */
-                                        /* default, applies only to       */
-                                        /* clients). False start is a     */
-/* mode where an SSL client will start sending application data before
- * verifying the server's Finished message. This means that we could end up
- * sending data to an imposter. However, the data will be encrypted and
- * only the true server can derive the session key. Thus, so long as the
- * cipher isn't broken this is safe. The advantage of false start is that
- * it saves a round trip for client-speaks-first protocols when performing a
- * full handshake.
- *
- * In addition to enabling this option, the application must register a
- * callback using the SSL_SetCanFalseStartCallback function.
- */
-
-/* For SSL 3.0 and TLS 1.0, by default we prevent chosen plaintext attacks
- * on SSL CBC mode cipher suites (see RFC 4346 Section F.3) by splitting
- * non-empty application_data records into two records; the first record has
- * only the first byte of plaintext, and the second has the rest.
- *
- * This only prevents the attack in the sending direction; the connection may
- * still be vulnerable to such attacks if the peer does not implement a similar
- * countermeasure.
- *
- * This protection mechanism is on by default; the default can be overridden by
- * setting NSS_SSL_CBC_RANDOM_IV=0 in the environment prior to execution,
- * and/or by the application setting the option SSL_CBC_RANDOM_IV to PR_FALSE.
- *
- * The per-record IV in TLS 1.1 and later adds one block of overhead per
- * record, whereas this hack will add at least two blocks of overhead per
- * record, so TLS 1.1+ will always be more efficient.
- *
- * Other implementations (e.g. some versions of OpenSSL, in some
- * configurations) prevent the same attack by prepending an empty
- * application_data record to every application_data record they send; we do
- * not do that because some implementations cannot handle empty
- * application_data records. Also, we only split application_data records and
- * not other types of records, because some implementations will not accept
- * fragmented records of some other types (e.g. some versions of NSS do not
- * accept fragmented alerts).
- */
-#define SSL_CBC_RANDOM_IV 23
-#define SSL_ENABLE_OCSP_STAPLING 24 /* Request OCSP stapling (client) */
-
-/* SSL_ENABLE_NPN controls whether the NPN extension is enabled for the initial
- * handshake when application layer protocol negotiation is used.
- * SSL_SetNextProtoCallback or SSL_SetNextProtoNego must be used to control the
- * application layer protocol negotiation; otherwise, the NPN extension will
- * not be negotiated. SSL_ENABLE_NPN is currently enabled by default but this
- * may change in future versions.
- */
-#define SSL_ENABLE_NPN 25
-
-/* SSL_ENABLE_ALPN controls whether the ALPN extension is enabled for the
- * initial handshake when application layer protocol negotiation is used.
- * SSL_SetNextProtoNego (not SSL_SetNextProtoCallback) must be used to control
- * the application layer protocol negotiation; otherwise, the ALPN extension
- * will not be negotiated. ALPN is not negotiated for renegotiation handshakes,
- * even though the ALPN specification defines a way to use ALPN during
- * renegotiations. SSL_ENABLE_ALPN is currently disabled by default, but this
- * may change in future versions.
- */
-#define SSL_ENABLE_ALPN 26
-
-/* SSL_REUSE_SERVER_ECDHE_KEY controls whether the ECDHE server key is
- * reused for multiple handshakes or generated each time.
- * SSL_REUSE_SERVER_ECDHE_KEY is currently enabled by default.
- * This socket option is for ECDHE, only. It is unrelated to DHE.
- */
-#define SSL_REUSE_SERVER_ECDHE_KEY 27
-
-#define SSL_ENABLE_FALLBACK_SCSV 28 /* Send fallback SCSV in \
-                                     * handshakes. */
-
-/* SSL_ENABLE_SERVER_DHE controls whether DHE is enabled for the server socket.
- */
-#define SSL_ENABLE_SERVER_DHE 29
-
-/* Use draft-ietf-tls-session-hash. Controls whether we offer the
- * extended_master_secret extension which, when accepted, hashes
- * the handshake transcript into the master secret. This option is
- * disabled by default.
- */
-#define SSL_ENABLE_EXTENDED_MASTER_SECRET 30
-
-/* Request Signed Certificate Timestamps via TLS extension (client) */
-#define SSL_ENABLE_SIGNED_CERT_TIMESTAMPS 31
-
-#ifdef SSL_DEPRECATED_FUNCTION
-/* Old deprecated function names */
-SSL_IMPORT SECStatus SSL_Enable(PRFileDesc *fd, int option, PRBool on);
-SSL_IMPORT SECStatus SSL_EnableDefault(int option, PRBool on);
-#endif
-
-/* New function names */
-SSL_IMPORT SECStatus SSL_OptionSet(PRFileDesc *fd, PRInt32 option, PRBool on);
-SSL_IMPORT SECStatus SSL_OptionGet(PRFileDesc *fd, PRInt32 option, PRBool *on);
-SSL_IMPORT SECStatus SSL_OptionSetDefault(PRInt32 option, PRBool on);
-SSL_IMPORT SECStatus SSL_OptionGetDefault(PRInt32 option, PRBool *on);
-SSL_IMPORT SECStatus SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHandle);
-
-/* SSLNextProtoCallback is called during the handshake for the client, when a
- * Next Protocol Negotiation (NPN) extension has been received from the server.
- * |protos| and |protosLen| define a buffer which contains the server's
- * advertisement. This data is guaranteed to be well formed per the NPN spec.
- * |protoOut| is a buffer provided by the caller, of length 255 (the maximum
- * allowed by the protocol). On successful return, the protocol to be announced
- * to the server will be in |protoOut| and its length in |*protoOutLen|.
- *
- * The callback must return SECFailure or SECSuccess (not SECWouldBlock).
- */
-typedef SECStatus(PR_CALLBACK *SSLNextProtoCallback)(
-    void *arg,
-    PRFileDesc *fd,
-    const unsigned char *protos,
-    unsigned int protosLen,
-    unsigned char *protoOut,
-    unsigned int *protoOutLen,
-    unsigned int protoMaxOut);
-
-/* SSL_SetNextProtoCallback sets a callback function to handle Next Protocol
- * Negotiation. It causes a client to advertise NPN. */
-SSL_IMPORT SECStatus SSL_SetNextProtoCallback(PRFileDesc *fd,
-                                              SSLNextProtoCallback callback,
-                                              void *arg);
-
-/* SSL_SetNextProtoNego can be used as an alternative to
- * SSL_SetNextProtoCallback. It also causes a client to advertise NPN and
- * installs a default callback function which selects the first supported
- * protocol in server-preference order. If no matching protocol is found it
- * selects the first supported protocol.
- *
- * Using this function also allows the client to transparently support ALPN.
- * The same set of protocols will be advertised via ALPN and, if the server
- * uses ALPN to select a protocol, SSL_GetNextProto will return
- * SSL_NEXT_PROTO_SELECTED as the state.
- *
- * Since NPN uses the first protocol as the fallback protocol, when sending an
- * ALPN extension, the first protocol is moved to the end of the list. This
- * indicates that the fallback protocol is the least preferred. The other
- * protocols should be in preference order.
- *
- * The supported protocols are specified in |data| in wire-format (8-bit
- * length-prefixed). For example: "\010http/1.1\006spdy/2". */
-SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd,
-                                          const unsigned char *data,
-                                          unsigned int length);
-
-typedef enum SSLNextProtoState {
-    SSL_NEXT_PROTO_NO_SUPPORT = 0, /* No peer support                */
-    SSL_NEXT_PROTO_NEGOTIATED = 1, /* Mutual agreement               */
-    SSL_NEXT_PROTO_NO_OVERLAP = 2, /* No protocol overlap found      */
-    SSL_NEXT_PROTO_SELECTED = 3    /* Server selected proto (ALPN)   */
-} SSLNextProtoState;
-
-/* SSL_GetNextProto can be used in the HandshakeCallback or any time after
- * a handshake to retrieve the result of the Next Protocol negotiation.
- *
- * The length of the negotiated protocol, if any, is written into *bufLen.
- * If the negotiated protocol is longer than bufLenMax, then SECFailure is
- * returned. Otherwise, the negotiated protocol, if any, is written into buf,
- * and SECSuccess is returned. */
-SSL_IMPORT SECStatus SSL_GetNextProto(PRFileDesc *fd,
-                                      SSLNextProtoState *state,
-                                      unsigned char *buf,
-                                      unsigned int *bufLen,
-                                      unsigned int bufLenMax);
-
-/*
-** Control ciphers that SSL uses. If on is non-zero then the named cipher
-** is enabled, otherwise it is disabled.
-** The "cipher" values are defined in sslproto.h (the SSL_EN_* values).
-** EnableCipher records user preferences.
-** SetPolicy sets the policy according to the policy module.
-*/
-#ifdef SSL_DEPRECATED_FUNCTION
-/* Old deprecated function names */
-SSL_IMPORT SECStatus SSL_EnableCipher(long which, PRBool enabled);
-SSL_IMPORT SECStatus SSL_SetPolicy(long which, int policy);
-#endif
-
-/* New function names */
-SSL_IMPORT SECStatus SSL_CipherPrefSet(PRFileDesc *fd, PRInt32 cipher, PRBool enabled);
-SSL_IMPORT SECStatus SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 cipher, PRBool *enabled);
-SSL_IMPORT SECStatus SSL_CipherPrefSetDefault(PRInt32 cipher, PRBool enabled);
-SSL_IMPORT SECStatus SSL_CipherPrefGetDefault(PRInt32 cipher, PRBool *enabled);
-SSL_IMPORT SECStatus SSL_CipherPolicySet(PRInt32 cipher, PRInt32 policy);
-SSL_IMPORT SECStatus SSL_CipherPolicyGet(PRInt32 cipher, PRInt32 *policy);
-
-/*
-** Control for TLS signature algorithms for TLS 1.2 only.
-**
-** This governs what signature algorithms are sent by a client in the
-** signature_algorithms extension.  A client will not accept a signature from a
-** server unless it uses an enabled algorithm.
-**
-** This also governs what the server sends in the supported_signature_algorithms
-** field of a CertificateRequest.  It also changes what the server uses to sign
-** ServerKeyExchange: a server uses the first entry from this list that is
-** compatible with the client's advertised signature_algorithms extension and
-** the selected server certificate.
-**
-** Omitting SHA-256 from this list might be foolish.  Support is mandatory in
-** TLS 1.2 and there might be interoperability issues.  For a server, NSS only
-** supports SHA-256 for verifying a TLS 1.2 CertificateVerify.  This list needs
-** to include SHA-256 if client authentication is requested or required, or
-** creating a CertificateRequest will fail.
-*/
-SSL_IMPORT SECStatus SSL_SignaturePrefSet(
-    PRFileDesc *fd, const SSLSignatureAndHashAlg *algorithms,
-    unsigned int count);
-
-/*
-** Get the currently configured signature algorithms.
-**
-** The algorithms are written to |algorithms| but not if there are more than
-** |maxCount| values configured.  The number of algorithms that are in use are
-** written to |count|.  This fails if |maxCount| is insufficiently large.
-*/
-SSL_IMPORT SECStatus SSL_SignaturePrefGet(
-    PRFileDesc *fd, SSLSignatureAndHashAlg *algorithms, unsigned int *count,
-    unsigned int maxCount);
-
-/*
-** Returns the maximum number of signature algorithms that are supported and
-** can be set or retrieved using SSL_SignaturePrefSet or SSL_SignaturePrefGet.
-*/
-SSL_IMPORT unsigned int SSL_SignatureMaxCount();
-
-/* SSL_DHEGroupPrefSet is used to configure the set of allowed/enabled DHE group
-** parameters that can be used by NSS for the given server socket.
-** The first item in the array is used as the default group, if no other
-** selection criteria can be used by NSS.
-** The set is provided as an array of identifiers as defined by SSLDHEGroupType.
-** If more than one group identifier is provided, NSS will select the one to use.
-** For example, a TLS extension sent by the client might indicate a preference.
-*/
-SSL_IMPORT SECStatus SSL_DHEGroupPrefSet(PRFileDesc *fd,
-                                         SSLDHEGroupType *groups,
-                                         PRUint16 num_groups);
-
-/* Enable the use of a DHE group that's smaller than the library default,
-** for backwards compatibility reasons. The DH parameters will be created
-** at the time this function is called, which might take a very long time.
-** The function will block until generation is completed.
-** The intention is to enforce that fresh and safe parameters are generated
-** each time a process is started.
-** At the time this API was initially implemented, the API will enable the
-** use of 1024 bit DHE parameters. This value might get increased in future
-** versions of NSS.
-**
-** It is allowed to call this API will a NULL value for parameter fd,
-** which will prepare the global parameters that NSS will reuse for the remainder
-** of the process lifetime. This can be used early after startup of a process,
-** to avoid a delay when handling incoming client connections.
-** This preparation with a NULL for parameter fd will NOT enable the weak group
-** on sockets. The function needs to be called again for every socket that
-** should use the weak group.
-**
-** It is allowed to use this API in combination with the SSL_DHEGroupPrefSet API.
-** If both APIs have been called, the weakest group will be used,
-** unless it is certain that the client supports larger group parameters.
-** The weak group will be used as the default group, overriding the preference
-** for the first group potentially set with a call to SSL_DHEGroupPrefSet
-** (The first group set using SSL_DHEGroupPrefSet will still be enabled, but
-** it's no longer the default group.)
-*/
-SSL_IMPORT SECStatus SSL_EnableWeakDHEPrimeGroup(PRFileDesc *fd, PRBool enabled);
-
-/* SSL_CipherOrderSet sets the cipher suite preference order from |ciphers|,
- * which must be an array of cipher suite ids of length |len|. All the given
- * cipher suite ids must appear in the array that is returned by
- * |SSL_GetImplementedCiphers| and may only appear once, at most. */
-SSL_IMPORT SECStatus SSL_CipherOrderSet(PRFileDesc *fd, const PRUint16 *ciphers,
-                                        unsigned int len);
-
-/* SSLChannelBindingType enumerates the types of supported channel binding
- * values. See RFC 5929. */
-typedef enum SSLChannelBindingType {
-    SSL_CHANNEL_BINDING_TLS_UNIQUE = 1,
-} SSLChannelBindingType;
-
-/* SSL_GetChannelBinding copies the requested channel binding value, as defined
- * in RFC 5929, into |out|. The full length of the binding value is written
- * into |*outLen|.
- *
- * At most |outLenMax| bytes of data are copied. If |outLenMax| is
- * insufficient then the function returns SECFailure and sets the error to
- * SEC_ERROR_OUTPUT_LEN, but |*outLen| is still set.
- *
- * This call will fail if made during a renegotiation. */
-SSL_IMPORT SECStatus SSL_GetChannelBinding(PRFileDesc *fd,
-                                           SSLChannelBindingType binding_type,
-                                           unsigned char *out,
-                                           unsigned int *outLen,
-                                           unsigned int outLenMax);
-
-/* SSL Version Range API
-**
-** This API should be used to control SSL 3.0 & TLS support instead of the
-** older SSL_Option* API; however, the SSL_Option* API MUST still be used to
-** control SSL 2.0 support. In this version of libssl, SSL 3.0 and TLS 1.0 are
-** enabled by default. Future versions of libssl may change which versions of
-** the protocol are enabled by default.
-**
-** The SSLProtocolVariant enum indicates whether the protocol is of type
-** stream or datagram. This must be provided to the functions that do not
-** take an fd. Functions which take an fd will get the variant from the fd,
-** which is typed.
-**
-** Using the new version range API in conjunction with the older
-** SSL_OptionSet-based API for controlling the enabled protocol versions may
-** cause unexpected results. Going forward, we guarantee only the following:
-**
-** SSL_OptionGet(SSL_ENABLE_TLS) will return PR_TRUE if *ANY* versions of TLS
-** are enabled.
-**
-** SSL_OptionSet(SSL_ENABLE_TLS, PR_FALSE) will disable *ALL* versions of TLS,
-** including TLS 1.0 and later.
-**
-** The above two properties provide compatibility for applications that use
-** SSL_OptionSet to implement the insecure fallback from TLS 1.x to SSL 3.0.
-**
-** SSL_OptionSet(SSL_ENABLE_TLS, PR_TRUE) will enable TLS 1.0, and may also
-** enable some later versions of TLS, if it is necessary to do so in order to
-** keep the set of enabled versions contiguous. For example, if TLS 1.2 is
-** enabled, then after SSL_OptionSet(SSL_ENABLE_TLS, PR_TRUE), TLS 1.0,
-** TLS 1.1, and TLS 1.2 will be enabled, and the call will have no effect on
-** whether SSL 3.0 is enabled. If no later versions of TLS are enabled at the
-** time SSL_OptionSet(SSL_ENABLE_TLS, PR_TRUE) is called, then no later
-** versions of TLS will be enabled by the call.
-**
-** SSL_OptionSet(SSL_ENABLE_SSL3, PR_FALSE) will disable SSL 3.0, and will not
-** change the set of TLS versions that are enabled.
-**
-** SSL_OptionSet(SSL_ENABLE_SSL3, PR_TRUE) will enable SSL 3.0, and may also
-** enable some versions of TLS if TLS 1.1 or later is enabled at the time of
-** the call, the same way SSL_OptionSet(SSL_ENABLE_TLS, PR_TRUE) works, in
-** order to keep the set of enabled versions contiguous.
-*/
-
-/* Returns, in |*vrange|, the range of SSL3/TLS versions supported for the
-** given protocol variant by the version of libssl linked-to at runtime.
-*/
-SSL_IMPORT SECStatus SSL_VersionRangeGetSupported(
-    SSLProtocolVariant protocolVariant, SSLVersionRange *vrange);
-
-/* Returns, in |*vrange|, the range of SSL3/TLS versions enabled by default
-** for the given protocol variant.
-*/
-SSL_IMPORT SECStatus SSL_VersionRangeGetDefault(
-    SSLProtocolVariant protocolVariant, SSLVersionRange *vrange);
-
-/* Sets the range of enabled-by-default SSL3/TLS versions for the given
-** protocol variant to |*vrange|.
-*/
-SSL_IMPORT SECStatus SSL_VersionRangeSetDefault(
-    SSLProtocolVariant protocolVariant, const SSLVersionRange *vrange);
-
-/* Returns, in |*vrange|, the range of enabled SSL3/TLS versions for |fd|. */
-SSL_IMPORT SECStatus SSL_VersionRangeGet(PRFileDesc *fd,
-                                         SSLVersionRange *vrange);
-
-/* Sets the range of enabled SSL3/TLS versions for |fd| to |*vrange|. */
-SSL_IMPORT SECStatus SSL_VersionRangeSet(PRFileDesc *fd,
-                                         const SSLVersionRange *vrange);
-
-/* Sets the version to check the server random against for the
- * fallback check defined in [draft-ietf-tls-tls13-11 Section 6.3.1.1].
- * This function is provided to allow for detection of forced downgrade
- * attacks against client-side reconnect-and-fallback outside of TLS
- * by setting |version| to be that of the original connection, rather
- * than that of the new connection.
- *
- * The default, which can also be enabled by setting |version| to
- * zero, is just to check against the max version in the
- * version range (see SSL_VersionRangeSet). */
-SSL_IMPORT SECStatus SSL_SetDowngradeCheckVersion(PRFileDesc *fd,
-                                                  PRUint16 version);
-
-/* Values for "policy" argument to SSL_CipherPolicySet */
-/* Values returned by SSL_CipherPolicyGet. */
-#define SSL_NOT_ALLOWED 0 /* or invalid or unimplemented */
-#define SSL_ALLOWED 1
-#define SSL_RESTRICTED 2 /* only with "Step-Up" certs. */
-
-/* Values for "on" with SSL_REQUIRE_CERTIFICATE. */
-#define SSL_REQUIRE_NEVER ((PRBool)0)
-#define SSL_REQUIRE_ALWAYS ((PRBool)1)
-#define SSL_REQUIRE_FIRST_HANDSHAKE ((PRBool)2)
-#define SSL_REQUIRE_NO_ERROR ((PRBool)3)
-
-/* Values for "on" with SSL_ENABLE_RENEGOTIATION */
-/* Never renegotiate at all.                                               */
-#define SSL_RENEGOTIATE_NEVER ((PRBool)0)
-/* Renegotiate without restriction, whether or not the peer's client hello */
-/* bears the renegotiation info extension.  Vulnerable, as in the past.    */
-#define SSL_RENEGOTIATE_UNRESTRICTED ((PRBool)1)
-/* Only renegotiate if the peer's hello bears the TLS renegotiation_info   */
-/* extension. This is safe renegotiation.                                  */
-#define SSL_RENEGOTIATE_REQUIRES_XTN ((PRBool)2)
-/* Disallow unsafe renegotiation in server sockets only, but allow clients */
-/* to continue to renegotiate with vulnerable servers.                     */
-/* This value should only be used during the transition period when few    */
-/* servers have been upgraded.                                             */
-#define SSL_RENEGOTIATE_TRANSITIONAL ((PRBool)3)
-
-/*
-** Reset the handshake state for fd. This will make the complete SSL
-** handshake protocol execute from the ground up on the next i/o
-** operation.
-*/
-SSL_IMPORT SECStatus SSL_ResetHandshake(PRFileDesc *fd, PRBool asServer);
-
-/*
-** Force the handshake for fd to complete immediately.  This blocks until
-** the complete SSL handshake protocol is finished.
-*/
-SSL_IMPORT SECStatus SSL_ForceHandshake(PRFileDesc *fd);
-
-/*
-** Same as above, but with an I/O timeout.
- */
-SSL_IMPORT SECStatus SSL_ForceHandshakeWithTimeout(PRFileDesc *fd,
-                                                   PRIntervalTime timeout);
-
-SSL_IMPORT SECStatus SSL_RestartHandshakeAfterCertReq(PRFileDesc *fd,
-                                                      CERTCertificate *cert,
-                                                      SECKEYPrivateKey *key,
-                                                      CERTCertificateList *certChain);
-
-/*
-** Query security status of socket. *on is set to one if security is
-** enabled. *keySize will contain the stream key size used. *issuer will
-** contain the RFC1485 verison of the name of the issuer of the
-** certificate at the other end of the connection. For a client, this is
-** the issuer of the server's certificate; for a server, this is the
-** issuer of the client's certificate (if any). Subject is the subject of
-** the other end's certificate. The pointers can be zero if the desired
-** data is not needed.  All strings returned by this function are owned
-** by the caller, and need to be freed with PORT_Free.
-*/
-SSL_IMPORT SECStatus SSL_SecurityStatus(PRFileDesc *fd, int *on, char **cipher,
-                                        int *keySize, int *secretKeySize,
-                                        char **issuer, char **subject);
-
-/* Values for "on" */
-#define SSL_SECURITY_STATUS_NOOPT -1
-#define SSL_SECURITY_STATUS_OFF 0
-#define SSL_SECURITY_STATUS_ON_HIGH 1
-#define SSL_SECURITY_STATUS_ON_LOW 2
-#define SSL_SECURITY_STATUS_FORTEZZA 3 /* NO LONGER SUPPORTED */
-
-/*
-** Return the certificate for our SSL peer. If the client calls this
-** it will always return the server's certificate. If the server calls
-** this, it may return NULL if client authentication is not enabled or
-** if the client had no certificate when asked.
-**  "fd" the socket "file" descriptor
-*/
-SSL_IMPORT CERTCertificate *SSL_PeerCertificate(PRFileDesc *fd);
-
-/*
-** Return the certificates presented by the SSL peer. If the SSL peer
-** did not present certificates, return NULL with the
-** SSL_ERROR_NO_CERTIFICATE error. On failure, return NULL with an error
-** code other than SSL_ERROR_NO_CERTIFICATE.
-**  "fd" the socket "file" descriptor
-*/
-SSL_IMPORT CERTCertList *SSL_PeerCertificateChain(PRFileDesc *fd);
-
-/* SSL_PeerStapledOCSPResponses returns the OCSP responses that were provided
- * by the TLS server. The return value is a pointer to an internal SECItemArray
- * that contains the returned OCSP responses; it is only valid until the
- * callback function that calls SSL_PeerStapledOCSPResponses returns.
- *
- * If no OCSP responses were given by the server then the result will be empty.
- * If there was an error, then the result will be NULL.
- *
- * You must set the SSL_ENABLE_OCSP_STAPLING option to enable OCSP stapling.
- * to be provided by a server.
- *
- * libssl does not do any validation of the OCSP response itself; the
- * authenticate certificate hook is responsible for doing so. The default
- * authenticate certificate hook, SSL_AuthCertificate, does not implement
- * any OCSP stapling funtionality, but this may change in future versions.
- */
-SSL_IMPORT const SECItemArray *SSL_PeerStapledOCSPResponses(PRFileDesc *fd);
-
-/* SSL_PeerSignedCertTimestamps returns the signed_certificate_timestamp
- * extension data provided by the TLS server. The return value is a pointer
- * to an internal SECItem that contains the returned response (as a serialized
- * SignedCertificateTimestampList, see RFC 6962). The returned pointer is only
- * valid until the callback function that calls SSL_PeerSignedCertTimestamps
- * (e.g. the authenticate certificate hook, or the handshake callback) returns.
- *
- * If no Signed Certificate Timestamps were given by the server then the result
- * will be empty. If there was an error, then the result will be NULL.
- *
- * You must set the SSL_ENABLE_SIGNED_CERT_TIMESTAMPS option to indicate support
- * for Signed Certificate Timestamps to a server.
- *
- * libssl does not do any parsing or validation of the response itself.
- */
-SSL_IMPORT const SECItem *SSL_PeerSignedCertTimestamps(PRFileDesc *fd);
-
-/* SSL_SetStapledOCSPResponses stores an array of one or multiple OCSP responses
- * in the fd's data, which may be sent as part of a server side cert_status
- * handshake message. Parameter |responses| is for the server certificate of
- * the key exchange type |kea|.
- * The function will duplicate the responses array.
- */
-SSL_IMPORT SECStatus
-SSL_SetStapledOCSPResponses(PRFileDesc *fd, const SECItemArray *responses,
-                            SSLKEAType kea);
-
-/*
- * SSL_SetSignedCertTimestamps stores serialized signed_certificate_timestamp
- * extension data in the fd. The signed_certificate_timestamp data is sent
- * during the handshake (if requested by the client). Parameter |scts|
- * is for the server certificate of the key exchange type |kea|.
- * The function will duplicate the provided data item. To clear previously
- * set data for a given key exchange type |kea|, pass NULL to |scts|.
- */
-SSL_IMPORT SECStatus
-SSL_SetSignedCertTimestamps(PRFileDesc *fd, const SECItem *scts,
-                            SSLKEAType kea);
-
-/*
-** Authenticate certificate hook. Called when a certificate comes in
-** (because of SSL_REQUIRE_CERTIFICATE in SSL_Enable) to authenticate the
-** certificate.
-**
-** The authenticate certificate hook must return SECSuccess to indicate the
-** certificate is valid, SECFailure to indicate the certificate is invalid,
-** or SECWouldBlock if the application will authenticate the certificate
-** asynchronously. SECWouldBlock is only supported for non-blocking sockets.
-**
-** If the authenticate certificate hook returns SECFailure, then the bad cert
-** hook will be called. The bad cert handler is NEVER called if the
-** authenticate certificate hook returns SECWouldBlock. If the application
-** needs to handle and/or override a bad cert, it should do so before it
-** calls SSL_AuthCertificateComplete (modifying the error it passes to
-** SSL_AuthCertificateComplete as needed).
-**
-** See the documentation for SSL_AuthCertificateComplete for more information
-** about the asynchronous behavior that occurs when the authenticate
-** certificate hook returns SECWouldBlock.
-**
-** RFC 6066 says that clients should send the bad_certificate_status_response
-** alert when they encounter an error processing the stapled OCSP response.
-** libssl does not provide a way for the authenticate certificate hook to
-** indicate that an OCSP error (SEC_ERROR_OCSP_*) that it returns is an error
-** in the stapled OCSP response or an error in some other OCSP response.
-** Further, NSS does not provide a convenient way to control or determine
-** which OCSP response(s) were used to validate a certificate chain.
-** Consequently, the current version of libssl does not ever send the
-** bad_certificate_status_response alert. This may change in future releases.
-*/
-typedef SECStatus(PR_CALLBACK *SSLAuthCertificate)(void *arg, PRFileDesc *fd,
-                                                   PRBool checkSig,
-                                                   PRBool isServer);
-
-SSL_IMPORT SECStatus SSL_AuthCertificateHook(PRFileDesc *fd,
-                                             SSLAuthCertificate f,
-                                             void *arg);
-
-/* An implementation of the certificate authentication hook */
-SSL_IMPORT SECStatus SSL_AuthCertificate(void *arg, PRFileDesc *fd,
-                                         PRBool checkSig, PRBool isServer);
-
-/*
- * Prototype for SSL callback to get client auth data from the application.
- *  arg - application passed argument
- *  caNames - pointer to distinguished names of CAs that the server likes
- *  pRetCert - pointer to pointer to cert, for return of cert
- *  pRetKey - pointer to key pointer, for return of key
- */
-typedef SECStatus(PR_CALLBACK *SSLGetClientAuthData)(void *arg,
-                                                     PRFileDesc *fd,
-                                                     CERTDistNames *caNames,
-                                                     CERTCertificate **pRetCert,  /*return */
-                                                     SECKEYPrivateKey **pRetKey); /* return */
-
-/*
- * Set the client side callback for SSL to retrieve user's private key
- * and certificate.
- *  fd - the file descriptor for the connection in question
- *  f - the application's callback that delivers the key and cert
- *  a - application specific data
- */
-SSL_IMPORT SECStatus SSL_GetClientAuthDataHook(PRFileDesc *fd,
-                                               SSLGetClientAuthData f, void *a);
-
-/*
-** SNI extension processing callback function.
-** It is called when SSL socket receives SNI extension in ClientHello message.
-** Upon this callback invocation, application is responsible to reconfigure the
-** socket with the data for a particular server name.
-** There are three potential outcomes of this function invocation:
-**    * application does not recognize the name or the type and wants the
-**    "unrecognized_name" alert be sent to the client. In this case the callback
-**    function must return SSL_SNI_SEND_ALERT status.
-**    * application does not recognize  the name, but wants to continue with
-**    the handshake using the current socket configuration. In this case,
-**    no socket reconfiguration is needed and the function should return
-**    SSL_SNI_CURRENT_CONFIG_IS_USED.
-**    * application recognizes the name and reconfigures the socket with
-**    appropriate certs, key, etc. There are many ways to reconfigure. NSS
-**    provides SSL_ReconfigFD function that can be used to update the socket
-**    data from model socket. To continue with the rest of the handshake, the
-**    implementation function should return an index of a name it has chosen.
-** LibSSL will ignore any SNI extension received in a ClientHello message
-** if application does not register a SSLSNISocketConfig callback.
-** Each type field of SECItem indicates the name type.
-** NOTE: currently RFC3546 defines only one name type: sni_host_name.
-** Client is allowed to send only one name per known type. LibSSL will
-** send an "unrecognized_name" alert if SNI extension name list contains more
-** then one name of a type.
-*/
-typedef PRInt32(PR_CALLBACK *SSLSNISocketConfig)(PRFileDesc *fd,
-                                                 const SECItem *srvNameArr,
-                                                 PRUint32 srvNameArrSize,
-                                                 void *arg);
-
-/*
-** SSLSNISocketConfig should return an index within 0 and srvNameArrSize-1
-** when it has reconfigured the socket fd to use certs and keys, etc
-** for a specific name. There are two other allowed return values. One
-** tells libSSL to use the default cert and key.  The other tells libSSL
-** to send the "unrecognized_name" alert.  These values are:
-**/
-#define SSL_SNI_CURRENT_CONFIG_IS_USED -1
-#define SSL_SNI_SEND_ALERT -2
-
-/*
-** Set application implemented SNISocketConfig callback.
-*/
-SSL_IMPORT SECStatus SSL_SNISocketConfigHook(PRFileDesc *fd,
-                                             SSLSNISocketConfig f,
-                                             void *arg);
-
-/*
-** Reconfigure fd SSL socket with model socket parameters. Sets
-** server certs and keys, list of trust anchor, socket options
-** and all SSL socket call backs and parameters.
-*/
-SSL_IMPORT PRFileDesc *SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd);
-
-/*
- * Set the client side argument for SSL to retrieve PKCS #11 pin.
- *  fd - the file descriptor for the connection in question
- *  a - pkcs11 application specific data
- */
-SSL_IMPORT SECStatus SSL_SetPKCS11PinArg(PRFileDesc *fd, void *a);
-
-/*
-** This is a callback for dealing with server certs that are not authenticated
-** by the client.  The client app can decide that it actually likes the
-** cert by some external means and restart the connection.
-**
-** The bad cert hook must return SECSuccess to override the result of the
-** authenticate certificate hook, SECFailure if the certificate should still be
-** considered invalid, or SECWouldBlock if the application will authenticate
-** the certificate asynchronously. SECWouldBlock is only supported for
-** non-blocking sockets.
-**
-** See the documentation for SSL_AuthCertificateComplete for more information
-** about the asynchronous behavior that occurs when the bad cert hook returns
-** SECWouldBlock.
-*/
-typedef SECStatus(PR_CALLBACK *SSLBadCertHandler)(void *arg, PRFileDesc *fd);
-SSL_IMPORT SECStatus SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f,
-                                     void *arg);
-
-/*
-** Configure SSL socket for running a secure server. Needs the
-** certificate for the server and the servers private key. The arguments
-** are copied.
-*/
-SSL_IMPORT SECStatus SSL_ConfigSecureServer(
-    PRFileDesc *fd, CERTCertificate *cert,
-    SECKEYPrivateKey *key, SSLKEAType kea);
-
-/*
-** Allows SSL socket configuration with caller-supplied certificate chain.
-** If certChainOpt is NULL, tries to find one.
-*/
-SSL_IMPORT SECStatus
-SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert,
-                                    const CERTCertificateList *certChainOpt,
-                                    SECKEYPrivateKey *key, SSLKEAType kea);
-
-/*
-** Configure a secure server's session-id cache. Define the maximum number
-** of entries in the cache, the longevity of the entires, and the directory
-** where the cache files will be placed.  These values can be zero, and
-** if so, the implementation will choose defaults.
-** This version of the function is for use in applications that have only one
-** process that uses the cache (even if that process has multiple threads).
-*/
-SSL_IMPORT SECStatus SSL_ConfigServerSessionIDCache(int maxCacheEntries,
-                                                    PRUint32 timeout,
-                                                    PRUint32 ssl3_timeout,
-                                                    const char *directory);
-
-/* Configure a secure server's session-id cache. Depends on value of
- * enableMPCache, configures malti-proc or single proc cache. */
-SSL_IMPORT SECStatus SSL_ConfigServerSessionIDCacheWithOpt(
-    PRUint32 timeout,
-    PRUint32 ssl3_timeout,
-    const char *directory,
-    int maxCacheEntries,
-    int maxCertCacheEntries,
-    int maxSrvNameCacheEntries,
-    PRBool enableMPCache);
-
-/*
-** Like SSL_ConfigServerSessionIDCache, with one important difference.
-** If the application will run multiple processes (as opposed to, or in
-** addition to multiple threads), then it must call this function, instead
-** of calling SSL_ConfigServerSessionIDCache().
-** This has nothing to do with the number of processORs, only processEs.
-** This function sets up a Server Session ID (SID) cache that is safe for
-** access by multiple processes on the same system.
-*/
-SSL_IMPORT SECStatus SSL_ConfigMPServerSIDCache(int maxCacheEntries,
-                                                PRUint32 timeout,
-                                                PRUint32 ssl3_timeout,
-                                                const char *directory);
-
-/* Get and set the configured maximum number of mutexes used for the
-** server's store of SSL sessions.  This value is used by the server
-** session ID cache initialization functions shown above.  Note that on
-** some platforms, these mutexes are actually implemented with POSIX
-** semaphores, or with unnamed pipes.  The default value varies by platform.
-** An attempt to set a too-low maximum will return an error and the
-** configured value will not be changed.
-*/
-SSL_IMPORT PRUint32 SSL_GetMaxServerCacheLocks(void);
-SSL_IMPORT SECStatus SSL_SetMaxServerCacheLocks(PRUint32 maxLocks);
-
-/* environment variable set by SSL_ConfigMPServerSIDCache, and queried by
- * SSL_InheritMPServerSIDCache when envString is NULL.
- */
-#define SSL_ENV_VAR_NAME "SSL_INHERITANCE"
-
-/* called in child to inherit SID Cache variables.
- * If envString is NULL, this function will use the value of the environment
- * variable "SSL_INHERITANCE", otherwise the string value passed in will be
- * used.
- */
-SSL_IMPORT SECStatus SSL_InheritMPServerSIDCache(const char *envString);
-
-/*
-** Set the callback that gets called when a TLS handshake is complete. The
-** handshake callback is called after verifying the peer's Finished message and
-** before processing incoming application data.
-**
-** For the initial handshake: If the handshake false started (see
-** SSL_ENABLE_FALSE_START), then application data may already have been sent
-** before the handshake callback is called. If we did not false start then the
-** callback will get called before any application data is sent.
-*/
-typedef void(PR_CALLBACK *SSLHandshakeCallback)(PRFileDesc *fd,
-                                                void *client_data);
-SSL_IMPORT SECStatus SSL_HandshakeCallback(PRFileDesc *fd,
-                                           SSLHandshakeCallback cb, void *client_data);
-
-/* Applications that wish to enable TLS false start must set this callback
-** function. NSS will invoke the functon to determine if a particular
-** connection should use false start or not. SECSuccess indicates that the
-** callback completed successfully, and if so *canFalseStart indicates if false
-** start can be used. If the callback does not return SECSuccess then the
-** handshake will be canceled. NSS's recommended criteria can be evaluated by
-** calling SSL_RecommendedCanFalseStart.
-**
-** If no false start callback is registered then false start will never be
-** done, even if the SSL_ENABLE_FALSE_START option is enabled.
-**/
-typedef SECStatus(PR_CALLBACK *SSLCanFalseStartCallback)(
-    PRFileDesc *fd, void *arg, PRBool *canFalseStart);
-
-SSL_IMPORT SECStatus SSL_SetCanFalseStartCallback(
-    PRFileDesc *fd, SSLCanFalseStartCallback callback, void *arg);
-
-/* This function sets *canFalseStart according to the recommended criteria for
-** false start. These criteria may change from release to release and may depend
-** on which handshake features have been negotiated and/or properties of the
-** certifciates/keys used on the connection.
-*/
-SSL_IMPORT SECStatus SSL_RecommendedCanFalseStart(PRFileDesc *fd,
-                                                  PRBool *canFalseStart);
-
-/*
-** For the server, request a new handshake.  For the client, begin a new
-** handshake.  If flushCache is non-zero, the SSL3 cache entry will be
-** flushed first, ensuring that a full SSL handshake will be done.
-** If flushCache is zero, and an SSL connection is established, it will
-** do the much faster session restart handshake.  This will change the
-** session keys without doing another private key operation.
-*/
-SSL_IMPORT SECStatus SSL_ReHandshake(PRFileDesc *fd, PRBool flushCache);
-
-/*
-** Same as above, but with an I/O timeout.
- */
-SSL_IMPORT SECStatus SSL_ReHandshakeWithTimeout(PRFileDesc *fd,
-                                                PRBool flushCache,
-                                                PRIntervalTime timeout);
-
-/* Returns a SECItem containing the certificate_types field of the
-** CertificateRequest message.  Each byte of the data is a TLS
-** ClientCertificateType value, and they are ordered from most preferred to
-** least.  This function should only be called from the
-** SSL_GetClientAuthDataHook callback, and will return NULL if called at any
-** other time.  The returned value is valid only until the callback returns, and
-** should not be freed.
-*/
-SSL_IMPORT const SECItem *
-SSL_GetRequestedClientCertificateTypes(PRFileDesc *fd);
-
-#ifdef SSL_DEPRECATED_FUNCTION
-/* deprecated!
-** For the server, request a new handshake.  For the client, begin a new
-** handshake.  Flushes SSL3 session cache entry first, ensuring that a
-** full handshake will be done.
-** This call is equivalent to SSL_ReHandshake(fd, PR_TRUE)
-*/
-SSL_IMPORT SECStatus SSL_RedoHandshake(PRFileDesc *fd);
-#endif
-
-/*
- * Allow the application to pass a URL or hostname into the SSL library.
- */
-SSL_IMPORT SECStatus SSL_SetURL(PRFileDesc *fd, const char *url);
-
-/*
- * Allow an application to define a set of trust anchors for peer
- * cert validation.
- */
-SSL_IMPORT SECStatus SSL_SetTrustAnchors(PRFileDesc *fd, CERTCertList *list);
-
-/*
-** Return the number of bytes that SSL has waiting in internal buffers.
-** Return 0 if security is not enabled.
-*/
-SSL_IMPORT int SSL_DataPending(PRFileDesc *fd);
-
-/*
-** Invalidate the SSL session associated with fd.
-*/
-SSL_IMPORT SECStatus SSL_InvalidateSession(PRFileDesc *fd);
-
-/*
-** Cache the SSL session associated with fd, if it has not already been cached.
-*/
-SSL_IMPORT SECStatus SSL_CacheSession(PRFileDesc *fd);
-
-/*
-** Cache the SSL session associated with fd, if it has not already been cached.
-** This function may only be called when processing within a callback assigned
-** via SSL_HandshakeCallback
-*/
-SSL_IMPORT SECStatus SSL_CacheSessionUnlocked(PRFileDesc *fd);
-
-/*
-** Return a SECItem containing the SSL session ID associated with the fd.
-*/
-SSL_IMPORT SECItem *SSL_GetSessionID(PRFileDesc *fd);
-
-/*
-** Clear out the client's SSL session cache, not the server's session cache.
-*/
-SSL_IMPORT void SSL_ClearSessionCache(void);
-
-/*
-** Close the server's SSL session cache.
-*/
-SSL_IMPORT SECStatus SSL_ShutdownServerSessionIDCache(void);
-
-/*
-** Set peer information so we can correctly look up SSL session later.
-** You only have to do this if you're tunneling through a proxy.
-*/
-SSL_IMPORT SECStatus SSL_SetSockPeerID(PRFileDesc *fd, const char *peerID);
-
-/*
-** Reveal the security information for the peer.
-*/
-SSL_IMPORT CERTCertificate *SSL_RevealCert(PRFileDesc *socket);
-SSL_IMPORT void *SSL_RevealPinArg(PRFileDesc *socket);
-SSL_IMPORT char *SSL_RevealURL(PRFileDesc *socket);
-
-/* This callback may be passed to the SSL library via a call to
- * SSL_GetClientAuthDataHook() for each SSL client socket.
- * It will be invoked when SSL needs to know what certificate and private key
- * (if any) to use to respond to a request for client authentication.
- * If arg is non-NULL, it is a pointer to a NULL-terminated string containing
- * the nickname of the cert/key pair to use.
- * If arg is NULL, this function will search the cert and key databases for
- * a suitable match and send it if one is found.
- */
-SSL_IMPORT SECStatus
-NSS_GetClientAuthData(void *arg,
-                      PRFileDesc *socket,
-                      struct CERTDistNamesStr *caNames,
-                      struct CERTCertificateStr **pRetCert,
-                      struct SECKEYPrivateKeyStr **pRetKey);
-
-/*
-** Configure DTLS-SRTP (RFC 5764) cipher suite preferences.
-** Input is a list of ciphers in descending preference order and a length
-** of the list. As a side effect, this causes the use_srtp extension to be
-** negotiated.
-**
-** Invalid or unimplemented cipher suites in |ciphers| are ignored. If at
-** least one cipher suite in |ciphers| is implemented, returns SECSuccess.
-** Otherwise returns SECFailure.
-*/
-SSL_IMPORT SECStatus SSL_SetSRTPCiphers(PRFileDesc *fd,
-                                        const PRUint16 *ciphers,
-                                        unsigned int numCiphers);
-
-/*
-** Get the selected DTLS-SRTP cipher suite (if any).
-** To be called after the handshake completes.
-** Returns SECFailure if not negotiated.
-*/
-SSL_IMPORT SECStatus SSL_GetSRTPCipher(PRFileDesc *fd,
-                                       PRUint16 *cipher);
-
-/*
- * Look to see if any of the signers in the cert chain for "cert" are found
- * in the list of caNames.
- * Returns SECSuccess if so, SECFailure if not.
- * Used by NSS_GetClientAuthData.  May be used by other callback functions.
- */
-SSL_IMPORT SECStatus NSS_CmpCertChainWCANames(CERTCertificate *cert,
-                                              CERTDistNames *caNames);
-
-/*
- * Returns key exchange type of the keys in an SSL server certificate.
- */
-SSL_IMPORT SSLKEAType NSS_FindCertKEAType(CERTCertificate *cert);
-
-/* Set cipher policies to a predefined Domestic (U.S.A.) policy.
- * This essentially allows all supported ciphers.
- */
-SSL_IMPORT SECStatus NSS_SetDomesticPolicy(void);
-
-/* Set cipher policies to a predefined Policy that is exportable from the USA
- *   according to present U.S. policies as we understand them.
- * It is the same as NSS_SetDomesticPolicy now.
- */
-SSL_IMPORT SECStatus NSS_SetExportPolicy(void);
-
-/* Set cipher policies to a predefined Policy that is exportable from the USA
- *   according to present U.S. policies as we understand them, and that the
- *   nation of France will permit to be imported into their country.
- * It is the same as NSS_SetDomesticPolicy now.
- */
-SSL_IMPORT SECStatus NSS_SetFrancePolicy(void);
-
-SSL_IMPORT SSL3Statistics *SSL_GetStatistics(void);
-
-/* Report more information than SSL_SecurityStatus.
- * Caller supplies the info struct.  This function fills it in.  Caller should
- * pass sizeof(SSLChannelInfo) as the |len| argument.
- *
- * The information here will be zeroed prior to details being confirmed.  The
- * details are confirmed either when a Finished message is received, or - for a
- * client - when the second flight of messages have been sent.  This function
- * therefore produces unreliable results prior to receiving the
- * SSLHandshakeCallback or the SSLCanFalseStartCallback.
- */
-SSL_IMPORT SECStatus SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info,
-                                        PRUintn len);
-/* Get preliminary information about a channel.
- * Caller supplies the info struct.  This function fills it in.  Caller should
- * pass sizeof(SSLPreliminaryChannelInfo) as the |len| argument.
- *
- * this function is available to SSLAuthCertificate, SSLGetClientAuthData,
- * SSLSNISocketConfig, and other callbacks that might be called during the
- * processing of the first flight of client of server handshake messages.
- * Values are marked as being unavailable when renegotiation is initiated.
- */
-SSL_IMPORT SECStatus
-SSL_GetPreliminaryChannelInfo(PRFileDesc *fd,
-                              SSLPreliminaryChannelInfo *info,
-                              PRUintn len);
-/* Get information about cipher suite with id of |cipherSuite|.
- * Caller supplies the info struct.  This function fills it in.  Caller should
- * pass sizeof(SSLCipherSuiteInfo) as the |len| argument.
- */
-SSL_IMPORT SECStatus SSL_GetCipherSuiteInfo(PRUint16 cipherSuite,
-                                            SSLCipherSuiteInfo *info, PRUintn len);
-
-/* Returnes negotiated through SNI host info. */
-SSL_IMPORT SECItem *SSL_GetNegotiatedHostInfo(PRFileDesc *fd);
-
-/* Export keying material according to RFC 5705.
-** fd must correspond to a TLS 1.0 or higher socket and out must
-** already be allocated. If hasContext is false, it uses the no-context
-** construction from the RFC and ignores the context and contextLen
-** arguments.
-*/
-SSL_IMPORT SECStatus SSL_ExportKeyingMaterial(PRFileDesc *fd,
-                                              const char *label,
-                                              unsigned int labelLen,
-                                              PRBool hasContext,
-                                              const unsigned char *context,
-                                              unsigned int contextLen,
-                                              unsigned char *out,
-                                              unsigned int outLen);
-
-/*
-** Return a new reference to the certificate that was most recently sent
-** to the peer on this SSL/TLS connection, or NULL if none has been sent.
-*/
-SSL_IMPORT CERTCertificate *SSL_LocalCertificate(PRFileDesc *fd);
-
-/* Test an SSL configuration to see if  SSL_BYPASS_PKCS11 can be turned on.
-** Check the key exchange algorithm for each cipher in the list to see if
-** a master secret key can be extracted after being derived with the mechanism
-** required by the protocolmask argument. If the KEA will use keys from the
-** specified cert make sure the extract operation is attempted from the slot
-** where the private key resides.
-** If MS can be extracted for all ciphers, (*pcanbypass) is set to TRUE and
-** SECSuccess is returned. In all other cases but one (*pcanbypass) is
-** set to FALSE and SECFailure is returned.
-** In that last case Derive() has been called successfully but the MS is null,
-** CanBypass sets (*pcanbypass) to FALSE and returns SECSuccess indicating the
-** arguments were all valid but the slot cannot be bypassed.
-**
-** Note: A TRUE return code from CanBypass means "Your configuration will perform
-** NO WORSE with the bypass enabled than without"; it does NOT mean that every
-** cipher suite listed will work properly with the selected protocols.
-**
-** Caveat: If export cipher suites are included in the argument list Canbypass
-** will return FALSE.
-**/
-
-/* protocol mask bits */
-#define SSL_CBP_SSL3 0x0001   /* test SSL v3 mechanisms */
-#define SSL_CBP_TLS1_0 0x0002 /* test TLS v1.0 mechanisms */
-
-SSL_IMPORT SECStatus SSL_CanBypass(CERTCertificate *cert,
-                                   SECKEYPrivateKey *privKey,
-                                   PRUint32 protocolmask,
-                                   PRUint16 *ciphers, int nciphers,
-                                   PRBool *pcanbypass, void *pwArg);
-
-/*
-** Did the handshake with the peer negotiate the given extension?
-** Output parameter valid only if function returns SECSuccess
-*/
-SSL_IMPORT SECStatus SSL_HandshakeNegotiatedExtension(PRFileDesc *socket,
-                                                      SSLExtensionType extId,
-                                                      PRBool *yes);
-
-SSL_IMPORT SECStatus SSL_HandshakeResumedSession(PRFileDesc *fd,
-                                                 PRBool *last_handshake_resumed);
-
-/* See SSL_SetClientChannelIDCallback for usage. If the callback returns
- * SECWouldBlock then SSL_RestartHandshakeAfterChannelIDReq should be called in
- * the future to restart the handshake.  On SECSuccess, the callback must have
- * written a P-256, EC key pair to |*out_public_key| and |*out_private_key|. */
-typedef SECStatus(PR_CALLBACK *SSLClientChannelIDCallback)(
-    void *arg,
-    PRFileDesc *fd,
-    SECKEYPublicKey **out_public_key,
-    SECKEYPrivateKey **out_private_key);
-
-/* SSL_RestartHandshakeAfterChannelIDReq attempts to restart the handshake
- * after a ChannelID callback returned SECWouldBlock.
- *
- * This function takes ownership of |channelIDPub| and |channelID|. */
-SSL_IMPORT SECStatus SSL_RestartHandshakeAfterChannelIDReq(
-    PRFileDesc *fd,
-    SECKEYPublicKey *channelIDPub,
-    SECKEYPrivateKey *channelID);
-
-/* SSL_SetClientChannelIDCallback sets a callback function that will be called
- * once the server's ServerHello has been processed. This is only applicable to
- * a client socket and setting this callback causes the TLS Channel ID
- * extension to be advertised. */
-SSL_IMPORT SECStatus SSL_SetClientChannelIDCallback(
-    PRFileDesc *fd,
-    SSLClientChannelIDCallback callback,
-    void *arg);
-
-/*
-** How long should we wait before retransmitting the next flight of
-** the DTLS handshake? Returns SECFailure if not DTLS or not in a
-** handshake.
-*/
-SSL_IMPORT SECStatus DTLS_GetHandshakeTimeout(PRFileDesc *socket,
-                                              PRIntervalTime *timeout);
-
-/*
- * Return a boolean that indicates whether the underlying library
- * will perform as the caller expects.
- *
- * The only argument is a string, which should be the version
- * identifier of the NSS library. That string will be compared
- * against a string that represents the actual build version of
- * the SSL library.
- */
-extern PRBool NSSSSL_VersionCheck(const char *importedVersion);
-
-/*
- * Returns a const string of the SSL library version.
- */
-extern const char *NSSSSL_GetVersion(void);
-
-/* Restart an SSL connection that was paused to do asynchronous certificate
- * chain validation (when the auth certificate hook or bad cert handler
- * returned SECWouldBlock).
- *
- * This function only works for non-blocking sockets; Do not use it for
- * blocking sockets. Currently, this function works only for the client role of
- * a connection; it does not work for the server role.
- *
- * The application must call SSL_AuthCertificateComplete with 0 as the value of
- * the error parameter after it has successfully validated the peer's
- * certificate, in order to continue the SSL handshake.
- *
- * The application may call SSL_AuthCertificateComplete with a non-zero value
- * for error (e.g. SEC_ERROR_REVOKED_CERTIFICATE) when certificate validation
- * fails, before it closes the connection. If the application does so, an
- * alert corresponding to the error (e.g. certificate_revoked) will be sent to
- * the peer. See the source code of the internal function
- * ssl3_SendAlertForCertError for the current mapping of error to alert. This
- * mapping may change in future versions of libssl.
- *
- * This function will not complete the entire handshake. The application must
- * call SSL_ForceHandshake, PR_Recv, PR_Send, etc. after calling this function
- * to force the handshake to complete.
- *
- * On the first handshake of a connection, libssl will wait for the peer's
- * certificate to be authenticated before calling the handshake callback,
- * sending a client certificate, sending any application data, or returning
- * any application data to the application. On subsequent (renegotiation)
- * handshakes, libssl will block the handshake unconditionally while the
- * certificate is being validated.
- *
- * libssl may send and receive handshake messages while waiting for the
- * application to call SSL_AuthCertificateComplete, and it may call other
- * callbacks (e.g, the client auth data hook) before
- * SSL_AuthCertificateComplete has been called.
- *
- * An application that uses this asynchronous mechanism will usually have lower
- * handshake latency if it has to do public key operations on the certificate
- * chain and/or CRL/OCSP/cert fetching during the authentication, especially if
- * it does so in parallel on another thread. However, if the application can
- * authenticate the peer's certificate quickly then it may be more efficient
- * to use the synchronous mechanism (i.e. returning SECFailure/SECSuccess
- * instead of SECWouldBlock from the authenticate certificate hook).
- *
- * Be careful about converting an application from synchronous cert validation
- * to asynchronous certificate validation. A naive conversion is likely to
- * result in deadlocks; e.g. the application will wait in PR_Poll for network
- * I/O on the connection while all network I/O on the connection is blocked
- * waiting for this function to be called.
- *
- * Returns SECFailure on failure, SECSuccess on success. Never returns
- * SECWouldBlock. Note that SSL_AuthCertificateComplete will (usually) return
- * SECSuccess; do not interpret the return value of SSL_AuthCertificateComplete
- * as an indicator of whether it is OK to continue using the connection. For
- * example, SSL_AuthCertificateComplete(fd, SEC_ERROR_REVOKED_CERTIFICATE) will
- * return SECSuccess (normally), but that does not mean that the application
- * should continue using the connection. If the application passes a non-zero
- * value for second argument (error), or if SSL_AuthCertificateComplete returns
- * anything other than SECSuccess, then the application should close the
- * connection.
- */
-SSL_IMPORT SECStatus SSL_AuthCertificateComplete(PRFileDesc *fd,
-                                                 PRErrorCode error);
-SEC_END_PROTOS
-
-#endif /* __ssl_h_ */
diff --git a/net/third_party/nss/ssl/ssl.rc b/net/third_party/nss/ssl/ssl.rc
deleted file mode 100644
index 809a07e..0000000
--- a/net/third_party/nss/ssl/ssl.rc
+++ /dev/null
@@ -1,68 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nss.h"
-#include <winver.h>
-
-#define MY_LIBNAME "ssl"
-#define MY_FILEDESCRIPTION "NSS SSL Library"
-
-#define STRINGIZE(x) #x
-#define STRINGIZE2(x) STRINGIZE(x)
-#define NSS_VMAJOR_STR STRINGIZE2(NSS_VMAJOR)
-
-#ifdef _DEBUG
-#define MY_DEBUG_STR " (debug)"
-#define MY_FILEFLAGS_1 VS_FF_DEBUG
-#else
-#define MY_DEBUG_STR ""
-#define MY_FILEFLAGS_1 0x0L
-#endif
-#if NSS_BETA
-#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
-#else
-#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
-#endif
-
-#ifdef WINNT
-#define MY_FILEOS VOS_NT_WINDOWS32
-#else
-#define MY_FILEOS VOS__WINDOWS32
-#endif
-
-#define MY_INTERNAL_NAME MY_LIBNAME NSS_VMAJOR_STR
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version-information resource
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION NSS_VMAJOR,NSS_VMINOR,NSS_VPATCH,NSS_VBUILD
- PRODUCTVERSION NSS_VMAJOR,NSS_VMINOR,NSS_VPATCH,NSS_VBUILD
- FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
- FILEFLAGS MY_FILEFLAGS_2
- FILEOS MY_FILEOS
- FILETYPE VFT_DLL
- FILESUBTYPE 0x0L // not used
-
-BEGIN
-    BLOCK "StringFileInfo"
-    BEGIN
-        BLOCK "040904B0" // Lang=US English, CharSet=Unicode
-        BEGIN
-            VALUE "CompanyName", "Mozilla Foundation\0"
-            VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
-            VALUE "FileVersion", NSS_VERSION "\0"
-            VALUE "InternalName", MY_INTERNAL_NAME "\0"
-            VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
-            VALUE "ProductName", "Network Security Services\0"
-            VALUE "ProductVersion", NSS_VERSION "\0"
-        END
-    END
-    BLOCK "VarFileInfo"
-    BEGIN
-        VALUE "Translation", 0x409, 1200
-    END
-END
diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c
deleted file mode 100644
index b6f4987b..0000000
--- a/net/third_party/nss/ssl/ssl3con.c
+++ /dev/null
@@ -1,14146 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * SSL3 Protocol
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* TODO(ekr): Implement HelloVerifyRequest on server side. OK for now. */
-
-#include "cert.h"
-#include "ssl.h"
-#include "cryptohi.h" /* for DSAU_ stuff */
-#include "keyhi.h"
-#include "secder.h"
-#include "secitem.h"
-#include "sechash.h"
-
-#include "sslimpl.h"
-#include "sslproto.h"
-#include "sslerr.h"
-#include "prtime.h"
-#include "prinrval.h"
-#include "prerror.h"
-#include "pratom.h"
-#include "prthread.h"
-#include "nss.h"
-#include "nssoptions.h"
-
-#include "pk11func.h"
-#include "secmod.h"
-#ifndef NO_PKCS11_BYPASS
-#include "blapi.h"
-#endif
-
-#include <stdio.h>
-#ifdef NSS_SSL_ENABLE_ZLIB
-#include "zlib.h"
-#endif
-
-#ifndef PK11_SETATTRS
-#define PK11_SETATTRS(x, id, v, l) \
-    (x)->type = (id);              \
-    (x)->pValue = (v);             \
-    (x)->ulValueLen = (l);
-#endif
-
-static SECStatus ssl3_AuthCertificate(sslSocket *ss);
-static void ssl3_CleanupPeerCerts(sslSocket *ss);
-static void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid);
-static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec,
-                                       PK11SlotInfo *serverKeySlot);
-static SECStatus ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms);
-static SECStatus ssl3_DeriveConnectionKeysPKCS11(sslSocket *ss);
-static SECStatus ssl3_HandshakeFailure(sslSocket *ss);
-static SECStatus ssl3_InitState(sslSocket *ss);
-
-static SECStatus ssl3_SendCertificateRequest(sslSocket *ss);
-static SECStatus ssl3_SendNextProto(sslSocket *ss);
-static SECStatus ssl3_SendChannelIDEncryptedExtensions(sslSocket *ss);
-static SECStatus ssl3_SendFinished(sslSocket *ss, PRInt32 flags);
-static SECStatus ssl3_SendServerHelloDone(sslSocket *ss);
-static SECStatus ssl3_SendServerKeyExchange(sslSocket *ss);
-static SECStatus ssl3_UpdateHandshakeHashes(sslSocket *ss,
-                                            const unsigned char *b,
-                                            unsigned int l);
-static SECStatus ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss,
-                                                      SSL3Opaque *b,
-                                                      PRUint32 length,
-                                                      SSL3Hashes *hashesPtr);
-static SECStatus ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags);
-
-static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen,
-                             int maxOutputLen, const unsigned char *input,
-                             int inputLen);
-#ifndef NO_PKCS11_BYPASS
-static SECStatus ssl3_AESGCMBypass(ssl3KeyMaterial *keys, PRBool doDecrypt,
-                                   unsigned char *out, int *outlen, int maxout,
-                                   const unsigned char *in, int inlen,
-                                   const unsigned char *additionalData,
-                                   int additionalDataLen);
-#endif
-
-#define MAX_SEND_BUF_LENGTH 32000 /* watch for 16-bit integer overflow */
-#define MIN_SEND_BUF_LENGTH 4000
-
-/* This list of SSL3 cipher suites is sorted in descending order of
- * precedence (desirability).  It only includes cipher suites we implement.
- * This table is modified by SSL3_SetPolicy(). The ordering of cipher suites
- * in this table must match the ordering in SSL_ImplementedCiphers (sslenum.c)
- *
- * Important: See bug 946147 before enabling, reordering, or adding any cipher
- * suites to this list.
- */
-/* clang-format off */
-static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
-   /*      cipher_suite                     policy       enabled   isPresent */
-
-#ifndef NSS_DISABLE_ECC
- { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
- { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,   SSL_ALLOWED, PR_TRUE, PR_FALSE},
- { TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
- { TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,   SSL_ALLOWED, PR_TRUE, PR_FALSE},
-   /* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA is out of order to work around
-    * bug 946147.
-    */
- { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,    SSL_ALLOWED, PR_TRUE, PR_FALSE},
- { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,    SSL_ALLOWED, PR_TRUE, PR_FALSE},
- { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,      SSL_ALLOWED, PR_TRUE, PR_FALSE},
- { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
- { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,   SSL_ALLOWED, PR_TRUE, PR_FALSE},
- { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,      SSL_ALLOWED, PR_TRUE, PR_FALSE},
- { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,   SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,     SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,        SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDHE_RSA_WITH_RC4_128_SHA,          SSL_ALLOWED, PR_FALSE, PR_FALSE},
-#endif /* NSS_DISABLE_ECC */
-
- { TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,     SSL_ALLOWED, PR_TRUE,  PR_FALSE},
- { TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,SSL_ALLOWED,PR_TRUE,  PR_FALSE},
- { TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,     SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_DHE_RSA_WITH_AES_128_CBC_SHA,        SSL_ALLOWED, PR_TRUE,  PR_FALSE},
- { TLS_DHE_DSS_WITH_AES_128_CBC_SHA,        SSL_ALLOWED, PR_TRUE,  PR_FALSE},
- { TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,     SSL_ALLOWED, PR_TRUE,  PR_FALSE},
- { TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,     SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,   SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,   SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_DHE_RSA_WITH_AES_256_CBC_SHA,        SSL_ALLOWED, PR_TRUE,  PR_FALSE},
- { TLS_DHE_DSS_WITH_AES_256_CBC_SHA,        SSL_ALLOWED, PR_TRUE,  PR_FALSE},
- { TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,     SSL_ALLOWED, PR_TRUE,  PR_FALSE},
- { TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,     SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,   SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,   SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,       SSL_ALLOWED, PR_TRUE,  PR_FALSE},
- { TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,       SSL_ALLOWED, PR_TRUE,  PR_FALSE},
- { TLS_DHE_DSS_WITH_RC4_128_SHA,            SSL_ALLOWED, PR_FALSE, PR_FALSE},
-
-#ifndef NSS_DISABLE_ECC
- { TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,     SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,       SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,     SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,       SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,    SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,      SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDH_ECDSA_WITH_RC4_128_SHA,         SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDH_RSA_WITH_RC4_128_SHA,           SSL_ALLOWED, PR_FALSE, PR_FALSE},
-#endif /* NSS_DISABLE_ECC */
-
- /* RSA */
- { TLS_RSA_WITH_AES_128_GCM_SHA256,         SSL_ALLOWED, PR_TRUE,  PR_FALSE},
- { TLS_RSA_WITH_AES_128_CBC_SHA,            SSL_ALLOWED, PR_TRUE,  PR_FALSE},
- { TLS_RSA_WITH_AES_128_CBC_SHA256,         SSL_ALLOWED, PR_TRUE,  PR_FALSE},
- { TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,       SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_RSA_WITH_AES_256_CBC_SHA,            SSL_ALLOWED, PR_TRUE,  PR_FALSE},
- { TLS_RSA_WITH_AES_256_CBC_SHA256,         SSL_ALLOWED, PR_TRUE,  PR_FALSE},
- { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,       SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_RSA_WITH_SEED_CBC_SHA,               SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,      SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_RSA_WITH_3DES_EDE_CBC_SHA,           SSL_ALLOWED, PR_TRUE,  PR_FALSE},
- { TLS_RSA_WITH_RC4_128_SHA,                SSL_ALLOWED, PR_TRUE,  PR_FALSE},
- { TLS_RSA_WITH_RC4_128_MD5,                SSL_ALLOWED, PR_TRUE,  PR_FALSE},
-
- /* 56-bit DES "domestic" cipher suites */
- { TLS_DHE_RSA_WITH_DES_CBC_SHA,            SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_DHE_DSS_WITH_DES_CBC_SHA,            SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { SSL_RSA_FIPS_WITH_DES_CBC_SHA,           SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_RSA_WITH_DES_CBC_SHA,                SSL_ALLOWED, PR_FALSE, PR_FALSE},
-
- /* export ciphersuites with 1024-bit public key exchange keys */
- { TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,      SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,     SSL_ALLOWED, PR_FALSE, PR_FALSE},
-
- /* export ciphersuites with 512-bit public key exchange keys */
- { TLS_RSA_EXPORT_WITH_RC4_40_MD5,          SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,      SSL_ALLOWED, PR_FALSE, PR_FALSE},
-
- /* ciphersuites with no encryption */
-#ifndef NSS_DISABLE_ECC
- { TLS_ECDHE_ECDSA_WITH_NULL_SHA,           SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDHE_RSA_WITH_NULL_SHA,             SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDH_RSA_WITH_NULL_SHA,              SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDH_ECDSA_WITH_NULL_SHA,            SSL_ALLOWED, PR_FALSE, PR_FALSE},
-#endif /* NSS_DISABLE_ECC */
- { TLS_RSA_WITH_NULL_SHA,                   SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_RSA_WITH_NULL_SHA256,                SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_RSA_WITH_NULL_MD5,                   SSL_ALLOWED, PR_FALSE, PR_FALSE},
-};
-/* clang-format on */
-
-static const SSLSignatureAndHashAlg defaultSignatureAlgorithms[] = {
-    { ssl_hash_sha256, ssl_sign_rsa },
-    { ssl_hash_sha384, ssl_sign_rsa },
-    { ssl_hash_sha512, ssl_sign_rsa },
-    { ssl_hash_sha1, ssl_sign_rsa },
-#ifndef NSS_DISABLE_ECC
-    { ssl_hash_sha256, ssl_sign_ecdsa },
-    { ssl_hash_sha384, ssl_sign_ecdsa },
-    { ssl_hash_sha512, ssl_sign_ecdsa },
-    { ssl_hash_sha1, ssl_sign_ecdsa },
-#endif
-    { ssl_hash_sha256, ssl_sign_dsa },
-    { ssl_hash_sha1, ssl_sign_dsa }
-};
-PR_STATIC_ASSERT(PR_ARRAY_SIZE(defaultSignatureAlgorithms) <=
-                 MAX_SIGNATURE_ALGORITHMS);
-
-/* Verify that SSL_ImplementedCiphers and cipherSuites are in consistent order.
- */
-#ifdef DEBUG
-void
-ssl3_CheckCipherSuiteOrderConsistency()
-{
-    unsigned int i;
-
-    /* Note that SSL_ImplementedCiphers has more elements than cipherSuites
-     * because it SSL_ImplementedCiphers includes SSL 2.0 cipher suites.
-     */
-    PORT_Assert(SSL_NumImplementedCiphers >= PR_ARRAY_SIZE(cipherSuites));
-
-    for (i = 0; i < PR_ARRAY_SIZE(cipherSuites); ++i) {
-        PORT_Assert(SSL_ImplementedCiphers[i] == cipherSuites[i].cipher_suite);
-    }
-}
-#endif
-
-/* This list of SSL3 compression methods is sorted in descending order of
- * precedence (desirability).  It only includes compression methods we
- * implement.
- */
-static const /*SSLCompressionMethod*/ PRUint8 compressions[] = {
-#ifdef NSS_SSL_ENABLE_ZLIB
-    ssl_compression_deflate,
-#endif
-    ssl_compression_null
-};
-
-static const int compressionMethodsCount =
-    sizeof(compressions) / sizeof(compressions[0]);
-
-/* compressionEnabled returns true iff the compression algorithm is enabled
- * for the given SSL socket. */
-static PRBool
-compressionEnabled(sslSocket *ss, SSLCompressionMethod compression)
-{
-    switch (compression) {
-        case ssl_compression_null:
-            return PR_TRUE; /* Always enabled */
-#ifdef NSS_SSL_ENABLE_ZLIB
-        case ssl_compression_deflate:
-            if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-                return ss->opt.enableDeflate;
-            }
-            return PR_FALSE;
-#endif
-        default:
-            return PR_FALSE;
-    }
-}
-
-static const /*SSL3ClientCertificateType */ PRUint8 certificate_types[] = {
-    ct_RSA_sign,
-#ifndef NSS_DISABLE_ECC
-    ct_ECDSA_sign,
-#endif /* NSS_DISABLE_ECC */
-    ct_DSS_sign,
-};
-
-#define EXPORT_RSA_KEY_LENGTH 64 /* bytes */
-
-/* This global item is used only in servers.  It is is initialized by
-** SSL_ConfigSecureServer(), and is used in ssl3_SendCertificateRequest().
-*/
-CERTDistNames *ssl3_server_ca_list = NULL;
-static SSL3Statistics ssl3stats;
-
-/* indexed by SSL3BulkCipher */
-/* clang-format off */
-static const ssl3BulkCipherDef bulk_cipher_defs[] = {
-    /*                                       |--------- Lengths --------| */
-    /* cipher             calg               k  s  type         i  b  t  n o */
-    /*                                       e  e               v  l  a  o i */
-    /*                                       y  c               |  o  g  n d */
-    /*                                       |  r               |  c  |  c | */
-    /*                                       |  e               |  k  |  e | */
-    /*                                       |  t               |  |  |  | | */
-    {cipher_null,         calg_null,         0, 0, type_stream, 0, 0, 0, 0, SEC_OID_NULL_CIPHER},
-    {cipher_rc4,          calg_rc4,         16,16, type_stream, 0, 0, 0, 0, SEC_OID_RC4},
-    {cipher_rc4_40,       calg_rc4,         16, 5, type_stream, 0, 0, 0, 0, SEC_OID_RC4_40},
-    {cipher_rc4_56,       calg_rc4,         16, 7, type_stream, 0, 0, 0, 0, SEC_OID_RC4_56},
-    {cipher_rc2,          calg_rc2,         16,16, type_block,  8, 8, 0, 0, SEC_OID_RC2_CBC},
-    {cipher_rc2_40,       calg_rc2,         16, 5, type_block,  8, 8, 0, 0, SEC_OID_RC2_40_CBC},
-    {cipher_des,          calg_des,          8, 8, type_block,  8, 8, 0, 0, SEC_OID_DES_CBC},
-    {cipher_3des,         calg_3des,        24,24, type_block,  8, 8, 0, 0, SEC_OID_DES_EDE3_CBC},
-    {cipher_des40,        calg_des,          8, 5, type_block,  8, 8, 0, 0, SEC_OID_DES_40_CBC},
-    {cipher_idea,         calg_idea,        16,16, type_block,  8, 8, 0, 0, SEC_OID_IDEA_CBC},
-    {cipher_aes_128,      calg_aes,         16,16, type_block, 16,16, 0, 0, SEC_OID_AES_128_CBC},
-    {cipher_aes_256,      calg_aes,         32,32, type_block, 16,16, 0, 0, SEC_OID_AES_256_CBC},
-    {cipher_camellia_128, calg_camellia,    16,16, type_block, 16,16, 0, 0, SEC_OID_CAMELLIA_128_CBC},
-    {cipher_camellia_256, calg_camellia,    32,32, type_block, 16,16, 0, 0, SEC_OID_CAMELLIA_256_CBC},
-    {cipher_seed,         calg_seed,        16,16, type_block, 16,16, 0, 0, SEC_OID_SEED_CBC},
-    {cipher_aes_128_gcm,  calg_aes_gcm,     16,16, type_aead,   4, 0,16, 8, SEC_OID_AES_128_GCM},
-    {cipher_chacha20,     calg_chacha20,    32,32, type_aead,  12, 0,16, 0, SEC_OID_CHACHA20_POLY1305},
-    {cipher_missing,      calg_null,         0, 0, type_stream, 0, 0, 0, 0, 0},
-};
-
-static const ssl3KEADef kea_defs[] =
-{ /* indexed by SSL3KeyExchangeAlgorithm */
-    /* kea            exchKeyType signKeyType is_limited limit tls_keygen ephemeral  oid */
-    {kea_null,           kt_null, ssl_sign_null,  PR_FALSE,   0, PR_FALSE, PR_FALSE, 0},
-    {kea_rsa,            kt_rsa,  ssl_sign_rsa,   PR_FALSE,   0, PR_FALSE, PR_FALSE, SEC_OID_TLS_RSA},
-    {kea_rsa_export,     kt_rsa,  ssl_sign_rsa,   PR_TRUE,  512, PR_FALSE, PR_FALSE, SEC_OID_TLS_RSA_EXPORT},
-    {kea_rsa_export_1024,kt_rsa,  ssl_sign_rsa,   PR_TRUE, 1024, PR_FALSE, PR_FALSE, SEC_OID_TLS_RSA_EXPORT},
-    {kea_dh_dss,         kt_dh,   ssl_sign_dsa,   PR_FALSE,   0, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_DSS},
-    {kea_dh_dss_export,  kt_dh,   ssl_sign_dsa,   PR_TRUE,  512, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_DSS_EXPORT},
-    {kea_dh_rsa,         kt_dh,   ssl_sign_rsa,   PR_FALSE,   0, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_RSA},
-    {kea_dh_rsa_export,  kt_dh,   ssl_sign_rsa,   PR_TRUE,  512, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_RSA_EXPORT},
-    {kea_dhe_dss,        kt_dh,   ssl_sign_dsa,   PR_FALSE,   0, PR_FALSE, PR_TRUE,  SEC_OID_TLS_DHE_DSS},
-    {kea_dhe_dss_export, kt_dh,   ssl_sign_dsa,   PR_TRUE,  512, PR_FALSE, PR_TRUE,  SEC_OID_TLS_DHE_DSS_EXPORT},
-    {kea_dhe_rsa,        kt_dh,   ssl_sign_rsa,   PR_FALSE,   0, PR_FALSE, PR_TRUE,  SEC_OID_TLS_DHE_RSA},
-    {kea_dhe_rsa_export, kt_dh,   ssl_sign_rsa,   PR_TRUE,  512, PR_FALSE, PR_TRUE,  SEC_OID_TLS_DHE_RSA_EXPORT},
-    {kea_dh_anon,        kt_dh,   ssl_sign_null,  PR_FALSE,   0, PR_FALSE, PR_TRUE,  SEC_OID_TLS_DH_ANON},
-    {kea_dh_anon_export, kt_dh,   ssl_sign_null,  PR_TRUE,  512, PR_FALSE, PR_TRUE,  SEC_OID_TLS_DH_ANON_EXPORT},
-    {kea_rsa_fips,       kt_rsa,  ssl_sign_rsa,   PR_FALSE,   0, PR_TRUE,  PR_FALSE, SEC_OID_TLS_RSA},
-#ifndef NSS_DISABLE_ECC
-    {kea_ecdh_ecdsa,     kt_ecdh, ssl_sign_ecdsa, PR_FALSE,   0, PR_FALSE, PR_FALSE, SEC_OID_TLS_ECDH_ECDSA},
-    {kea_ecdhe_ecdsa,    kt_ecdh, ssl_sign_ecdsa, PR_FALSE,   0, PR_FALSE, PR_TRUE,  SEC_OID_TLS_ECDHE_ECDSA},
-    {kea_ecdh_rsa,       kt_ecdh, ssl_sign_rsa,   PR_FALSE,   0, PR_FALSE, PR_FALSE, SEC_OID_TLS_ECDH_RSA},
-    {kea_ecdhe_rsa,      kt_ecdh, ssl_sign_rsa,   PR_FALSE,   0, PR_FALSE, PR_TRUE,  SEC_OID_TLS_ECDHE_RSA},
-    {kea_ecdh_anon,      kt_ecdh, ssl_sign_null,  PR_FALSE,   0, PR_FALSE, PR_TRUE,  SEC_OID_TLS_ECDH_ANON},
-#endif /* NSS_DISABLE_ECC */
-};
-
-/* must use ssl_LookupCipherSuiteDef to access */
-static const ssl3CipherSuiteDef cipher_suite_defs[] =
-{
-/*  cipher_suite                    bulk_cipher_alg mac_alg key_exchange_alg */
-
-    {TLS_NULL_WITH_NULL_NULL,       cipher_null,   mac_null, kea_null},
-    {TLS_RSA_WITH_NULL_MD5,         cipher_null,   mac_md5, kea_rsa},
-    {TLS_RSA_WITH_NULL_SHA,         cipher_null,   mac_sha, kea_rsa},
-    {TLS_RSA_WITH_NULL_SHA256,      cipher_null,   hmac_sha256, kea_rsa},
-    {TLS_RSA_EXPORT_WITH_RC4_40_MD5,cipher_rc4_40, mac_md5, kea_rsa_export},
-    {TLS_RSA_WITH_RC4_128_MD5,      cipher_rc4,    mac_md5, kea_rsa},
-    {TLS_RSA_WITH_RC4_128_SHA,      cipher_rc4,    mac_sha, kea_rsa},
-    {TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
-                                    cipher_rc2_40, mac_md5, kea_rsa_export},
-#if 0 /* not implemented */
-    {TLS_RSA_WITH_IDEA_CBC_SHA,     cipher_idea,   mac_sha, kea_rsa},
-    {TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,
-                                    cipher_des40,  mac_sha, kea_rsa_export},
-#endif
-    {TLS_RSA_WITH_DES_CBC_SHA,      cipher_des,    mac_sha, kea_rsa},
-    {TLS_RSA_WITH_3DES_EDE_CBC_SHA, cipher_3des,   mac_sha, kea_rsa},
-    {TLS_DHE_DSS_WITH_DES_CBC_SHA,  cipher_des,    mac_sha, kea_dhe_dss},
-    {TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
-                                    cipher_3des,   mac_sha, kea_dhe_dss},
-    {TLS_DHE_DSS_WITH_RC4_128_SHA,  cipher_rc4,    mac_sha, kea_dhe_dss},
-#if 0 /* not implemented */
-    {TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
-                                    cipher_des40,  mac_sha, kea_dh_dss_export},
-    {TLS_DH_DSS_DES_CBC_SHA,        cipher_des,    mac_sha, kea_dh_dss},
-    {TLS_DH_DSS_3DES_CBC_SHA,       cipher_3des,   mac_sha, kea_dh_dss},
-    {TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
-                                    cipher_des40,  mac_sha, kea_dh_rsa_export},
-    {TLS_DH_RSA_DES_CBC_SHA,        cipher_des,    mac_sha, kea_dh_rsa},
-    {TLS_DH_RSA_3DES_CBC_SHA,       cipher_3des,   mac_sha, kea_dh_rsa},
-    {TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
-                                    cipher_des40,  mac_sha, kea_dh_dss_export},
-    {TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
-                                    cipher_des40,  mac_sha, kea_dh_rsa_export},
-#endif
-    {TLS_DHE_RSA_WITH_DES_CBC_SHA,  cipher_des,    mac_sha, kea_dhe_rsa},
-    {TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
-                                    cipher_3des,   mac_sha, kea_dhe_rsa},
-#if 0
-    {SSL_DH_ANON_EXPORT_RC4_40_MD5, cipher_rc4_40, mac_md5, kea_dh_anon_export},
-    {TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
-                                    cipher_des40,  mac_sha, kea_dh_anon_export},
-    {TLS_DH_anon_WITH_DES_CBC_SHA,  cipher_des,    mac_sha, kea_dh_anon},
-    {TLS_DH_anon_WITH_3DES_CBC_SHA, cipher_3des,   mac_sha, kea_dh_anon},
-#endif
-
-
-/* New TLS cipher suites */
-    {TLS_RSA_WITH_AES_128_CBC_SHA,      cipher_aes_128, mac_sha, kea_rsa},
-    {TLS_RSA_WITH_AES_128_CBC_SHA256,   cipher_aes_128, hmac_sha256, kea_rsa},
-    {TLS_DHE_DSS_WITH_AES_128_CBC_SHA,  cipher_aes_128, mac_sha, kea_dhe_dss},
-    {TLS_DHE_RSA_WITH_AES_128_CBC_SHA,  cipher_aes_128, mac_sha, kea_dhe_rsa},
-    {TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, cipher_aes_128, hmac_sha256, kea_dhe_rsa},
-    {TLS_RSA_WITH_AES_256_CBC_SHA,      cipher_aes_256, mac_sha, kea_rsa},
-    {TLS_RSA_WITH_AES_256_CBC_SHA256,   cipher_aes_256, hmac_sha256, kea_rsa},
-    {TLS_DHE_DSS_WITH_AES_256_CBC_SHA,  cipher_aes_256, mac_sha, kea_dhe_dss},
-    {TLS_DHE_RSA_WITH_AES_256_CBC_SHA,  cipher_aes_256, mac_sha, kea_dhe_rsa},
-    {TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, cipher_aes_256, hmac_sha256, kea_dhe_rsa},
-#if 0
-    {TLS_DH_DSS_WITH_AES_128_CBC_SHA,   cipher_aes_128, mac_sha, kea_dh_dss},
-    {TLS_DH_RSA_WITH_AES_128_CBC_SHA,   cipher_aes_128, mac_sha, kea_dh_rsa},
-    {TLS_DH_anon_WITH_AES_128_CBC_SHA,  cipher_aes_128, mac_sha, kea_dh_anon},
-    {TLS_DH_DSS_WITH_AES_256_CBC_SHA,   cipher_aes_256, mac_sha, kea_dh_dss},
-    {TLS_DH_RSA_WITH_AES_256_CBC_SHA,   cipher_aes_256, mac_sha, kea_dh_rsa},
-    {TLS_DH_anon_WITH_AES_256_CBC_SHA,  cipher_aes_256, mac_sha, kea_dh_anon},
-#endif
-
-    {TLS_RSA_WITH_SEED_CBC_SHA,     cipher_seed,   mac_sha, kea_rsa},
-
-    {TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, cipher_camellia_128, mac_sha, kea_rsa},
-    {TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
-     cipher_camellia_128, mac_sha, kea_dhe_dss},
-    {TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
-     cipher_camellia_128, mac_sha, kea_dhe_rsa},
-    {TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, cipher_camellia_256, mac_sha, kea_rsa},
-    {TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
-     cipher_camellia_256, mac_sha, kea_dhe_dss},
-    {TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
-     cipher_camellia_256, mac_sha, kea_dhe_rsa},
-
-    {TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,
-                                    cipher_des,    mac_sha,kea_rsa_export_1024},
-    {TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,
-                                    cipher_rc4_56, mac_sha,kea_rsa_export_1024},
-
-    {SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, kea_rsa_fips},
-    {SSL_RSA_FIPS_WITH_DES_CBC_SHA, cipher_des,    mac_sha, kea_rsa_fips},
-
-    {TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_dhe_rsa},
-    {TLS_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_rsa},
-    {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_ecdhe_rsa},
-    {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_ecdhe_ecdsa},
-
-    {TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_dhe_dss},
-    {TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, cipher_aes_128, hmac_sha256, kea_dhe_dss},
-    {TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, cipher_aes_256, hmac_sha256, kea_dhe_dss},
-
-    {TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, cipher_chacha20, mac_aead, kea_dhe_rsa},
-    {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, cipher_chacha20, mac_aead, kea_ecdhe_rsa},
-    {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, cipher_chacha20, mac_aead, kea_ecdhe_ecdsa},
-
-#ifndef NSS_DISABLE_ECC
-    {TLS_ECDH_ECDSA_WITH_NULL_SHA,        cipher_null, mac_sha, kea_ecdh_ecdsa},
-    {TLS_ECDH_ECDSA_WITH_RC4_128_SHA,      cipher_rc4, mac_sha, kea_ecdh_ecdsa},
-    {TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, kea_ecdh_ecdsa},
-    {TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_ecdh_ecdsa},
-    {TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_ecdh_ecdsa},
-
-    {TLS_ECDHE_ECDSA_WITH_NULL_SHA,        cipher_null, mac_sha, kea_ecdhe_ecdsa},
-    {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,      cipher_rc4, mac_sha, kea_ecdhe_ecdsa},
-    {TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, kea_ecdhe_ecdsa},
-    {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_ecdhe_ecdsa},
-    {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, cipher_aes_128, hmac_sha256, kea_ecdhe_ecdsa},
-    {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_ecdhe_ecdsa},
-
-    {TLS_ECDH_RSA_WITH_NULL_SHA,         cipher_null,    mac_sha, kea_ecdh_rsa},
-    {TLS_ECDH_RSA_WITH_RC4_128_SHA,      cipher_rc4,     mac_sha, kea_ecdh_rsa},
-    {TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, cipher_3des,    mac_sha, kea_ecdh_rsa},
-    {TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,  cipher_aes_128, mac_sha, kea_ecdh_rsa},
-    {TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,  cipher_aes_256, mac_sha, kea_ecdh_rsa},
-
-    {TLS_ECDHE_RSA_WITH_NULL_SHA,         cipher_null,    mac_sha, kea_ecdhe_rsa},
-    {TLS_ECDHE_RSA_WITH_RC4_128_SHA,      cipher_rc4,     mac_sha, kea_ecdhe_rsa},
-    {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, cipher_3des,    mac_sha, kea_ecdhe_rsa},
-    {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,  cipher_aes_128, mac_sha, kea_ecdhe_rsa},
-    {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, cipher_aes_128, hmac_sha256, kea_ecdhe_rsa},
-    {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,  cipher_aes_256, mac_sha, kea_ecdhe_rsa},
-
-#if 0
-    {TLS_ECDH_anon_WITH_NULL_SHA,         cipher_null,    mac_sha, kea_ecdh_anon},
-    {TLS_ECDH_anon_WITH_RC4_128_SHA,      cipher_rc4,     mac_sha, kea_ecdh_anon},
-    {TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, cipher_3des,    mac_sha, kea_ecdh_anon},
-    {TLS_ECDH_anon_WITH_AES_128_CBC_SHA,  cipher_aes_128, mac_sha, kea_ecdh_anon},
-    {TLS_ECDH_anon_WITH_AES_256_CBC_SHA,  cipher_aes_256, mac_sha, kea_ecdh_anon},
-#endif
-#endif /* NSS_DISABLE_ECC */
-};
-/* clang-format on */
-
-static const CK_MECHANISM_TYPE kea_alg_defs[] = {
-    0x80000000L,
-    CKM_RSA_PKCS,
-    CKM_DH_PKCS_DERIVE,
-    CKM_KEA_KEY_DERIVE,
-    CKM_ECDH1_DERIVE
-};
-
-typedef struct SSLCipher2MechStr {
-    SSLCipherAlgorithm calg;
-    CK_MECHANISM_TYPE cmech;
-} SSLCipher2Mech;
-
-/* indexed by type SSLCipherAlgorithm */
-static const SSLCipher2Mech alg2Mech[] = {
-    /* calg,          cmech  */
-    { calg_null, (CK_MECHANISM_TYPE)0x80000000L },
-    { calg_rc4, CKM_RC4 },
-    { calg_rc2, CKM_RC2_CBC },
-    { calg_des, CKM_DES_CBC },
-    { calg_3des, CKM_DES3_CBC },
-    { calg_idea, CKM_IDEA_CBC },
-    { calg_fortezza, CKM_SKIPJACK_CBC64 },
-    { calg_aes, CKM_AES_CBC },
-    { calg_camellia, CKM_CAMELLIA_CBC },
-    { calg_seed, CKM_SEED_CBC },
-    { calg_aes_gcm, CKM_AES_GCM },
-    { calg_chacha20, CKM_NSS_CHACHA20_POLY1305 },
-    /*  { calg_init     , (CK_MECHANISM_TYPE)0x7fffffffL    }  */
-};
-
-#define mmech_invalid (CK_MECHANISM_TYPE)0x80000000L
-#define mmech_md5 CKM_SSL3_MD5_MAC
-#define mmech_sha CKM_SSL3_SHA1_MAC
-#define mmech_md5_hmac CKM_MD5_HMAC
-#define mmech_sha_hmac CKM_SHA_1_HMAC
-#define mmech_sha256_hmac CKM_SHA256_HMAC
-
-/* clang-format off */
-static const ssl3MACDef mac_defs[] = { /* indexed by SSL3MACAlgorithm */
-    /* pad_size is only used for SSL 3.0 MAC. See RFC 6101 Sec. 5.2.3.1. */
-    /* mac      mmech       pad_size  mac_size                       */
-    { mac_null, mmech_invalid,    0,  0         ,  0},
-    { mac_md5,  mmech_md5,       48,  MD5_LENGTH,  SEC_OID_HMAC_MD5 },
-    { mac_sha,  mmech_sha,       40,  SHA1_LENGTH, SEC_OID_HMAC_SHA1},
-    {hmac_md5,  mmech_md5_hmac,   0,  MD5_LENGTH,  SEC_OID_HMAC_MD5},
-    {hmac_sha,  mmech_sha_hmac,   0,  SHA1_LENGTH, SEC_OID_HMAC_SHA1},
-    {hmac_sha256, mmech_sha256_hmac, 0, SHA256_LENGTH, SEC_OID_HMAC_SHA256},
-    { mac_aead, mmech_invalid,    0,  0, 0 },
-};
-/* clang-format on */
-
-/* indexed by SSL3BulkCipher */
-const char *const ssl3_cipherName[] = {
-    "NULL",
-    "RC4",
-    "RC4-40",
-    "RC4-56",
-    "RC2-CBC",
-    "RC2-CBC-40",
-    "DES-CBC",
-    "3DES-EDE-CBC",
-    "DES-CBC-40",
-    "IDEA-CBC",
-    "AES-128",
-    "AES-256",
-    "Camellia-128",
-    "Camellia-256",
-    "SEED-CBC",
-    "AES-128-GCM",
-    "missing"
-};
-
-const PRUint8 tls13_downgrade_random[] = { 0x44, 0x4F, 0x57, 0x4E,
-                                           0x47, 0x52, 0x44, 0x01 };
-const PRUint8 tls12_downgrade_random[] = { 0x44, 0x4F, 0x57, 0x4E,
-                                           0x47, 0x52, 0x44, 0x00 };
-
-#ifndef NSS_DISABLE_ECC
-/* The ECCWrappedKeyInfo structure defines how various pieces of
- * information are laid out within wrappedSymmetricWrappingkey
- * for ECDH key exchange. Since wrappedSymmetricWrappingkey is
- * a 512-byte buffer (see sslimpl.h), the variable length field
- * in ECCWrappedKeyInfo can be at most (512 - 8) = 504 bytes.
- *
- * XXX For now, NSS only supports named elliptic curves of size 571 bits
- * or smaller. The public value will fit within 145 bytes and EC params
- * will fit within 12 bytes. We'll need to revisit this when NSS
- * supports arbitrary curves.
- */
-#define MAX_EC_WRAPPED_KEY_BUFLEN 504
-
-typedef struct ECCWrappedKeyInfoStr {
-    PRUint16 size;                          /* EC public key size in bits */
-    PRUint16 encodedParamLen;               /* length (in bytes) of DER encoded EC params */
-    PRUint16 pubValueLen;                   /* length (in bytes) of EC public value */
-    PRUint16 wrappedKeyLen;                 /* length (in bytes) of the wrapped key */
-    PRUint8 var[MAX_EC_WRAPPED_KEY_BUFLEN]; /* this buffer contains the */
-    /* EC public-key params, the EC public value and the wrapped key  */
-} ECCWrappedKeyInfo;
-#endif /* NSS_DISABLE_ECC */
-
-CK_MECHANISM_TYPE
-ssl3_Alg2Mech(SSLCipherAlgorithm calg)
-{
-    PORT_Assert(alg2Mech[calg].calg == calg);
-    return alg2Mech[calg].cmech;
-}
-
-#if defined(TRACE)
-
-static char *
-ssl3_DecodeHandshakeType(int msgType)
-{
-    char *rv;
-    static char line[40];
-
-    switch (msgType) {
-        case hello_request:
-            rv = "hello_request (0)";
-            break;
-        case client_hello:
-            rv = "client_hello  (1)";
-            break;
-        case server_hello:
-            rv = "server_hello  (2)";
-            break;
-        case hello_verify_request:
-            rv = "hello_verify_request (3)";
-            break;
-        case encrypted_extensions:
-            rv = "encrypted_extensions (8)";
-            break;
-        case certificate:
-            rv = "certificate  (11)";
-            break;
-        case server_key_exchange:
-            rv = "server_key_exchange (12)";
-            break;
-        case certificate_request:
-            rv = "certificate_request (13)";
-            break;
-        case server_hello_done:
-            rv = "server_hello_done   (14)";
-            break;
-        case certificate_verify:
-            rv = "certificate_verify  (15)";
-            break;
-        case client_key_exchange:
-            rv = "client_key_exchange (16)";
-            break;
-        case finished:
-            rv = "finished     (20)";
-            break;
-        default:
-            sprintf(line, "*UNKNOWN* handshake type! (%d)", msgType);
-            rv = line;
-    }
-    return rv;
-}
-
-static char *
-ssl3_DecodeContentType(int msgType)
-{
-    char *rv;
-    static char line[40];
-
-    switch (msgType) {
-        case content_change_cipher_spec:
-            rv = "change_cipher_spec (20)";
-            break;
-        case content_alert:
-            rv = "alert      (21)";
-            break;
-        case content_handshake:
-            rv = "handshake  (22)";
-            break;
-        case content_application_data:
-            rv = "application_data (23)";
-            break;
-        default:
-            sprintf(line, "*UNKNOWN* record type! (%d)", msgType);
-            rv = line;
-    }
-    return rv;
-}
-
-#endif
-
-SSL3Statistics *
-SSL_GetStatistics(void)
-{
-    return &ssl3stats;
-}
-
-typedef struct tooLongStr {
-#if defined(IS_LITTLE_ENDIAN)
-    PRInt32 low;
-    PRInt32 high;
-#else
-    PRInt32 high;
-    PRInt32 low;
-#endif
-} tooLong;
-
-void
-SSL_AtomicIncrementLong(long *x)
-{
-    if ((sizeof *x) == sizeof(PRInt32)) {
-        PR_ATOMIC_INCREMENT((PRInt32 *)x);
-    } else {
-        tooLong *tl = (tooLong *)x;
-        if (PR_ATOMIC_INCREMENT(&tl->low) == 0)
-            PR_ATOMIC_INCREMENT(&tl->high);
-    }
-}
-
-static PRBool
-ssl3_CipherSuiteAllowedForVersionRange(
-    ssl3CipherSuite cipherSuite,
-    const SSLVersionRange *vrange)
-{
-    switch (cipherSuite) {
-        /* See RFC 4346 A.5. Export cipher suites must not be used in TLS 1.1 or
-         * later. This set of cipher suites is similar to, but different from, the
-         * set of cipher suites considered exportable by SSL_IsExportCipherSuite.
-         */
-        case TLS_RSA_EXPORT_WITH_RC4_40_MD5:
-        case TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
-            /*   TLS_RSA_EXPORT_WITH_DES40_CBC_SHA:      never implemented
-             *   TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:   never implemented
-             *   TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:   never implemented
-             *   TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:  never implemented
-             *   TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:  never implemented
-             *   TLS_DH_anon_EXPORT_WITH_RC4_40_MD5:     never implemented
-             *   TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA:  never implemented
-             */
-            return vrange->min <= SSL_LIBRARY_VERSION_TLS_1_0;
-
-        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
-        case TLS_RSA_WITH_AES_256_CBC_SHA256:
-        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
-        case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
-        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
-        case TLS_RSA_WITH_AES_128_CBC_SHA256:
-        case TLS_RSA_WITH_AES_128_GCM_SHA256:
-        case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
-        case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
-        case TLS_RSA_WITH_NULL_SHA256:
-        case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
-            return vrange->max == SSL_LIBRARY_VERSION_TLS_1_2;
-
-        case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
-        case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
-        case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
-            return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_2;
-
-        /* RFC 4492: ECC cipher suites need TLS extensions to negotiate curves and
-         * point formats.*/
-        case TLS_ECDH_ECDSA_WITH_NULL_SHA:
-        case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
-        case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
-        case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
-        case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
-        case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
-        case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
-        case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
-        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
-        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
-        case TLS_ECDH_RSA_WITH_NULL_SHA:
-        case TLS_ECDH_RSA_WITH_RC4_128_SHA:
-        case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
-        case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
-        case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
-        case TLS_ECDHE_RSA_WITH_NULL_SHA:
-        case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
-        case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
-        case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
-        case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
-            return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_0 &&
-                   vrange->min < SSL_LIBRARY_VERSION_TLS_1_3;
-
-        default:
-            return vrange->min < SSL_LIBRARY_VERSION_TLS_1_3;
-    }
-}
-
-/* return pointer to ssl3CipherSuiteDef for suite, or NULL */
-/* XXX This does a linear search.  A binary search would be better. */
-static const ssl3CipherSuiteDef *
-ssl_LookupCipherSuiteDef(ssl3CipherSuite suite)
-{
-    int cipher_suite_def_len =
-        sizeof(cipher_suite_defs) / sizeof(cipher_suite_defs[0]);
-    int i;
-
-    for (i = 0; i < cipher_suite_def_len; i++) {
-        if (cipher_suite_defs[i].cipher_suite == suite)
-            return &cipher_suite_defs[i];
-    }
-    PORT_Assert(PR_FALSE); /* We should never get here. */
-    PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
-    return NULL;
-}
-
-/* Find the cipher configuration struct associate with suite */
-/* XXX This does a linear search.  A binary search would be better. */
-static ssl3CipherSuiteCfg *
-ssl_LookupCipherSuiteCfg(ssl3CipherSuite suite, ssl3CipherSuiteCfg *suites)
-{
-    int i;
-
-    for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
-        if (suites[i].cipher_suite == suite)
-            return &suites[i];
-    }
-    /* return NULL and let the caller handle it.  */
-    PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
-    return NULL;
-}
-
-/* Initialize the suite->isPresent value for config_match
- * Returns count of enabled ciphers supported by extant tokens,
- * regardless of policy or user preference.
- * If this returns zero, the user cannot do SSL v3.
- */
-int
-ssl3_config_match_init(sslSocket *ss)
-{
-    ssl3CipherSuiteCfg *suite;
-    const ssl3CipherSuiteDef *cipher_def;
-    SSLCipherAlgorithm cipher_alg;
-    CK_MECHANISM_TYPE cipher_mech;
-    SSL3KEAType exchKeyType;
-    int i;
-    int numPresent = 0;
-    int numEnabled = 0;
-    PRBool isServer;
-    sslServerCerts *svrAuth;
-
-    PORT_Assert(ss);
-    if (!ss) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return 0;
-    }
-    if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
-        return 0;
-    }
-    isServer = (PRBool)(ss->sec.isServer != 0);
-
-    for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
-        suite = &ss->cipherSuites[i];
-        if (suite->enabled) {
-            ++numEnabled;
-            /* We need the cipher defs to see if we have a token that can handle
-             * this cipher.  It isn't part of the static definition.
-             */
-            cipher_def = ssl_LookupCipherSuiteDef(suite->cipher_suite);
-            if (!cipher_def) {
-                suite->isPresent = PR_FALSE;
-                continue;
-            }
-            cipher_alg = bulk_cipher_defs[cipher_def->bulk_cipher_alg].calg;
-            cipher_mech = ssl3_Alg2Mech(cipher_alg);
-            exchKeyType =
-                kea_defs[cipher_def->key_exchange_alg].exchKeyType;
-#ifdef NSS_DISABLE_ECC
-            svrAuth = ss->serverCerts + exchKeyType;
-#else
-            /* XXX SSLKEAType isn't really a good choice for
-             * indexing certificates. It doesn't work for
-             * (EC)DHE-* ciphers. Here we use a hack to ensure
-             * that the server uses an RSA cert for (EC)DHE-RSA.
-             */
-            switch (cipher_def->key_exchange_alg) {
-                case kea_dhe_dss:
-                    svrAuth = ss->serverCerts + ssl_kea_dh;
-                    break;
-                case kea_ecdhe_rsa:
-                case kea_dhe_rsa:
-                    svrAuth = ss->serverCerts + kt_rsa;
-                    break;
-                case kea_ecdh_ecdsa:
-                case kea_ecdh_rsa:
-                /*
-                 * XXX We ought to have different indices for
-                 * ECDSA- and RSA-signed EC certificates so
-                 * we could support both key exchange mechanisms
-                 * simultaneously. For now, both of them use
-                 * whatever is in the certificate slot for kt_ecdh
-                 */
-                case kea_dhe_dss_export:
-                case kea_dhe_rsa_export:
-                default:
-                    svrAuth = ss->serverCerts + exchKeyType;
-                    break;
-            }
-#endif /* NSS_DISABLE_ECC */
-
-            /* Mark the suites that are backed by real tokens, certs and keys */
-            suite->isPresent = (PRBool)(((exchKeyType == kt_null) ||
-                                         ((!isServer ||
-                                           (svrAuth->serverKeyPair && svrAuth->SERVERKEY &&
-                                            svrAuth->serverCertChain)) &&
-                                          PK11_TokenExists(kea_alg_defs[exchKeyType]))) &&
-                                        ((cipher_alg == calg_null) || PK11_TokenExists(cipher_mech)));
-            if (suite->isPresent)
-                ++numPresent;
-        }
-    }
-    PORT_Assert(numPresent > 0 || numEnabled == 0);
-    if (numPresent <= 0) {
-        PORT_SetError(SSL_ERROR_NO_CIPHERS_SUPPORTED);
-    }
-    return numPresent;
-}
-
-/* return PR_TRUE if suite matches policy, enabled state and is applicable to
- * the given version range. */
-/* It would be a REALLY BAD THING (tm) if we ever permitted the use
-** of a cipher that was NOT_ALLOWED.  So, if this is ever called with
-** policy == SSL_NOT_ALLOWED, report no match.
-*/
-/* adjust suite enabled to the availability of a token that can do the
- * cipher suite. */
-static PRBool
-config_match(ssl3CipherSuiteCfg *suite, int policy, PRBool enabled,
-             const SSLVersionRange *vrange, const sslSocket *ss)
-{
-    const ssl3CipherSuiteDef *cipher_def;
-
-    PORT_Assert(policy != SSL_NOT_ALLOWED && enabled != PR_FALSE);
-    if (policy == SSL_NOT_ALLOWED || !enabled)
-        return PR_FALSE;
-
-    cipher_def = ssl_LookupCipherSuiteDef(suite->cipher_suite);
-    PORT_Assert(cipher_def != NULL);
-
-    PORT_Assert(ss != NULL);
-    if (ss->sec.isServer && !ss->opt.enableServerDhe &&
-        kea_defs[cipher_def->key_exchange_alg].exchKeyType == ssl_kea_dh)
-        return PR_FALSE;
-
-    return (PRBool)(suite->enabled &&
-                    suite->isPresent &&
-                    suite->policy != SSL_NOT_ALLOWED &&
-                    suite->policy <= policy &&
-                    ssl3_CipherSuiteAllowedForVersionRange(
-                        suite->cipher_suite, vrange));
-}
-
-/* return number of cipher suites that match policy, enabled state and are
- * applicable for the configured protocol version range. */
-/* called from ssl3_SendClientHello and ssl3_ConstructV2CipherSpecsHack */
-static int
-count_cipher_suites(sslSocket *ss, int policy, PRBool enabled)
-{
-    int i, count = 0;
-
-    if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
-        return 0;
-    }
-    for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
-        if (config_match(&ss->cipherSuites[i], policy, enabled, &ss->vrange, ss))
-            count++;
-    }
-    if (count <= 0) {
-        PORT_SetError(SSL_ERROR_SSL_DISABLED);
-    }
-    return count;
-}
-
-/*
- * Null compression, mac and encryption functions
- */
-
-static SECStatus
-Null_Cipher(void *ctx, unsigned char *output, int *outputLen, int maxOutputLen,
-            const unsigned char *input, int inputLen)
-{
-    if (inputLen > maxOutputLen) {
-        *outputLen = 0; /* Match PK11_CipherOp in setting outputLen */
-        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
-        return SECFailure;
-    }
-    *outputLen = inputLen;
-    if (input != output)
-        PORT_Memcpy(output, input, inputLen);
-    return SECSuccess;
-}
-
-/*
- * SSL3 Utility functions
- */
-
-/* allowLargerPeerVersion controls whether the function will select the
- * highest enabled SSL version or fail when peerVersion is greater than the
- * highest enabled version.
- *
- * If allowLargerPeerVersion is true, peerVersion is the peer's highest
- * enabled version rather than the peer's selected version.
- */
-SECStatus
-ssl3_NegotiateVersion(sslSocket *ss, SSL3ProtocolVersion peerVersion,
-                      PRBool allowLargerPeerVersion)
-{
-    if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
-        PORT_SetError(SSL_ERROR_SSL_DISABLED);
-        return SECFailure;
-    }
-
-    if (peerVersion < ss->vrange.min ||
-        (peerVersion > ss->vrange.max && !allowLargerPeerVersion)) {
-        PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
-        return SECFailure;
-    }
-
-    ss->version = PR_MIN(peerVersion, ss->vrange.max);
-    PORT_Assert(ssl3_VersionIsSupported(ss->protocolVariant, ss->version));
-
-    return SECSuccess;
-}
-
-static SECStatus
-ssl3_GetNewRandom(SSL3Random *random)
-{
-    SECStatus rv;
-
-    rv = PK11_GenerateRandom(random->rand, SSL3_RANDOM_LENGTH);
-    if (rv != SECSuccess) {
-        ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE);
-    }
-    return rv;
-}
-
-/* Called by ssl3_SendServerKeyExchange and ssl3_SendCertificateVerify */
-SECStatus
-ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, SECItem *buf,
-                PRBool isTLS)
-{
-    SECStatus rv = SECFailure;
-    PRBool doDerEncode = PR_FALSE;
-    int signatureLen;
-    SECItem hashItem;
-
-    buf->data = NULL;
-
-    switch (key->keyType) {
-        case rsaKey:
-            hashItem.data = hash->u.raw;
-            hashItem.len = hash->len;
-            break;
-        case dsaKey:
-            doDerEncode = isTLS;
-            /* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
-             * In that case, we use just the SHA1 part. */
-            if (hash->hashAlg == ssl_hash_none) {
-                hashItem.data = hash->u.s.sha;
-                hashItem.len = sizeof(hash->u.s.sha);
-            } else {
-                hashItem.data = hash->u.raw;
-                hashItem.len = hash->len;
-            }
-            break;
-#ifndef NSS_DISABLE_ECC
-        case ecKey:
-            doDerEncode = PR_TRUE;
-            /* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
-             * In that case, we use just the SHA1 part. */
-            if (hash->hashAlg == ssl_hash_none) {
-                hashItem.data = hash->u.s.sha;
-                hashItem.len = sizeof(hash->u.s.sha);
-            } else {
-                hashItem.data = hash->u.raw;
-                hashItem.len = hash->len;
-            }
-            break;
-#endif /* NSS_DISABLE_ECC */
-        default:
-            PORT_SetError(SEC_ERROR_INVALID_KEY);
-            goto done;
-    }
-    PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len));
-
-    if (hash->hashAlg == ssl_hash_none) {
-        signatureLen = PK11_SignatureLen(key);
-        if (signatureLen <= 0) {
-            PORT_SetError(SEC_ERROR_INVALID_KEY);
-            goto done;
-        }
-
-        buf->len = (unsigned)signatureLen;
-        buf->data = (unsigned char *)PORT_Alloc(signatureLen);
-        if (!buf->data)
-            goto done; /* error code was set. */
-
-        rv = PK11_Sign(key, buf, &hashItem);
-    } else {
-        SECOidTag hashOID = ssl3_TLSHashAlgorithmToOID(hash->hashAlg);
-        rv = SGN_Digest(key, hashOID, buf, &hashItem);
-    }
-    if (rv != SECSuccess) {
-        ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE);
-    } else if (doDerEncode) {
-        SECItem derSig = { siBuffer, NULL, 0 };
-
-        /* This also works for an ECDSA signature */
-        rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len);
-        if (rv == SECSuccess) {
-            PORT_Free(buf->data); /* discard unencoded signature. */
-            *buf = derSig;        /* give caller encoded signature. */
-        } else if (derSig.data) {
-            PORT_Free(derSig.data);
-        }
-    }
-
-    PRINT_BUF(60, (NULL, "signed hashes", (unsigned char *)buf->data, buf->len));
-done:
-    if (rv != SECSuccess && buf->data) {
-        PORT_Free(buf->data);
-        buf->data = NULL;
-    }
-    return rv;
-}
-
-/* Called from ssl3_HandleServerKeyExchange, ssl3_HandleCertificateVerify */
-SECStatus
-ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert,
-                        SECItem *buf, PRBool isTLS, void *pwArg)
-{
-    SECKEYPublicKey *key;
-    SECItem *signature = NULL;
-    SECStatus rv;
-    SECItem hashItem;
-    SECOidTag encAlg;
-    SECOidTag hashAlg;
-
-    PRINT_BUF(60, (NULL, "check signed hashes",
-                   buf->data, buf->len));
-
-    key = CERT_ExtractPublicKey(cert);
-    if (key == NULL) {
-        ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
-        return SECFailure;
-    }
-
-    hashAlg = ssl3_TLSHashAlgorithmToOID(hash->hashAlg);
-    switch (key->keyType) {
-        case rsaKey:
-            encAlg = SEC_OID_PKCS1_RSA_ENCRYPTION;
-            hashItem.data = hash->u.raw;
-            hashItem.len = hash->len;
-            break;
-        case dsaKey:
-            encAlg = SEC_OID_ANSIX9_DSA_SIGNATURE;
-            /* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
-             * In that case, we use just the SHA1 part. */
-            if (hash->hashAlg == ssl_hash_none) {
-                hashItem.data = hash->u.s.sha;
-                hashItem.len = sizeof(hash->u.s.sha);
-            } else {
-                hashItem.data = hash->u.raw;
-                hashItem.len = hash->len;
-            }
-            /* Allow DER encoded DSA signatures in SSL 3.0 */
-            if (isTLS || buf->len != SECKEY_SignatureLen(key)) {
-                signature = DSAU_DecodeDerSigToLen(buf, SECKEY_SignatureLen(key));
-                if (!signature) {
-                    PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
-                    return SECFailure;
-                }
-                buf = signature;
-            }
-            break;
-
-#ifndef NSS_DISABLE_ECC
-        case ecKey:
-            encAlg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
-            /* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
-             * In that case, we use just the SHA1 part.
-             * ECDSA signatures always encode the integers r and s using ASN.1
-             * (unlike DSA where ASN.1 encoding is used with TLS but not with
-             * SSL3). So we can use VFY_VerifyDigestDirect for ECDSA.
-             */
-            if (hash->hashAlg == ssl_hash_none) {
-                hashAlg = SEC_OID_SHA1;
-                hashItem.data = hash->u.s.sha;
-                hashItem.len = sizeof(hash->u.s.sha);
-            } else {
-                hashItem.data = hash->u.raw;
-                hashItem.len = hash->len;
-            }
-            break;
-#endif /* NSS_DISABLE_ECC */
-
-        default:
-            SECKEY_DestroyPublicKey(key);
-            PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
-            return SECFailure;
-    }
-
-    PRINT_BUF(60, (NULL, "hash(es) to be verified",
-                   hashItem.data, hashItem.len));
-
-    if (hashAlg == SEC_OID_UNKNOWN || key->keyType == dsaKey) {
-        /* VFY_VerifyDigestDirect requires DSA signatures to be DER-encoded.
-         * DSA signatures are DER-encoded in TLS but not in SSL3 and the code
-         * above always removes the DER encoding of DSA signatures when
-         * present. Thus DSA signatures are always verified with PK11_Verify.
-         */
-        rv = PK11_Verify(key, buf, &hashItem, pwArg);
-    } else {
-        rv = VFY_VerifyDigestDirect(&hashItem, key, buf, encAlg, hashAlg,
-                                    pwArg);
-    }
-    SECKEY_DestroyPublicKey(key);
-    if (signature) {
-        SECITEM_FreeItem(signature, PR_TRUE);
-    }
-    if (rv != SECSuccess) {
-        ssl_MapLowLevelError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
-    }
-    return rv;
-}
-
-/* Caller must set hiLevel error code. */
-/* Called from ssl3_ComputeExportRSAKeyHash
- *             ssl3_ComputeDHKeyHash
- * which are called from ssl3_HandleServerKeyExchange.
- *
- * hashAlg: ssl_hash_none indicates the pre-1.2, MD5/SHA1 combination hash.
- */
-SECStatus
-ssl3_ComputeCommonKeyHash(SSLHashType hashAlg,
-                          PRUint8 *hashBuf, unsigned int bufLen,
-                          SSL3Hashes *hashes, PRBool bypassPKCS11)
-{
-    SECStatus rv;
-    SECOidTag hashOID;
-
-#ifndef NO_PKCS11_BYPASS
-    if (bypassPKCS11) {
-        if (hashAlg == ssl_hash_none) {
-            MD5_HashBuf(hashes->u.s.md5, hashBuf, bufLen);
-            SHA1_HashBuf(hashes->u.s.sha, hashBuf, bufLen);
-            hashes->len = MD5_LENGTH + SHA1_LENGTH;
-        } else if (hashAlg == ssl_hash_sha1) {
-            SHA1_HashBuf(hashes->u.raw, hashBuf, bufLen);
-            hashes->len = SHA1_LENGTH;
-        } else if (hashAlg == ssl_hash_sha256) {
-            SHA256_HashBuf(hashes->u.raw, hashBuf, bufLen);
-            hashes->len = SHA256_LENGTH;
-        } else if (hashAlg == ssl_hash_sha384) {
-            SHA384_HashBuf(hashes->u.raw, hashBuf, bufLen);
-            hashes->len = SHA384_LENGTH;
-        } else if (hashAlg == ssl_hash_sha512) {
-            SHA512_HashBuf(hashes->u.raw, hashBuf, bufLen);
-            hashes->len = SHA512_LENGTH;
-        } else {
-            PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
-            return SECFailure;
-        }
-    } else
-#endif
-    {
-        if (hashAlg == ssl_hash_none) {
-            rv = PK11_HashBuf(SEC_OID_MD5, hashes->u.s.md5, hashBuf, bufLen);
-            if (rv != SECSuccess) {
-                ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
-                return rv;
-            }
-            rv = PK11_HashBuf(SEC_OID_SHA1, hashes->u.s.sha, hashBuf, bufLen);
-            if (rv != SECSuccess) {
-                ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
-                return rv;
-            }
-            hashes->len = MD5_LENGTH + SHA1_LENGTH;
-        } else {
-            hashOID = ssl3_TLSHashAlgorithmToOID(hashAlg);
-            hashes->len = HASH_ResultLenByOidTag(hashOID);
-            if (hashes->len == 0 || hashes->len > sizeof(hashes->u.raw)) {
-                ssl_MapLowLevelError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
-                return SECFailure;
-            }
-            rv = PK11_HashBuf(hashOID, hashes->u.raw, hashBuf, bufLen);
-            if (rv != SECSuccess) {
-                ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
-                return rv;
-            }
-        }
-    }
-    hashes->hashAlg = hashAlg;
-    return SECSuccess;
-}
-
-/* Caller must set hiLevel error code.
-** Called from ssl3_SendServerKeyExchange and
-**             ssl3_HandleServerKeyExchange.
-*/
-static SECStatus
-ssl3_ComputeExportRSAKeyHash(SSLHashType hashAlg,
-                             SECItem modulus, SECItem publicExponent,
-                             SSL3Random *client_rand, SSL3Random *server_rand,
-                             SSL3Hashes *hashes, PRBool bypassPKCS11)
-{
-    PRUint8 *hashBuf;
-    PRUint8 *pBuf;
-    SECStatus rv = SECSuccess;
-    unsigned int bufLen;
-    PRUint8 buf[2 * SSL3_RANDOM_LENGTH + 2 + 4096 / 8 + 2 + 4096 / 8];
-
-    bufLen = 2 * SSL3_RANDOM_LENGTH + 2 + modulus.len + 2 + publicExponent.len;
-    if (bufLen <= sizeof buf) {
-        hashBuf = buf;
-    } else {
-        hashBuf = PORT_Alloc(bufLen);
-        if (!hashBuf) {
-            return SECFailure;
-        }
-    }
-
-    memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH);
-    pBuf = hashBuf + SSL3_RANDOM_LENGTH;
-    memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH);
-    pBuf += SSL3_RANDOM_LENGTH;
-    pBuf[0] = (PRUint8)(modulus.len >> 8);
-    pBuf[1] = (PRUint8)(modulus.len);
-    pBuf += 2;
-    memcpy(pBuf, modulus.data, modulus.len);
-    pBuf += modulus.len;
-    pBuf[0] = (PRUint8)(publicExponent.len >> 8);
-    pBuf[1] = (PRUint8)(publicExponent.len);
-    pBuf += 2;
-    memcpy(pBuf, publicExponent.data, publicExponent.len);
-    pBuf += publicExponent.len;
-    PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);
-
-    rv = ssl3_ComputeCommonKeyHash(hashAlg, hashBuf, bufLen, hashes,
-                                   bypassPKCS11);
-
-    PRINT_BUF(95, (NULL, "RSAkey hash: ", hashBuf, bufLen));
-    if (hashAlg == ssl_hash_none) {
-        PRINT_BUF(95, (NULL, "RSAkey hash: MD5 result",
-                       hashes->u.s.md5, MD5_LENGTH));
-        PRINT_BUF(95, (NULL, "RSAkey hash: SHA1 result",
-                       hashes->u.s.sha, SHA1_LENGTH));
-    } else {
-        PRINT_BUF(95, (NULL, "RSAkey hash: result",
-                       hashes->u.raw, hashes->len));
-    }
-
-    if (hashBuf != buf && hashBuf != NULL)
-        PORT_Free(hashBuf);
-    return rv;
-}
-
-/* Caller must set hiLevel error code. */
-/* Called from ssl3_HandleServerKeyExchange. */
-static SECStatus
-ssl3_ComputeDHKeyHash(SSLHashType hashAlg,
-                      SECItem dh_p, SECItem dh_g, SECItem dh_Ys,
-                      SSL3Random *client_rand, SSL3Random *server_rand,
-                      SSL3Hashes *hashes, PRBool bypassPKCS11)
-{
-    PRUint8 *hashBuf;
-    PRUint8 *pBuf;
-    SECStatus rv = SECSuccess;
-    unsigned int bufLen;
-    PRUint8 buf[2 * SSL3_RANDOM_LENGTH + 2 + 4096 / 8 + 2 + 4096 / 8];
-
-    bufLen = 2 * SSL3_RANDOM_LENGTH + 2 + dh_p.len + 2 + dh_g.len + 2 + dh_Ys.len;
-    if (bufLen <= sizeof buf) {
-        hashBuf = buf;
-    } else {
-        hashBuf = PORT_Alloc(bufLen);
-        if (!hashBuf) {
-            return SECFailure;
-        }
-    }
-
-    memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH);
-    pBuf = hashBuf + SSL3_RANDOM_LENGTH;
-    memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH);
-    pBuf += SSL3_RANDOM_LENGTH;
-    pBuf[0] = (PRUint8)(dh_p.len >> 8);
-    pBuf[1] = (PRUint8)(dh_p.len);
-    pBuf += 2;
-    memcpy(pBuf, dh_p.data, dh_p.len);
-    pBuf += dh_p.len;
-    pBuf[0] = (PRUint8)(dh_g.len >> 8);
-    pBuf[1] = (PRUint8)(dh_g.len);
-    pBuf += 2;
-    memcpy(pBuf, dh_g.data, dh_g.len);
-    pBuf += dh_g.len;
-    pBuf[0] = (PRUint8)(dh_Ys.len >> 8);
-    pBuf[1] = (PRUint8)(dh_Ys.len);
-    pBuf += 2;
-    memcpy(pBuf, dh_Ys.data, dh_Ys.len);
-    pBuf += dh_Ys.len;
-    PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);
-
-    rv = ssl3_ComputeCommonKeyHash(hashAlg, hashBuf, bufLen, hashes,
-                                   bypassPKCS11);
-
-    PRINT_BUF(95, (NULL, "DHkey hash: ", hashBuf, bufLen));
-    if (hashAlg == ssl_hash_none) {
-        PRINT_BUF(95, (NULL, "DHkey hash: MD5 result",
-                       hashes->u.s.md5, MD5_LENGTH));
-        PRINT_BUF(95, (NULL, "DHkey hash: SHA1 result",
-                       hashes->u.s.sha, SHA1_LENGTH));
-    } else {
-        PRINT_BUF(95, (NULL, "DHkey hash: result",
-                       hashes->u.raw, hashes->len));
-    }
-
-    if (hashBuf != buf && hashBuf != NULL)
-        PORT_Free(hashBuf);
-    return rv;
-}
-
-void
-ssl3_BumpSequenceNumber(SSL3SequenceNumber *num)
-{
-    num->low++;
-    if (num->low == 0)
-        num->high++;
-}
-
-/* Called twice, only from ssl3_DestroyCipherSpec (immediately below). */
-static void
-ssl3_CleanupKeyMaterial(ssl3KeyMaterial *mat)
-{
-    if (mat->write_key != NULL) {
-        PK11_FreeSymKey(mat->write_key);
-        mat->write_key = NULL;
-    }
-    if (mat->write_mac_key != NULL) {
-        PK11_FreeSymKey(mat->write_mac_key);
-        mat->write_mac_key = NULL;
-    }
-    if (mat->write_mac_context != NULL) {
-        PK11_DestroyContext(mat->write_mac_context, PR_TRUE);
-        mat->write_mac_context = NULL;
-    }
-}
-
-/* Called from ssl3_SendChangeCipherSpecs() and
-**         ssl3_HandleChangeCipherSpecs()
-**             ssl3_DestroySSL3Info
-** Caller must hold SpecWriteLock.
-*/
-void
-ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName)
-{
-    PRBool freeit = (PRBool)(!spec->bypassCiphers);
-    /*  PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); Don't have ss! */
-    if (spec->destroy) {
-        spec->destroy(spec->encodeContext, freeit);
-        spec->destroy(spec->decodeContext, freeit);
-        spec->encodeContext = NULL; /* paranoia */
-        spec->decodeContext = NULL;
-    }
-    if (spec->destroyCompressContext && spec->compressContext) {
-        spec->destroyCompressContext(spec->compressContext, 1);
-        spec->compressContext = NULL;
-    }
-    if (spec->destroyDecompressContext && spec->decompressContext) {
-        spec->destroyDecompressContext(spec->decompressContext, 1);
-        spec->decompressContext = NULL;
-    }
-    if (freeSrvName && spec->srvVirtName.data) {
-        SECITEM_FreeItem(&spec->srvVirtName, PR_FALSE);
-    }
-    if (spec->master_secret != NULL) {
-        PK11_FreeSymKey(spec->master_secret);
-        spec->master_secret = NULL;
-    }
-    spec->msItem.data = NULL;
-    spec->msItem.len = 0;
-    ssl3_CleanupKeyMaterial(&spec->client);
-    ssl3_CleanupKeyMaterial(&spec->server);
-    spec->bypassCiphers = PR_FALSE;
-    spec->destroy = NULL;
-    spec->destroyCompressContext = NULL;
-    spec->destroyDecompressContext = NULL;
-}
-
-/* Fill in the pending cipher spec with info from the selected ciphersuite.
-** This is as much initialization as we can do without having key material.
-** Called from ssl3_HandleServerHello(), ssl3_SendServerHello()
-** Caller must hold the ssl3 handshake lock.
-** Acquires & releases SpecWriteLock.
-*/
-SECStatus
-ssl3_SetupPendingCipherSpec(sslSocket *ss)
-{
-    ssl3CipherSpec *pwSpec;
-    ssl3CipherSpec *cwSpec;
-    ssl3CipherSuite suite = ss->ssl3.hs.cipher_suite;
-    SSL3MACAlgorithm mac;
-    SSL3BulkCipher cipher;
-    SSL3KeyExchangeAlgorithm kea;
-    const ssl3CipherSuiteDef *suite_def;
-    PRBool isTLS;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    ssl_GetSpecWriteLock(ss); /*******************************/
-
-    pwSpec = ss->ssl3.pwSpec;
-    PORT_Assert(pwSpec == ss->ssl3.prSpec);
-
-    /* This hack provides maximal interoperability with SSL 3 servers. */
-    cwSpec = ss->ssl3.cwSpec;
-    if (cwSpec->mac_def->mac == mac_null) {
-        /* SSL records are not being MACed. */
-        cwSpec->version = ss->version;
-    }
-
-    pwSpec->version = ss->version;
-    isTLS = (PRBool)(pwSpec->version > SSL_LIBRARY_VERSION_3_0);
-
-    SSL_TRC(3, ("%d: SSL3[%d]: Set XXX Pending Cipher Suite to 0x%04x",
-                SSL_GETPID(), ss->fd, suite));
-
-    suite_def = ssl_LookupCipherSuiteDef(suite);
-    if (suite_def == NULL) {
-        ssl_ReleaseSpecWriteLock(ss);
-        return SECFailure; /* error code set by ssl_LookupCipherSuiteDef */
-    }
-
-    if (IS_DTLS(ss)) {
-        /* Double-check that we did not pick an RC4 suite */
-        PORT_Assert((suite_def->bulk_cipher_alg != cipher_rc4) &&
-                    (suite_def->bulk_cipher_alg != cipher_rc4_40) &&
-                    (suite_def->bulk_cipher_alg != cipher_rc4_56));
-    }
-
-    cipher = suite_def->bulk_cipher_alg;
-    kea = suite_def->key_exchange_alg;
-    mac = suite_def->mac_alg;
-    if (mac <= ssl_mac_sha && mac != ssl_mac_null && isTLS)
-        mac += 2;
-
-    ss->ssl3.hs.suite_def = suite_def;
-    ss->ssl3.hs.kea_def = &kea_defs[kea];
-    PORT_Assert(ss->ssl3.hs.kea_def->kea == kea);
-
-    pwSpec->cipher_def = &bulk_cipher_defs[cipher];
-    PORT_Assert(pwSpec->cipher_def->cipher == cipher);
-
-    pwSpec->mac_def = &mac_defs[mac];
-    PORT_Assert(pwSpec->mac_def->mac == mac);
-
-    ss->sec.keyBits = pwSpec->cipher_def->key_size * BPB;
-    ss->sec.secretKeyBits = pwSpec->cipher_def->secret_key_size * BPB;
-    ss->sec.cipherType = cipher;
-
-    pwSpec->encodeContext = NULL;
-    pwSpec->decodeContext = NULL;
-
-    pwSpec->mac_size = pwSpec->mac_def->mac_size;
-
-    pwSpec->compression_method = ss->ssl3.hs.compression;
-    pwSpec->compressContext = NULL;
-    pwSpec->decompressContext = NULL;
-
-    if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
-        PORT_Assert(ss->ssl3.hs.kea_def->ephemeral);
-        PORT_Assert(pwSpec->cipher_def->type == type_aead);
-    }
-    ssl_ReleaseSpecWriteLock(ss); /*******************************/
-    return SECSuccess;
-}
-
-#ifdef NSS_SSL_ENABLE_ZLIB
-#define SSL3_DEFLATE_CONTEXT_SIZE sizeof(z_stream)
-
-static SECStatus
-ssl3_MapZlibError(int zlib_error)
-{
-    switch (zlib_error) {
-        case Z_OK:
-            return SECSuccess;
-        default:
-            return SECFailure;
-    }
-}
-
-static SECStatus
-ssl3_DeflateInit(void *void_context)
-{
-    z_stream *context = void_context;
-    context->zalloc = NULL;
-    context->zfree = NULL;
-    context->opaque = NULL;
-
-    return ssl3_MapZlibError(deflateInit(context, Z_DEFAULT_COMPRESSION));
-}
-
-static SECStatus
-ssl3_InflateInit(void *void_context)
-{
-    z_stream *context = void_context;
-    context->zalloc = NULL;
-    context->zfree = NULL;
-    context->opaque = NULL;
-    context->next_in = NULL;
-    context->avail_in = 0;
-
-    return ssl3_MapZlibError(inflateInit(context));
-}
-
-static SECStatus
-ssl3_DeflateCompress(void *void_context, unsigned char *out, int *out_len,
-                     int maxout, const unsigned char *in, int inlen)
-{
-    z_stream *context = void_context;
-
-    if (!inlen) {
-        *out_len = 0;
-        return SECSuccess;
-    }
-
-    context->next_in = (unsigned char *)in;
-    context->avail_in = inlen;
-    context->next_out = out;
-    context->avail_out = maxout;
-    if (deflate(context, Z_SYNC_FLUSH) != Z_OK) {
-        return SECFailure;
-    }
-    if (context->avail_out == 0) {
-        /* We ran out of space! */
-        SSL_TRC(3, ("%d: SSL3[%d] Ran out of buffer while compressing",
-                    SSL_GETPID()));
-        return SECFailure;
-    }
-
-    *out_len = maxout - context->avail_out;
-    return SECSuccess;
-}
-
-static SECStatus
-ssl3_DeflateDecompress(void *void_context, unsigned char *out, int *out_len,
-                       int maxout, const unsigned char *in, int inlen)
-{
-    z_stream *context = void_context;
-
-    if (!inlen) {
-        *out_len = 0;
-        return SECSuccess;
-    }
-
-    context->next_in = (unsigned char *)in;
-    context->avail_in = inlen;
-    context->next_out = out;
-    context->avail_out = maxout;
-    if (inflate(context, Z_SYNC_FLUSH) != Z_OK) {
-        PORT_SetError(SSL_ERROR_DECOMPRESSION_FAILURE);
-        return SECFailure;
-    }
-
-    *out_len = maxout - context->avail_out;
-    return SECSuccess;
-}
-
-static SECStatus
-ssl3_DestroyCompressContext(void *void_context, PRBool unused)
-{
-    deflateEnd(void_context);
-    PORT_Free(void_context);
-    return SECSuccess;
-}
-
-static SECStatus
-ssl3_DestroyDecompressContext(void *void_context, PRBool unused)
-{
-    inflateEnd(void_context);
-    PORT_Free(void_context);
-    return SECSuccess;
-}
-
-#endif /* NSS_SSL_ENABLE_ZLIB */
-
-/* Initialize the compression functions and contexts for the given
- * CipherSpec.  */
-static SECStatus
-ssl3_InitCompressionContext(ssl3CipherSpec *pwSpec)
-{
-    /* Setup the compression functions */
-    switch (pwSpec->compression_method) {
-        case ssl_compression_null:
-            pwSpec->compressor = NULL;
-            pwSpec->decompressor = NULL;
-            pwSpec->compressContext = NULL;
-            pwSpec->decompressContext = NULL;
-            pwSpec->destroyCompressContext = NULL;
-            pwSpec->destroyDecompressContext = NULL;
-            break;
-#ifdef NSS_SSL_ENABLE_ZLIB
-        case ssl_compression_deflate:
-            pwSpec->compressor = ssl3_DeflateCompress;
-            pwSpec->decompressor = ssl3_DeflateDecompress;
-            pwSpec->compressContext = PORT_Alloc(SSL3_DEFLATE_CONTEXT_SIZE);
-            pwSpec->decompressContext = PORT_Alloc(SSL3_DEFLATE_CONTEXT_SIZE);
-            pwSpec->destroyCompressContext = ssl3_DestroyCompressContext;
-            pwSpec->destroyDecompressContext = ssl3_DestroyDecompressContext;
-            ssl3_DeflateInit(pwSpec->compressContext);
-            ssl3_InflateInit(pwSpec->decompressContext);
-            break;
-#endif /* NSS_SSL_ENABLE_ZLIB */
-        default:
-            PORT_Assert(0);
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            return SECFailure;
-    }
-
-    return SECSuccess;
-}
-
-#ifndef NO_PKCS11_BYPASS
-/* Initialize encryption contexts for pending spec.
- * MAC contexts are set up when computing the mac, not here.
- * Master Secret already is derived in spec->msItem
- * Caller holds Spec write lock.
- */
-static SECStatus
-ssl3_InitPendingContextsBypass(sslSocket *ss)
-{
-    ssl3CipherSpec *pwSpec;
-    const ssl3BulkCipherDef *cipher_def;
-    void *serverContext = NULL;
-    void *clientContext = NULL;
-    BLapiInitContextFunc initFn = (BLapiInitContextFunc)NULL;
-    int mode = 0;
-    unsigned int optArg1 = 0;
-    unsigned int optArg2 = 0;
-    PRBool server_encrypts = ss->sec.isServer;
-    SSLCipherAlgorithm calg;
-    SECStatus rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
-    PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
-
-    pwSpec = ss->ssl3.pwSpec;
-    cipher_def = pwSpec->cipher_def;
-
-    calg = cipher_def->calg;
-
-    if (calg == ssl_calg_aes_gcm) {
-        pwSpec->encode = NULL;
-        pwSpec->decode = NULL;
-        pwSpec->destroy = NULL;
-        pwSpec->encodeContext = NULL;
-        pwSpec->decodeContext = NULL;
-        pwSpec->aead = ssl3_AESGCMBypass;
-        ssl3_InitCompressionContext(pwSpec);
-        return SECSuccess;
-    }
-
-    serverContext = pwSpec->server.cipher_context;
-    clientContext = pwSpec->client.cipher_context;
-
-    switch (calg) {
-        case ssl_calg_null:
-            pwSpec->encode = Null_Cipher;
-            pwSpec->decode = Null_Cipher;
-            pwSpec->destroy = NULL;
-            goto success;
-
-        case ssl_calg_rc4:
-            initFn = (BLapiInitContextFunc)RC4_InitContext;
-            pwSpec->encode = (SSLCipher)RC4_Encrypt;
-            pwSpec->decode = (SSLCipher)RC4_Decrypt;
-            pwSpec->destroy = (SSLDestroy)RC4_DestroyContext;
-            break;
-        case ssl_calg_rc2:
-            initFn = (BLapiInitContextFunc)RC2_InitContext;
-            mode = NSS_RC2_CBC;
-            optArg1 = cipher_def->key_size;
-            pwSpec->encode = (SSLCipher)RC2_Encrypt;
-            pwSpec->decode = (SSLCipher)RC2_Decrypt;
-            pwSpec->destroy = (SSLDestroy)RC2_DestroyContext;
-            break;
-        case ssl_calg_des:
-            initFn = (BLapiInitContextFunc)DES_InitContext;
-            mode = NSS_DES_CBC;
-            optArg1 = server_encrypts;
-            pwSpec->encode = (SSLCipher)DES_Encrypt;
-            pwSpec->decode = (SSLCipher)DES_Decrypt;
-            pwSpec->destroy = (SSLDestroy)DES_DestroyContext;
-            break;
-        case ssl_calg_3des:
-            initFn = (BLapiInitContextFunc)DES_InitContext;
-            mode = NSS_DES_EDE3_CBC;
-            optArg1 = server_encrypts;
-            pwSpec->encode = (SSLCipher)DES_Encrypt;
-            pwSpec->decode = (SSLCipher)DES_Decrypt;
-            pwSpec->destroy = (SSLDestroy)DES_DestroyContext;
-            break;
-        case ssl_calg_aes:
-            initFn = (BLapiInitContextFunc)AES_InitContext;
-            mode = NSS_AES_CBC;
-            optArg1 = server_encrypts;
-            optArg2 = AES_BLOCK_SIZE;
-            pwSpec->encode = (SSLCipher)AES_Encrypt;
-            pwSpec->decode = (SSLCipher)AES_Decrypt;
-            pwSpec->destroy = (SSLDestroy)AES_DestroyContext;
-            break;
-
-        case ssl_calg_camellia:
-            initFn = (BLapiInitContextFunc)Camellia_InitContext;
-            mode = NSS_CAMELLIA_CBC;
-            optArg1 = server_encrypts;
-            optArg2 = CAMELLIA_BLOCK_SIZE;
-            pwSpec->encode = (SSLCipher)Camellia_Encrypt;
-            pwSpec->decode = (SSLCipher)Camellia_Decrypt;
-            pwSpec->destroy = (SSLDestroy)Camellia_DestroyContext;
-            break;
-
-        case ssl_calg_seed:
-            initFn = (BLapiInitContextFunc)SEED_InitContext;
-            mode = NSS_SEED_CBC;
-            optArg1 = server_encrypts;
-            optArg2 = SEED_BLOCK_SIZE;
-            pwSpec->encode = (SSLCipher)SEED_Encrypt;
-            pwSpec->decode = (SSLCipher)SEED_Decrypt;
-            pwSpec->destroy = (SSLDestroy)SEED_DestroyContext;
-            break;
-
-        case ssl_calg_idea:
-        case ssl_calg_fortezza:
-        default:
-            PORT_Assert(0);
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            goto bail_out;
-    }
-    rv = (*initFn)(serverContext,
-                   pwSpec->server.write_key_item.data,
-                   pwSpec->server.write_key_item.len,
-                   pwSpec->server.write_iv_item.data,
-                   mode, optArg1, optArg2);
-    if (rv != SECSuccess) {
-        PORT_Assert(0);
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        goto bail_out;
-    }
-
-    switch (calg) {
-        case ssl_calg_des:
-        case ssl_calg_3des:
-        case ssl_calg_aes:
-        case ssl_calg_camellia:
-        case ssl_calg_seed:
-            /* For block ciphers, if the server is encrypting, then the client
-             * is decrypting, and vice versa.
-             */
-            optArg1 = !optArg1;
-            break;
-        /* kill warnings. */
-        case ssl_calg_null:
-        case ssl_calg_rc4:
-        case ssl_calg_rc2:
-        case ssl_calg_idea:
-        case ssl_calg_fortezza:
-        case ssl_calg_aes_gcm:
-        case ssl_calg_chacha20:
-            break;
-    }
-
-    rv = (*initFn)(clientContext,
-                   pwSpec->client.write_key_item.data,
-                   pwSpec->client.write_key_item.len,
-                   pwSpec->client.write_iv_item.data,
-                   mode, optArg1, optArg2);
-    if (rv != SECSuccess) {
-        PORT_Assert(0);
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        goto bail_out;
-    }
-
-    pwSpec->encodeContext = (ss->sec.isServer) ? serverContext : clientContext;
-    pwSpec->decodeContext = (ss->sec.isServer) ? clientContext : serverContext;
-
-    ssl3_InitCompressionContext(pwSpec);
-
-success:
-    return SECSuccess;
-
-bail_out:
-    return SECFailure;
-}
-#endif
-
-/* This function should probably be moved to pk11wrap and be named
- * PK11_ParamFromIVAndEffectiveKeyBits
- */
-static SECItem *
-ssl3_ParamFromIV(CK_MECHANISM_TYPE mtype, SECItem *iv, CK_ULONG ulEffectiveBits)
-{
-    SECItem *param = PK11_ParamFromIV(mtype, iv);
-    if (param && param->data && param->len >= sizeof(CK_RC2_PARAMS)) {
-        switch (mtype) {
-            case CKM_RC2_KEY_GEN:
-            case CKM_RC2_ECB:
-            case CKM_RC2_CBC:
-            case CKM_RC2_MAC:
-            case CKM_RC2_MAC_GENERAL:
-            case CKM_RC2_CBC_PAD:
-                *(CK_RC2_PARAMS *)param->data = ulEffectiveBits;
-            default:
-                break;
-        }
-    }
-    return param;
-}
-
-/* ssl3_BuildRecordPseudoHeader writes the SSL/TLS pseudo-header (the data
- * which is included in the MAC or AEAD additional data) to |out| and returns
- * its length. See https://tools.ietf.org/html/rfc5246#section-6.2.3.3 for the
- * definition of the AEAD additional data.
- *
- * TLS pseudo-header includes the record's version field, SSL's doesn't. Which
- * pseudo-header defintiion to use should be decided based on the version of
- * the protocol that was negotiated when the cipher spec became current, NOT
- * based on the version value in the record itself, and the decision is passed
- * to this function as the |includesVersion| argument. But, the |version|
- * argument should be the record's version value.
- */
-static unsigned int
-ssl3_BuildRecordPseudoHeader(unsigned char *out,
-                             SSL3SequenceNumber seq_num,
-                             SSL3ContentType type,
-                             PRBool includesVersion,
-                             SSL3ProtocolVersion version,
-                             PRBool isDTLS,
-                             int length)
-{
-    out[0] = (unsigned char)(seq_num.high >> 24);
-    out[1] = (unsigned char)(seq_num.high >> 16);
-    out[2] = (unsigned char)(seq_num.high >> 8);
-    out[3] = (unsigned char)(seq_num.high >> 0);
-    out[4] = (unsigned char)(seq_num.low >> 24);
-    out[5] = (unsigned char)(seq_num.low >> 16);
-    out[6] = (unsigned char)(seq_num.low >> 8);
-    out[7] = (unsigned char)(seq_num.low >> 0);
-    out[8] = type;
-
-    /* SSL3 MAC doesn't include the record's version field. */
-    if (!includesVersion) {
-        out[9] = MSB(length);
-        out[10] = LSB(length);
-        return 11;
-    }
-
-    /* TLS MAC and AEAD additional data include version. */
-    if (isDTLS) {
-        SSL3ProtocolVersion dtls_version;
-
-        dtls_version = dtls_TLSVersionToDTLSVersion(version);
-        out[9] = MSB(dtls_version);
-        out[10] = LSB(dtls_version);
-    } else {
-        out[9] = MSB(version);
-        out[10] = LSB(version);
-    }
-    out[11] = MSB(length);
-    out[12] = LSB(length);
-    return 13;
-}
-
-static SECStatus
-ssl3_AESGCM(ssl3KeyMaterial *keys,
-            PRBool doDecrypt,
-            unsigned char *out,
-            int *outlen,
-            int maxout,
-            const unsigned char *in,
-            int inlen,
-            const unsigned char *additionalData,
-            int additionalDataLen)
-{
-    SECItem param;
-    SECStatus rv = SECFailure;
-    unsigned char nonce[12];
-    unsigned int uOutLen;
-    CK_GCM_PARAMS gcmParams;
-
-    const int tagSize = bulk_cipher_defs[cipher_aes_128_gcm].tag_size;
-    const int explicitNonceLen =
-        bulk_cipher_defs[cipher_aes_128_gcm].explicit_nonce_size;
-
-    /* See https://tools.ietf.org/html/rfc5288#section-3 for details of how the
-     * nonce is formed. */
-    memcpy(nonce, keys->write_iv, 4);
-    if (doDecrypt) {
-        memcpy(nonce + 4, in, explicitNonceLen);
-        in += explicitNonceLen;
-        inlen -= explicitNonceLen;
-        *outlen = 0;
-    } else {
-        if (maxout < explicitNonceLen) {
-            PORT_SetError(SEC_ERROR_INPUT_LEN);
-            return SECFailure;
-        }
-        /* Use the 64-bit sequence number as the explicit nonce. */
-        memcpy(nonce + 4, additionalData, explicitNonceLen);
-        memcpy(out, additionalData, explicitNonceLen);
-        out += explicitNonceLen;
-        maxout -= explicitNonceLen;
-        *outlen = explicitNonceLen;
-    }
-
-    param.type = siBuffer;
-    param.data = (unsigned char *)&gcmParams;
-    param.len = sizeof(gcmParams);
-    gcmParams.pIv = nonce;
-    gcmParams.ulIvLen = sizeof(nonce);
-    gcmParams.pAAD = (unsigned char *)additionalData; /* const cast */
-    gcmParams.ulAADLen = additionalDataLen;
-    gcmParams.ulTagBits = tagSize * 8;
-
-    if (doDecrypt) {
-        rv = PK11_Decrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
-                          maxout, in, inlen);
-    } else {
-        rv = PK11_Encrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
-                          maxout, in, inlen);
-    }
-    *outlen += (int)uOutLen;
-
-    return rv;
-}
-
-#ifndef NO_PKCS11_BYPASS
-static SECStatus
-ssl3_AESGCMBypass(ssl3KeyMaterial *keys,
-                  PRBool doDecrypt,
-                  unsigned char *out,
-                  int *outlen,
-                  int maxout,
-                  const unsigned char *in,
-                  int inlen,
-                  const unsigned char *additionalData,
-                  int additionalDataLen)
-{
-    SECStatus rv = SECFailure;
-    unsigned char nonce[12];
-    unsigned int uOutLen;
-    AESContext *cx;
-    CK_GCM_PARAMS gcmParams;
-
-    const int tagSize = bulk_cipher_defs[cipher_aes_128_gcm].tag_size;
-    const int explicitNonceLen =
-        bulk_cipher_defs[cipher_aes_128_gcm].explicit_nonce_size;
-
-    /* See https://tools.ietf.org/html/rfc5288#section-3 for details of how the
-     * nonce is formed. */
-    PORT_Assert(keys->write_iv_item.len == 4);
-    if (keys->write_iv_item.len != 4) {
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        return SECFailure;
-    }
-    memcpy(nonce, keys->write_iv_item.data, 4);
-    if (doDecrypt) {
-        memcpy(nonce + 4, in, explicitNonceLen);
-        in += explicitNonceLen;
-        inlen -= explicitNonceLen;
-        *outlen = 0;
-    } else {
-        if (maxout < explicitNonceLen) {
-            PORT_SetError(SEC_ERROR_INPUT_LEN);
-            return SECFailure;
-        }
-        /* Use the 64-bit sequence number as the explicit nonce. */
-        memcpy(nonce + 4, additionalData, explicitNonceLen);
-        memcpy(out, additionalData, explicitNonceLen);
-        out += explicitNonceLen;
-        maxout -= explicitNonceLen;
-        *outlen = explicitNonceLen;
-    }
-
-    gcmParams.pIv = nonce;
-    gcmParams.ulIvLen = sizeof(nonce);
-    gcmParams.pAAD = (unsigned char *)additionalData; /* const cast */
-    gcmParams.ulAADLen = additionalDataLen;
-    gcmParams.ulTagBits = tagSize * 8;
-
-    cx = (AESContext *)keys->cipher_context;
-    rv = AES_InitContext(cx, keys->write_key_item.data,
-                         keys->write_key_item.len,
-                         (unsigned char *)&gcmParams, NSS_AES_GCM, !doDecrypt,
-                         AES_BLOCK_SIZE);
-    if (rv != SECSuccess) {
-        return rv;
-    }
-    if (doDecrypt) {
-        rv = AES_Decrypt(cx, out, &uOutLen, maxout, in, inlen);
-    } else {
-        rv = AES_Encrypt(cx, out, &uOutLen, maxout, in, inlen);
-    }
-    AES_DestroyContext(cx, PR_FALSE);
-    *outlen += (int)uOutLen;
-
-    return rv;
-}
-#endif
-
-static SECStatus
-ssl3_ChaCha20Poly1305(ssl3KeyMaterial *keys, PRBool doDecrypt,
-                      unsigned char *out, int *outlen, int maxout,
-                      const unsigned char *in, int inlen,
-                      const unsigned char *additionalData,
-                      int additionalDataLen)
-{
-    size_t i;
-    SECItem param;
-    SECStatus rv = SECFailure;
-    unsigned int uOutLen;
-    unsigned char nonce[12];
-    CK_NSS_AEAD_PARAMS aeadParams;
-
-    const int tagSize = bulk_cipher_defs[cipher_chacha20].tag_size;
-
-    /* See
-     * https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305-04#section-2
-     * for details of how the nonce is formed. */
-    PORT_Memcpy(nonce, keys->write_iv, 12);
-
-    /* XOR the last 8 bytes of the IV with the sequence number. */
-    PORT_Assert(additionalDataLen >= 8);
-    for (i = 0; i < 8; ++i) {
-        nonce[4 + i] ^= additionalData[i];
-    }
-
-    param.type = siBuffer;
-    param.len = sizeof(aeadParams);
-    param.data = (unsigned char *)&aeadParams;
-    memset(&aeadParams, 0, sizeof(aeadParams));
-    aeadParams.pNonce = nonce;
-    aeadParams.ulNonceLen = sizeof(nonce);
-    aeadParams.pAAD = (unsigned char *)additionalData;
-    aeadParams.ulAADLen = additionalDataLen;
-    aeadParams.ulTagLen = tagSize;
-
-    if (doDecrypt) {
-        rv = PK11_Decrypt(keys->write_key, CKM_NSS_CHACHA20_POLY1305, &param,
-                          out, &uOutLen, maxout, in, inlen);
-    } else {
-        rv = PK11_Encrypt(keys->write_key, CKM_NSS_CHACHA20_POLY1305, &param,
-                          out, &uOutLen, maxout, in, inlen);
-    }
-    *outlen = (int)uOutLen;
-
-    return rv;
-}
-
-/* Initialize encryption and MAC contexts for pending spec.
- * Master Secret already is derived.
- * Caller holds Spec write lock.
- */
-static SECStatus
-ssl3_InitPendingContextsPKCS11(sslSocket *ss)
-{
-    ssl3CipherSpec *pwSpec;
-    const ssl3BulkCipherDef *cipher_def;
-    PK11Context *serverContext = NULL;
-    PK11Context *clientContext = NULL;
-    SECItem *param;
-    CK_MECHANISM_TYPE mechanism;
-    CK_MECHANISM_TYPE mac_mech;
-    CK_ULONG macLength;
-    CK_ULONG effKeyBits;
-    SECItem iv;
-    SECItem mac_param;
-    SSLCipherAlgorithm calg;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
-    PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
-
-    pwSpec = ss->ssl3.pwSpec;
-    cipher_def = pwSpec->cipher_def;
-    macLength = pwSpec->mac_size;
-    calg = cipher_def->calg;
-    PORT_Assert(alg2Mech[calg].calg == calg);
-
-    pwSpec->client.write_mac_context = NULL;
-    pwSpec->server.write_mac_context = NULL;
-
-    if (cipher_def->type == type_aead) {
-        pwSpec->encode = NULL;
-        pwSpec->decode = NULL;
-        pwSpec->destroy = NULL;
-        pwSpec->encodeContext = NULL;
-        pwSpec->decodeContext = NULL;
-        switch (calg) {
-            case calg_aes_gcm:
-                pwSpec->aead = ssl3_AESGCM;
-                break;
-            case calg_chacha20:
-                pwSpec->aead = ssl3_ChaCha20Poly1305;
-                break;
-            default:
-                PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-                return SECFailure;
-        }
-        return SECSuccess;
-    }
-
-    /*
-    ** Now setup the MAC contexts,
-    **   crypto contexts are setup below.
-    */
-
-    mac_mech = pwSpec->mac_def->mmech;
-    mac_param.data = (unsigned char *)&macLength;
-    mac_param.len = sizeof(macLength);
-    mac_param.type = 0;
-
-    pwSpec->client.write_mac_context = PK11_CreateContextBySymKey(
-        mac_mech, CKA_SIGN, pwSpec->client.write_mac_key, &mac_param);
-    if (pwSpec->client.write_mac_context == NULL) {
-        ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
-        goto fail;
-    }
-    pwSpec->server.write_mac_context = PK11_CreateContextBySymKey(
-        mac_mech, CKA_SIGN, pwSpec->server.write_mac_key, &mac_param);
-    if (pwSpec->server.write_mac_context == NULL) {
-        ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
-        goto fail;
-    }
-
-    /*
-    ** Now setup the crypto contexts.
-    */
-
-    if (calg == calg_null) {
-        pwSpec->encode = Null_Cipher;
-        pwSpec->decode = Null_Cipher;
-        pwSpec->destroy = NULL;
-        return SECSuccess;
-    }
-    mechanism = ssl3_Alg2Mech(calg);
-    effKeyBits = cipher_def->key_size * BPB;
-
-    /*
-     * build the server context
-     */
-    iv.data = pwSpec->server.write_iv;
-    iv.len = cipher_def->iv_size;
-    param = ssl3_ParamFromIV(mechanism, &iv, effKeyBits);
-    if (param == NULL) {
-        ssl_MapLowLevelError(SSL_ERROR_IV_PARAM_FAILURE);
-        goto fail;
-    }
-    serverContext = PK11_CreateContextBySymKey(mechanism,
-                                               (ss->sec.isServer ? CKA_ENCRYPT
-                                                                 : CKA_DECRYPT),
-                                               pwSpec->server.write_key, param);
-    iv.data = PK11_IVFromParam(mechanism, param, (int *)&iv.len);
-    if (iv.data)
-        PORT_Memcpy(pwSpec->server.write_iv, iv.data, iv.len);
-    SECITEM_FreeItem(param, PR_TRUE);
-    if (serverContext == NULL) {
-        ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
-        goto fail;
-    }
-
-    /*
-     * build the client context
-     */
-    iv.data = pwSpec->client.write_iv;
-    iv.len = cipher_def->iv_size;
-
-    param = ssl3_ParamFromIV(mechanism, &iv, effKeyBits);
-    if (param == NULL) {
-        ssl_MapLowLevelError(SSL_ERROR_IV_PARAM_FAILURE);
-        goto fail;
-    }
-    clientContext = PK11_CreateContextBySymKey(mechanism,
-                                               (ss->sec.isServer ? CKA_DECRYPT
-                                                                 : CKA_ENCRYPT),
-                                               pwSpec->client.write_key, param);
-    iv.data = PK11_IVFromParam(mechanism, param, (int *)&iv.len);
-    if (iv.data)
-        PORT_Memcpy(pwSpec->client.write_iv, iv.data, iv.len);
-    SECITEM_FreeItem(param, PR_TRUE);
-    if (clientContext == NULL) {
-        ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
-        goto fail;
-    }
-    pwSpec->encode = (SSLCipher)PK11_CipherOp;
-    pwSpec->decode = (SSLCipher)PK11_CipherOp;
-    pwSpec->destroy = (SSLDestroy)PK11_DestroyContext;
-
-    pwSpec->encodeContext = (ss->sec.isServer) ? serverContext : clientContext;
-    pwSpec->decodeContext = (ss->sec.isServer) ? clientContext : serverContext;
-
-    serverContext = NULL;
-    clientContext = NULL;
-
-    ssl3_InitCompressionContext(pwSpec);
-
-    return SECSuccess;
-
-fail:
-    if (serverContext != NULL)
-        PK11_DestroyContext(serverContext, PR_TRUE);
-    if (clientContext != NULL)
-        PK11_DestroyContext(clientContext, PR_TRUE);
-    if (pwSpec->client.write_mac_context != NULL) {
-        PK11_DestroyContext(pwSpec->client.write_mac_context, PR_TRUE);
-        pwSpec->client.write_mac_context = NULL;
-    }
-    if (pwSpec->server.write_mac_context != NULL) {
-        PK11_DestroyContext(pwSpec->server.write_mac_context, PR_TRUE);
-        pwSpec->server.write_mac_context = NULL;
-    }
-
-    return SECFailure;
-}
-
-#ifndef NO_PKCS11_BYPASS
-/* Returns whether we can bypass PKCS#11 for a given cipher algorithm.
- *
- * We do not support PKCS#11 bypass for ChaCha20/Poly1305.
- */
-static PRBool
-ssl3_CanBypassCipher(SSLCipherAlgorithm calg)
-{
-    switch (calg) {
-        case calg_chacha20:
-            return PR_FALSE;
-        default:
-            return PR_TRUE;
-    }
-}
-#endif
-
-/* Complete the initialization of all keys, ciphers, MACs and their contexts
- * for the pending Cipher Spec.
- * Called from: ssl3_SendClientKeyExchange  (for Full handshake)
- *              ssl3_HandleRSAClientKeyExchange (for Full handshake)
- *              ssl3_HandleServerHello      (for session restart)
- *              ssl3_HandleClientHello      (for session restart)
- * Sets error code, but caller probably should override to disambiguate.
- * NULL pms means re-use old master_secret.
- *
- *  This code is common to the bypass and PKCS11 execution paths. For
- *  the bypass case, pms is NULL. If the old master secret is reused,
- *  pms is NULL and the master secret is already in either
- *  pwSpec->msItem.len (the bypass case) or pwSpec->master_secret.
- *
- * For the bypass case,  pms is NULL.
- */
-SECStatus
-ssl3_InitPendingCipherSpec(sslSocket *ss, PK11SymKey *pms)
-{
-    ssl3CipherSpec *pwSpec;
-    ssl3CipherSpec *cwSpec;
-    SECStatus rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    ssl_GetSpecWriteLock(ss); /**************************************/
-
-    PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
-
-    pwSpec = ss->ssl3.pwSpec;
-    cwSpec = ss->ssl3.cwSpec;
-
-    if (pms || (!pwSpec->msItem.len && !pwSpec->master_secret)) {
-        rv = ssl3_DeriveMasterSecret(ss, pms);
-        if (rv != SECSuccess) {
-            goto done; /* err code set by ssl3_DeriveMasterSecret */
-        }
-    }
-#ifndef NO_PKCS11_BYPASS
-    if (ss->opt.bypassPKCS11 && pwSpec->msItem.len && pwSpec->msItem.data &&
-        ssl3_CanBypassCipher(ss->ssl3.pwSpec->cipher_def->calg)) {
-        /* Double Bypass succeeded in extracting the master_secret */
-        const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
-        PRBool isTLS = (PRBool)(kea_def->tls_keygen ||
-                                (pwSpec->version > SSL_LIBRARY_VERSION_3_0));
-        pwSpec->bypassCiphers = PR_TRUE;
-        rv = ssl3_KeyAndMacDeriveBypass(pwSpec,
-                                        (const unsigned char *)&ss->ssl3.hs.client_random,
-                                        (const unsigned char *)&ss->ssl3.hs.server_random,
-                                        isTLS,
-                                        (PRBool)(kea_def->is_limited));
-        if (rv == SECSuccess) {
-            rv = ssl3_InitPendingContextsBypass(ss);
-        }
-    } else
-#endif
-        if (pwSpec->master_secret) {
-        rv = ssl3_DeriveConnectionKeysPKCS11(ss);
-        if (rv == SECSuccess) {
-            rv = ssl3_InitPendingContextsPKCS11(ss);
-        }
-    } else {
-        PORT_Assert(pwSpec->master_secret);
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        rv = SECFailure;
-    }
-    if (rv != SECSuccess) {
-        goto done;
-    }
-
-    /* Generic behaviors -- common to all crypto methods */
-    if (!IS_DTLS(ss)) {
-        pwSpec->read_seq_num.high = pwSpec->write_seq_num.high = 0;
-    } else {
-        if (cwSpec->epoch == PR_UINT16_MAX) {
-            /* The problem here is that we have rehandshaked too many
-             * times (you are not allowed to wrap the epoch). The
-             * spec says you should be discarding the connection
-             * and start over, so not much we can do here. */
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            rv = SECFailure;
-            goto done;
-        }
-        /* The sequence number has the high 16 bits as the epoch. */
-        pwSpec->epoch = cwSpec->epoch + 1;
-        pwSpec->read_seq_num.high = pwSpec->write_seq_num.high =
-            pwSpec->epoch << 16;
-
-        dtls_InitRecvdRecords(&pwSpec->recvdRecords);
-    }
-    pwSpec->read_seq_num.low = pwSpec->write_seq_num.low = 0;
-
-done:
-    ssl_ReleaseSpecWriteLock(ss); /******************************/
-    if (rv != SECSuccess)
-        ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
-    return rv;
-}
-
-/*
- * 60 bytes is 3 times the maximum length MAC size that is supported.
- */
-static const unsigned char mac_pad_1[60] = {
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36
-};
-static const unsigned char mac_pad_2[60] = {
-    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
-    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
-    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
-    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
-    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
-    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
-    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
-    0x5c, 0x5c, 0x5c, 0x5c
-};
-
-/* Called from: ssl3_SendRecord()
-** Caller must already hold the SpecReadLock. (wish we could assert that!)
-*/
-static SECStatus
-ssl3_ComputeRecordMAC(
-    ssl3CipherSpec *spec,
-    PRBool useServerMacKey,
-    const unsigned char *header,
-    unsigned int headerLen,
-    const SSL3Opaque *input,
-    int inputLength,
-    unsigned char *outbuf,
-    unsigned int *outLength)
-{
-    const ssl3MACDef *mac_def;
-    SECStatus rv;
-
-    PRINT_BUF(95, (NULL, "frag hash1: header", header, headerLen));
-    PRINT_BUF(95, (NULL, "frag hash1: input", input, inputLength));
-
-    mac_def = spec->mac_def;
-    if (mac_def->mac == mac_null) {
-        *outLength = 0;
-        return SECSuccess;
-    }
-#ifndef NO_PKCS11_BYPASS
-    if (spec->bypassCiphers) {
-        /* bypass version */
-        const SECHashObject *hashObj = NULL;
-        unsigned int pad_bytes = 0;
-        PRUint64 write_mac_context[MAX_MAC_CONTEXT_LLONGS];
-
-        switch (mac_def->mac) {
-            case ssl_mac_null:
-                *outLength = 0;
-                return SECSuccess;
-            case ssl_mac_md5:
-                pad_bytes = 48;
-                hashObj = HASH_GetRawHashObject(HASH_AlgMD5);
-                break;
-            case ssl_mac_sha:
-                pad_bytes = 40;
-                hashObj = HASH_GetRawHashObject(HASH_AlgSHA1);
-                break;
-            case ssl_hmac_md5: /* used with TLS */
-                hashObj = HASH_GetRawHashObject(HASH_AlgMD5);
-                break;
-            case ssl_hmac_sha: /* used with TLS */
-                hashObj = HASH_GetRawHashObject(HASH_AlgSHA1);
-                break;
-            case ssl_hmac_sha256: /* used with TLS */
-                hashObj = HASH_GetRawHashObject(HASH_AlgSHA256);
-                break;
-            default:
-                break;
-        }
-        if (!hashObj) {
-            PORT_Assert(0);
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            return SECFailure;
-        }
-
-        if (spec->version <= SSL_LIBRARY_VERSION_3_0) {
-            unsigned int tempLen;
-            unsigned char temp[MAX_MAC_LENGTH];
-
-            /* compute "inner" part of SSL3 MAC */
-            hashObj->begin(write_mac_context);
-            if (useServerMacKey)
-                hashObj->update(write_mac_context,
-                                spec->server.write_mac_key_item.data,
-                                spec->server.write_mac_key_item.len);
-            else
-                hashObj->update(write_mac_context,
-                                spec->client.write_mac_key_item.data,
-                                spec->client.write_mac_key_item.len);
-            hashObj->update(write_mac_context, mac_pad_1, pad_bytes);
-            hashObj->update(write_mac_context, header, headerLen);
-            hashObj->update(write_mac_context, input, inputLength);
-            hashObj->end(write_mac_context, temp, &tempLen, sizeof temp);
-
-            /* compute "outer" part of SSL3 MAC */
-            hashObj->begin(write_mac_context);
-            if (useServerMacKey)
-                hashObj->update(write_mac_context,
-                                spec->server.write_mac_key_item.data,
-                                spec->server.write_mac_key_item.len);
-            else
-                hashObj->update(write_mac_context,
-                                spec->client.write_mac_key_item.data,
-                                spec->client.write_mac_key_item.len);
-            hashObj->update(write_mac_context, mac_pad_2, pad_bytes);
-            hashObj->update(write_mac_context, temp, tempLen);
-            hashObj->end(write_mac_context, outbuf, outLength, spec->mac_size);
-            rv = SECSuccess;
-        } else { /* is TLS */
-#define cx ((HMACContext *)write_mac_context)
-            if (useServerMacKey) {
-                rv = HMAC_Init(cx, hashObj,
-                               spec->server.write_mac_key_item.data,
-                               spec->server.write_mac_key_item.len, PR_FALSE);
-            } else {
-                rv = HMAC_Init(cx, hashObj,
-                               spec->client.write_mac_key_item.data,
-                               spec->client.write_mac_key_item.len, PR_FALSE);
-            }
-            if (rv == SECSuccess) {
-                HMAC_Begin(cx);
-                HMAC_Update(cx, header, headerLen);
-                HMAC_Update(cx, input, inputLength);
-                rv = HMAC_Finish(cx, outbuf, outLength, spec->mac_size);
-                HMAC_Destroy(cx, PR_FALSE);
-            }
-#undef cx
-        }
-    } else
-#endif
-    {
-        PK11Context *mac_context =
-            (useServerMacKey ? spec->server.write_mac_context
-                             : spec->client.write_mac_context);
-        rv = PK11_DigestBegin(mac_context);
-        rv |= PK11_DigestOp(mac_context, header, headerLen);
-        rv |= PK11_DigestOp(mac_context, input, inputLength);
-        rv |= PK11_DigestFinal(mac_context, outbuf, outLength, spec->mac_size);
-    }
-
-    PORT_Assert(rv != SECSuccess || *outLength == (unsigned)spec->mac_size);
-
-    PRINT_BUF(95, (NULL, "frag hash2: result", outbuf, *outLength));
-
-    if (rv != SECSuccess) {
-        rv = SECFailure;
-        ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
-    }
-    return rv;
-}
-
-/* Called from: ssl3_HandleRecord()
- * Caller must already hold the SpecReadLock. (wish we could assert that!)
- *
- * On entry:
- *   originalLen >= inputLen >= MAC size
-*/
-static SECStatus
-ssl3_ComputeRecordMACConstantTime(
-    ssl3CipherSpec *spec,
-    PRBool useServerMacKey,
-    const unsigned char *header,
-    unsigned int headerLen,
-    const SSL3Opaque *input,
-    int inputLen,
-    int originalLen,
-    unsigned char *outbuf,
-    unsigned int *outLen)
-{
-    CK_MECHANISM_TYPE macType;
-    CK_NSS_MAC_CONSTANT_TIME_PARAMS params;
-    SECItem param, inputItem, outputItem;
-    SECStatus rv;
-    PK11SymKey *key;
-
-    PORT_Assert(inputLen >= spec->mac_size);
-    PORT_Assert(originalLen >= inputLen);
-
-    if (spec->bypassCiphers) {
-        /* This function doesn't support PKCS#11 bypass. We fallback on the
-         * non-constant time version. */
-        goto fallback;
-    }
-
-    if (spec->mac_def->mac == mac_null) {
-        *outLen = 0;
-        return SECSuccess;
-    }
-
-    macType = CKM_NSS_HMAC_CONSTANT_TIME;
-    if (spec->version <= SSL_LIBRARY_VERSION_3_0) {
-        macType = CKM_NSS_SSL3_MAC_CONSTANT_TIME;
-    }
-
-    params.macAlg = spec->mac_def->mmech;
-    params.ulBodyTotalLen = originalLen;
-    params.pHeader = (unsigned char *)header; /* const cast */
-    params.ulHeaderLen = headerLen;
-
-    param.data = (unsigned char *)&params;
-    param.len = sizeof(params);
-    param.type = 0;
-
-    inputItem.data = (unsigned char *)input;
-    inputItem.len = inputLen;
-    inputItem.type = 0;
-
-    outputItem.data = outbuf;
-    outputItem.len = *outLen;
-    outputItem.type = 0;
-
-    key = spec->server.write_mac_key;
-    if (!useServerMacKey) {
-        key = spec->client.write_mac_key;
-    }
-
-    rv = PK11_SignWithSymKey(key, macType, &param, &outputItem, &inputItem);
-    if (rv != SECSuccess) {
-        if (PORT_GetError() == SEC_ERROR_INVALID_ALGORITHM) {
-            goto fallback;
-        }
-
-        *outLen = 0;
-        rv = SECFailure;
-        ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
-        return rv;
-    }
-
-    PORT_Assert(outputItem.len == (unsigned)spec->mac_size);
-    *outLen = outputItem.len;
-
-    return rv;
-
-fallback:
-    /* ssl3_ComputeRecordMAC expects the MAC to have been removed from the
-     * length already. */
-    inputLen -= spec->mac_size;
-    return ssl3_ComputeRecordMAC(spec, useServerMacKey, header, headerLen,
-                                 input, inputLen, outbuf, outLen);
-}
-
-static PRBool
-ssl3_ClientAuthTokenPresent(sslSessionID *sid)
-{
-    PK11SlotInfo *slot = NULL;
-    PRBool isPresent = PR_TRUE;
-
-    /* we only care if we are doing client auth */
-    if (!sid || !sid->u.ssl3.clAuthValid) {
-        return PR_TRUE;
-    }
-
-    /* get the slot */
-    slot = SECMOD_LookupSlot(sid->u.ssl3.clAuthModuleID,
-                             sid->u.ssl3.clAuthSlotID);
-    if (slot == NULL ||
-        !PK11_IsPresent(slot) ||
-        sid->u.ssl3.clAuthSeries != PK11_GetSlotSeries(slot) ||
-        sid->u.ssl3.clAuthSlotID != PK11_GetSlotID(slot) ||
-        sid->u.ssl3.clAuthModuleID != PK11_GetModuleID(slot) ||
-        (PK11_NeedLogin(slot) && !PK11_IsLoggedIn(slot, NULL))) {
-        isPresent = PR_FALSE;
-    }
-    if (slot) {
-        PK11_FreeSlot(slot);
-    }
-    return isPresent;
-}
-
-/* Caller must hold the spec read lock. */
-SECStatus
-ssl3_CompressMACEncryptRecord(ssl3CipherSpec *cwSpec,
-                              PRBool isServer,
-                              PRBool isDTLS,
-                              PRBool capRecordVersion,
-                              SSL3ContentType type,
-                              const SSL3Opaque *pIn,
-                              PRUint32 contentLen,
-                              sslBuffer *wrBuf)
-{
-    const ssl3BulkCipherDef *cipher_def;
-    SECStatus rv;
-    PRUint32 macLen = 0;
-    PRUint32 fragLen;
-    PRUint32 p1Len, p2Len, oddLen = 0;
-    PRUint16 headerLen;
-    unsigned int ivLen = 0;
-    int cipherBytes = 0;
-    unsigned char pseudoHeader[13];
-    unsigned int pseudoHeaderLen;
-
-    cipher_def = cwSpec->cipher_def;
-    headerLen = isDTLS ? DTLS_RECORD_HEADER_LENGTH : SSL3_RECORD_HEADER_LENGTH;
-
-    if (cipher_def->type == type_block &&
-        cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
-        /* Prepend the per-record explicit IV using technique 2b from
-         * RFC 4346 section 6.2.3.2: The IV is a cryptographically
-         * strong random number XORed with the CBC residue from the previous
-         * record.
-         */
-        ivLen = cipher_def->iv_size;
-        if (ivLen > wrBuf->space - headerLen) {
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            return SECFailure;
-        }
-        rv = PK11_GenerateRandom(wrBuf->buf + headerLen, ivLen);
-        if (rv != SECSuccess) {
-            ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE);
-            return rv;
-        }
-        rv = cwSpec->encode(cwSpec->encodeContext,
-                            wrBuf->buf + headerLen,
-                            &cipherBytes, /* output and actual outLen */
-                            ivLen,        /* max outlen */
-                            wrBuf->buf + headerLen,
-                            ivLen); /* input and inputLen*/
-        if (rv != SECSuccess || cipherBytes != ivLen) {
-            PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
-            return SECFailure;
-        }
-    }
-
-    if (cwSpec->compressor) {
-        int outlen;
-        rv = cwSpec->compressor(
-            cwSpec->compressContext,
-            wrBuf->buf + headerLen + ivLen, &outlen,
-            wrBuf->space - headerLen - ivLen, pIn, contentLen);
-        if (rv != SECSuccess)
-            return rv;
-        pIn = wrBuf->buf + headerLen + ivLen;
-        contentLen = outlen;
-    }
-
-    pseudoHeaderLen = ssl3_BuildRecordPseudoHeader(
-        pseudoHeader, cwSpec->write_seq_num, type,
-        cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_0, cwSpec->version,
-        isDTLS, contentLen);
-    PORT_Assert(pseudoHeaderLen <= sizeof(pseudoHeader));
-    if (cipher_def->type == type_aead) {
-        const int nonceLen = cipher_def->explicit_nonce_size;
-        const int tagLen = cipher_def->tag_size;
-
-        if (headerLen + nonceLen + contentLen + tagLen > wrBuf->space) {
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            return SECFailure;
-        }
-
-        cipherBytes = contentLen;
-        rv = cwSpec->aead(
-            isServer ? &cwSpec->server : &cwSpec->client,
-            PR_FALSE,                 /* do encrypt */
-            wrBuf->buf + headerLen,   /* output  */
-            &cipherBytes,             /* out len */
-            wrBuf->space - headerLen, /* max out */
-            pIn, contentLen,          /* input   */
-            pseudoHeader, pseudoHeaderLen);
-        if (rv != SECSuccess) {
-            PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
-            return SECFailure;
-        }
-    } else {
-        /*
-         * Add the MAC
-         */
-        rv = ssl3_ComputeRecordMAC(cwSpec, isServer,
-                                   pseudoHeader, pseudoHeaderLen, pIn, contentLen,
-                                   wrBuf->buf + headerLen + ivLen + contentLen,
-                                   &macLen);
-        if (rv != SECSuccess) {
-            ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
-            return SECFailure;
-        }
-        p1Len = contentLen;
-        p2Len = macLen;
-        fragLen = contentLen + macLen; /* needs to be encrypted */
-        PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024);
-
-        /*
-         * Pad the text (if we're doing a block cipher)
-         * then Encrypt it
-         */
-        if (cipher_def->type == type_block) {
-            unsigned char *pBuf;
-            int padding_length;
-            int i;
-
-            oddLen = contentLen % cipher_def->block_size;
-            /* Assume blockSize is a power of two */
-            padding_length = cipher_def->block_size - 1 - ((fragLen) & (cipher_def->block_size - 1));
-            fragLen += padding_length + 1;
-            PORT_Assert((fragLen % cipher_def->block_size) == 0);
-
-            /* Pad according to TLS rules (also acceptable to SSL3). */
-            pBuf = &wrBuf->buf[headerLen + ivLen + fragLen - 1];
-            for (i = padding_length + 1; i > 0; --i) {
-                *pBuf-- = padding_length;
-            }
-            /* now, if contentLen is not a multiple of block size, fix it */
-            p2Len = fragLen - p1Len;
-        }
-        if (p1Len < 256) {
-            oddLen = p1Len;
-            p1Len = 0;
-        } else {
-            p1Len -= oddLen;
-        }
-        if (oddLen) {
-            p2Len += oddLen;
-            PORT_Assert((cipher_def->block_size < 2) ||
-                        (p2Len % cipher_def->block_size) == 0);
-            memmove(wrBuf->buf + headerLen + ivLen + p1Len, pIn + p1Len,
-                    oddLen);
-        }
-        if (p1Len > 0) {
-            int cipherBytesPart1 = -1;
-            rv = cwSpec->encode(cwSpec->encodeContext,
-                                wrBuf->buf + headerLen + ivLen, /* output */
-                                &cipherBytesPart1,              /* actual outlen */
-                                p1Len,                          /* max outlen */
-                                pIn,
-                                p1Len); /* input, and inputlen */
-            PORT_Assert(rv == SECSuccess && cipherBytesPart1 == (int)p1Len);
-            if (rv != SECSuccess || cipherBytesPart1 != (int)p1Len) {
-                PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
-                return SECFailure;
-            }
-            cipherBytes += cipherBytesPart1;
-        }
-        if (p2Len > 0) {
-            int cipherBytesPart2 = -1;
-            rv = cwSpec->encode(cwSpec->encodeContext,
-                                wrBuf->buf + headerLen + ivLen + p1Len,
-                                &cipherBytesPart2, /* output and actual outLen */
-                                p2Len,             /* max outlen */
-                                wrBuf->buf + headerLen + ivLen + p1Len,
-                                p2Len); /* input and inputLen*/
-            PORT_Assert(rv == SECSuccess && cipherBytesPart2 == (int)p2Len);
-            if (rv != SECSuccess || cipherBytesPart2 != (int)p2Len) {
-                PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
-                return SECFailure;
-            }
-            cipherBytes += cipherBytesPart2;
-        }
-    }
-
-    PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 1024);
-
-    wrBuf->len = cipherBytes + headerLen;
-    wrBuf->buf[0] = type;
-    if (isDTLS) {
-        SSL3ProtocolVersion version;
-
-        version = dtls_TLSVersionToDTLSVersion(cwSpec->version);
-        wrBuf->buf[1] = MSB(version);
-        wrBuf->buf[2] = LSB(version);
-        wrBuf->buf[3] = (unsigned char)(cwSpec->write_seq_num.high >> 24);
-        wrBuf->buf[4] = (unsigned char)(cwSpec->write_seq_num.high >> 16);
-        wrBuf->buf[5] = (unsigned char)(cwSpec->write_seq_num.high >> 8);
-        wrBuf->buf[6] = (unsigned char)(cwSpec->write_seq_num.high >> 0);
-        wrBuf->buf[7] = (unsigned char)(cwSpec->write_seq_num.low >> 24);
-        wrBuf->buf[8] = (unsigned char)(cwSpec->write_seq_num.low >> 16);
-        wrBuf->buf[9] = (unsigned char)(cwSpec->write_seq_num.low >> 8);
-        wrBuf->buf[10] = (unsigned char)(cwSpec->write_seq_num.low >> 0);
-        wrBuf->buf[11] = MSB(cipherBytes);
-        wrBuf->buf[12] = LSB(cipherBytes);
-    } else {
-        SSL3ProtocolVersion version = cwSpec->version;
-
-        if (capRecordVersion || version >= SSL_LIBRARY_VERSION_TLS_1_3) {
-            version = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0, version);
-        }
-
-        wrBuf->buf[1] = MSB(version);
-        wrBuf->buf[2] = LSB(version);
-        wrBuf->buf[3] = MSB(cipherBytes);
-        wrBuf->buf[4] = LSB(cipherBytes);
-    }
-
-    ssl3_BumpSequenceNumber(&cwSpec->write_seq_num);
-
-    return SECSuccess;
-}
-
-/* Process the plain text before sending it.
- * Returns the number of bytes of plaintext that were successfully sent
- *  plus the number of bytes of plaintext that were copied into the
- *  output (write) buffer.
- * Returns SECFailure on a hard IO error, memory error, or crypto error.
- * Does NOT return SECWouldBlock.
- *
- * Notes on the use of the private ssl flags:
- * (no private SSL flags)
- *    Attempt to make and send SSL records for all plaintext
- *    If non-blocking and a send gets WOULD_BLOCK,
- *    or if the pending (ciphertext) buffer is not empty,
- *    then buffer remaining bytes of ciphertext into pending buf,
- *    and continue to do that for all succssive records until all
- *    bytes are used.
- * ssl_SEND_FLAG_FORCE_INTO_BUFFER
- *    As above, except this suppresses all write attempts, and forces
- *    all ciphertext into the pending ciphertext buffer.
- * ssl_SEND_FLAG_USE_EPOCH (for DTLS)
- *    Forces the use of the provided epoch
- * ssl_SEND_FLAG_CAP_RECORD_VERSION
- *    Caps the record layer version number of TLS ClientHello to { 3, 1 }
- *    (TLS 1.0). Some TLS 1.0 servers (which seem to use F5 BIG-IP) ignore
- *    ClientHello.client_version and use the record layer version number
- *    (TLSPlaintext.version) instead when negotiating protocol versions. In
- *    addition, if the record layer version number of ClientHello is { 3, 2 }
- *    (TLS 1.1) or higher, these servers reset the TCP connections. Lastly,
- *    some F5 BIG-IP servers hang if a record containing a ClientHello has a
- *    version greater than { 3, 1 } and a length greater than 255. Set this
- *    flag to work around such servers.
- */
-PRInt32
-ssl3_SendRecord(sslSocket *ss,
-                DTLSEpoch epoch, /* DTLS only */
-                SSL3ContentType type,
-                const SSL3Opaque *pIn, /* input buffer */
-                PRInt32 nIn,           /* bytes of input */
-                PRInt32 flags)
-{
-    sslBuffer *wrBuf = &ss->sec.writeBuf;
-    SECStatus rv;
-    PRInt32 totalSent = 0;
-    PRBool capRecordVersion;
-
-    SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d",
-                SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type),
-                nIn));
-    PRINT_BUF(50, (ss, "Send record (plain text)", pIn, nIn));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    if (ss->ssl3.fatalAlertSent) {
-        SSL_TRC(3, ("%d: SSL3[%d] Suppress write, fatal alert already sent",
-                    SSL_GETPID(), ss->fd));
-        return SECFailure;
-    }
-
-    capRecordVersion = ((flags & ssl_SEND_FLAG_CAP_RECORD_VERSION) != 0);
-
-    if (capRecordVersion) {
-        /* ssl_SEND_FLAG_CAP_RECORD_VERSION can only be used with the
-         * TLS initial ClientHello. */
-        PORT_Assert(!IS_DTLS(ss));
-        PORT_Assert(!ss->firstHsDone);
-        PORT_Assert(type == content_handshake);
-        PORT_Assert(ss->ssl3.hs.ws == wait_server_hello);
-    }
-
-    if (ss->ssl3.initialized == PR_FALSE) {
-        /* This can happen on a server if the very first incoming record
-        ** looks like a defective ssl3 record (e.g. too long), and we're
-        ** trying to send an alert.
-        */
-        PR_ASSERT(type == content_alert);
-        rv = ssl3_InitState(ss);
-        if (rv != SECSuccess) {
-            return SECFailure; /* ssl3_InitState has set the error code. */
-        }
-    }
-
-    /* check for Token Presence */
-    if (!ssl3_ClientAuthTokenPresent(ss->sec.ci.sid)) {
-        PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
-        return SECFailure;
-    }
-
-    while (nIn > 0) {
-        PRUint32 contentLen = PR_MIN(nIn, MAX_FRAGMENT_LENGTH);
-        unsigned int spaceNeeded;
-        unsigned int numRecords;
-
-        ssl_GetSpecReadLock(ss); /********************************/
-
-        if (nIn > 1 && ss->opt.cbcRandomIV &&
-            ss->ssl3.cwSpec->version < SSL_LIBRARY_VERSION_TLS_1_1 &&
-            type == content_application_data &&
-            ss->ssl3.cwSpec->cipher_def->type == type_block /* CBC mode */) {
-            /* We will split the first byte of the record into its own record,
-             * as explained in the documentation for SSL_CBC_RANDOM_IV in ssl.h
-             */
-            numRecords = 2;
-        } else {
-            numRecords = 1;
-        }
-
-        spaceNeeded = contentLen + (numRecords * SSL3_BUFFER_FUDGE);
-        if (ss->ssl3.cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1 &&
-            ss->ssl3.cwSpec->cipher_def->type == type_block) {
-            spaceNeeded += ss->ssl3.cwSpec->cipher_def->iv_size;
-        }
-        if (spaceNeeded > wrBuf->space) {
-            rv = sslBuffer_Grow(wrBuf, spaceNeeded);
-            if (rv != SECSuccess) {
-                SSL_DBG(("%d: SSL3[%d]: SendRecord, tried to get %d bytes",
-                         SSL_GETPID(), ss->fd, spaceNeeded));
-                goto spec_locked_loser; /* sslBuffer_Grow set error code. */
-            }
-        }
-
-        if (numRecords == 2) {
-            sslBuffer secondRecord;
-            rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec,
-                                               ss->sec.isServer, IS_DTLS(ss),
-                                               capRecordVersion, type, pIn,
-                                               1, wrBuf);
-            if (rv != SECSuccess)
-                goto spec_locked_loser;
-
-            PRINT_BUF(50, (ss, "send (encrypted) record data [1/2]:",
-                           wrBuf->buf, wrBuf->len));
-
-            secondRecord.buf = wrBuf->buf + wrBuf->len;
-            secondRecord.len = 0;
-            secondRecord.space = wrBuf->space - wrBuf->len;
-
-            rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec,
-                                               ss->sec.isServer, IS_DTLS(ss),
-                                               capRecordVersion, type,
-                                               pIn + 1,
-                                               contentLen - 1,
-                                               &secondRecord);
-            if (rv == SECSuccess) {
-                PRINT_BUF(50, (ss, "send (encrypted) record data [2/2]:",
-                               secondRecord.buf, secondRecord.len));
-                wrBuf->len += secondRecord.len;
-            }
-        } else {
-            if (!IS_DTLS(ss)) {
-                if (ss->ssl3.cwSpec->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-                    rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec,
-                                                       ss->sec.isServer,
-                                                       PR_FALSE,
-                                                       capRecordVersion,
-                                                       type, pIn,
-                                                       contentLen, wrBuf);
-                } else {
-                    rv = tls13_ProtectRecord(ss, type, pIn,
-                                             contentLen, wrBuf);
-                }
-            } else {
-                /* TLS <= 1.2 and TLS 1.3 cases are both handled in
-                 * dtls_CompressMACEncryptRecord. */
-                rv = dtls_CompressMACEncryptRecord(ss, epoch,
-                                                   !!(flags & ssl_SEND_FLAG_USE_EPOCH),
-                                                   type, pIn,
-                                                   contentLen, wrBuf);
-            }
-
-            if (rv == SECSuccess) {
-                PRINT_BUF(50, (ss, "send (encrypted) record data:",
-                               wrBuf->buf, wrBuf->len));
-            }
-        }
-
-    spec_locked_loser:
-        ssl_ReleaseSpecReadLock(ss); /************************************/
-
-        if (rv != SECSuccess)
-            return SECFailure;
-
-        pIn += contentLen;
-        nIn -= contentLen;
-        PORT_Assert(nIn >= 0);
-
-        /* If there's still some previously saved ciphertext,
-         * or the caller doesn't want us to send the data yet,
-         * then add all our new ciphertext to the amount previously saved.
-         */
-        if ((ss->pendingBuf.len > 0) ||
-            (flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {
-
-            rv = ssl_SaveWriteData(ss, wrBuf->buf, wrBuf->len);
-            if (rv != SECSuccess) {
-                /* presumably a memory error, SEC_ERROR_NO_MEMORY */
-                return SECFailure;
-            }
-            wrBuf->len = 0; /* All cipher text is saved away. */
-
-            if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {
-                PRInt32 sent;
-                ss->handshakeBegun = 1;
-                sent = ssl_SendSavedWriteData(ss);
-                if (sent < 0 && PR_GetError() != PR_WOULD_BLOCK_ERROR) {
-                    ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
-                    return SECFailure;
-                }
-                if (ss->pendingBuf.len) {
-                    flags |= ssl_SEND_FLAG_FORCE_INTO_BUFFER;
-                }
-            }
-        } else if (wrBuf->len > 0) {
-            PRInt32 sent;
-            ss->handshakeBegun = 1;
-            sent = ssl_DefSend(ss, wrBuf->buf, wrBuf->len,
-                               flags & ~ssl_SEND_FLAG_MASK);
-            if (sent < 0) {
-                if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
-                    ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
-                    return SECFailure;
-                }
-                /* we got PR_WOULD_BLOCK_ERROR, which means none was sent. */
-                sent = 0;
-            }
-            wrBuf->len -= sent;
-            if (wrBuf->len) {
-                if (IS_DTLS(ss)) {
-                    /* DTLS just says no in this case. No buffering */
-                    PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
-                    return SECFailure;
-                }
-                /* now take all the remaining unsent new ciphertext and
-                 * append it to the buffer of previously unsent ciphertext.
-                 */
-                rv = ssl_SaveWriteData(ss, wrBuf->buf + sent, wrBuf->len);
-                if (rv != SECSuccess) {
-                    /* presumably a memory error, SEC_ERROR_NO_MEMORY */
-                    return SECFailure;
-                }
-            }
-        }
-        totalSent += contentLen;
-    }
-    return totalSent;
-}
-
-#define SSL3_PENDING_HIGH_WATER 1024
-
-/* Attempt to send the content of "in" in an SSL application_data record.
- * Returns "len" or SECFailure,   never SECWouldBlock, nor SECSuccess.
- */
-int
-ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in,
-                         PRInt32 len, PRInt32 flags)
-{
-    PRInt32 totalSent = 0;
-    PRInt32 discarded = 0;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    /* These flags for internal use only */
-    PORT_Assert(!(flags & (ssl_SEND_FLAG_USE_EPOCH |
-                           ssl_SEND_FLAG_NO_RETRANSMIT)));
-    if (len < 0 || !in) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return SECFailure;
-    }
-
-    if (ss->pendingBuf.len > SSL3_PENDING_HIGH_WATER &&
-        !ssl_SocketIsBlocking(ss)) {
-        PORT_Assert(!ssl_SocketIsBlocking(ss));
-        PORT_SetError(PR_WOULD_BLOCK_ERROR);
-        return SECFailure;
-    }
-
-    if (ss->appDataBuffered && len) {
-        PORT_Assert(in[0] == (unsigned char)(ss->appDataBuffered));
-        if (in[0] != (unsigned char)(ss->appDataBuffered)) {
-            PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-            return SECFailure;
-        }
-        in++;
-        len--;
-        discarded = 1;
-    }
-    while (len > totalSent) {
-        PRInt32 sent, toSend;
-
-        if (totalSent > 0) {
-            /*
-             * The thread yield is intended to give the reader thread a
-             * chance to get some cycles while the writer thread is in
-             * the middle of a large application data write.  (See
-             * Bugzilla bug 127740, comment #1.)
-             */
-            ssl_ReleaseXmitBufLock(ss);
-            PR_Sleep(PR_INTERVAL_NO_WAIT); /* PR_Yield(); */
-            ssl_GetXmitBufLock(ss);
-        }
-        toSend = PR_MIN(len - totalSent, MAX_FRAGMENT_LENGTH);
-        /*
-         * Note that the 0 epoch is OK because flags will never require
-         * its use, as guaranteed by the PORT_Assert above.
-         */
-        sent = ssl3_SendRecord(ss, 0, content_application_data,
-                               in + totalSent, toSend, flags);
-        if (sent < 0) {
-            if (totalSent > 0 && PR_GetError() == PR_WOULD_BLOCK_ERROR) {
-                PORT_Assert(ss->lastWriteBlocked);
-                break;
-            }
-            return SECFailure; /* error code set by ssl3_SendRecord */
-        }
-        totalSent += sent;
-        if (ss->pendingBuf.len) {
-            /* must be a non-blocking socket */
-            PORT_Assert(!ssl_SocketIsBlocking(ss));
-            PORT_Assert(ss->lastWriteBlocked);
-            break;
-        }
-    }
-    if (ss->pendingBuf.len) {
-        /* Must be non-blocking. */
-        PORT_Assert(!ssl_SocketIsBlocking(ss));
-        if (totalSent > 0) {
-            ss->appDataBuffered = 0x100 | in[totalSent - 1];
-        }
-
-        totalSent = totalSent + discarded - 1;
-        if (totalSent <= 0) {
-            PORT_SetError(PR_WOULD_BLOCK_ERROR);
-            totalSent = SECFailure;
-        }
-        return totalSent;
-    }
-    ss->appDataBuffered = 0;
-    return totalSent + discarded;
-}
-
-/* Attempt to send buffered handshake messages.
- * This function returns SECSuccess or SECFailure, never SECWouldBlock.
- * Always set sendBuf.len to 0, even when returning SECFailure.
- *
- * Depending on whether we are doing DTLS or not, this either calls
- *
- * - ssl3_FlushHandshakeMessages if non-DTLS
- * - dtls_FlushHandshakeMessages if DTLS
- *
- * Called from SSL3_SendAlert(), ssl3_SendChangeCipherSpecs(),
- *             ssl3_AppendHandshake(), ssl3_SendClientHello(),
- *             ssl3_SendHelloRequest(), ssl3_SendServerHelloDone(),
- *             ssl3_SendFinished(),
- */
-SECStatus
-ssl3_FlushHandshake(sslSocket *ss, PRInt32 flags)
-{
-    if (IS_DTLS(ss)) {
-        return dtls_FlushHandshakeMessages(ss, flags);
-    } else {
-        return ssl3_FlushHandshakeMessages(ss, flags);
-    }
-}
-
-/* Attempt to send the content of sendBuf buffer in an SSL handshake record.
- * This function returns SECSuccess or SECFailure, never SECWouldBlock.
- * Always set sendBuf.len to 0, even when returning SECFailure.
- *
- * Called from ssl3_FlushHandshake
- */
-static SECStatus
-ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
-{
-    static const PRInt32 allowedFlags = ssl_SEND_FLAG_FORCE_INTO_BUFFER |
-                                        ssl_SEND_FLAG_CAP_RECORD_VERSION;
-    PRInt32 count = -1;
-    SECStatus rv = SECSuccess;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len)
-        return rv;
-
-    /* only these flags are allowed */
-    PORT_Assert(!(flags & ~allowedFlags));
-    if ((flags & ~allowedFlags) != 0) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        rv = SECFailure;
-    } else {
-        count = ssl3_SendRecord(ss, 0, content_handshake, ss->sec.ci.sendBuf.buf,
-                                ss->sec.ci.sendBuf.len, flags);
-    }
-    if (count < 0) {
-        int err = PORT_GetError();
-        PORT_Assert(err != PR_WOULD_BLOCK_ERROR);
-        if (err == PR_WOULD_BLOCK_ERROR) {
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        }
-        rv = SECFailure;
-    } else if ((unsigned int)count < ss->sec.ci.sendBuf.len) {
-        /* short write should never happen */
-        PORT_Assert((unsigned int)count >= ss->sec.ci.sendBuf.len);
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        rv = SECFailure;
-    } else {
-        rv = SECSuccess;
-    }
-
-    /* Whether we succeeded or failed, toss the old handshake data. */
-    ss->sec.ci.sendBuf.len = 0;
-    return rv;
-}
-
-/*
- * Called from ssl3_HandleAlert and from ssl3_HandleCertificate when
- * the remote client sends a negative response to our certificate request.
- * Returns SECFailure if the application has required client auth.
- *         SECSuccess otherwise.
- */
-static SECStatus
-ssl3_HandleNoCertificate(sslSocket *ss)
-{
-    if (ss->sec.peerCert != NULL) {
-        if (ss->sec.peerKey != NULL) {
-            SECKEY_DestroyPublicKey(ss->sec.peerKey);
-            ss->sec.peerKey = NULL;
-        }
-        CERT_DestroyCertificate(ss->sec.peerCert);
-        ss->sec.peerCert = NULL;
-    }
-    ssl3_CleanupPeerCerts(ss);
-
-    /* If the server has required client-auth blindly but doesn't
-     * actually look at the certificate it won't know that no
-     * certificate was presented so we shutdown the socket to ensure
-     * an error.  We only do this if we haven't already completed the
-     * first handshake because if we're redoing the handshake we
-     * know the server is paying attention to the certificate.
-     */
-    if ((ss->opt.requireCertificate == SSL_REQUIRE_ALWAYS) ||
-        (!ss->firstHsDone &&
-         (ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE))) {
-        PRFileDesc *lower;
-
-        if (ss->sec.uncache)
-            ss->sec.uncache(ss->sec.ci.sid);
-        SSL3_SendAlert(ss, alert_fatal, bad_certificate);
-
-        lower = ss->fd->lower;
-#ifdef _WIN32
-        lower->methods->shutdown(lower, PR_SHUTDOWN_SEND);
-#else
-        lower->methods->shutdown(lower, PR_SHUTDOWN_BOTH);
-#endif
-        PORT_SetError(SSL_ERROR_NO_CERTIFICATE);
-        return SECFailure;
-    }
-    return SECSuccess;
-}
-
-/************************************************************************
- * Alerts
- */
-
-/*
-** Acquires both handshake and XmitBuf locks.
-** Called from: ssl3_IllegalParameter   <-
-**              ssl3_HandshakeFailure   <-
-**              ssl3_HandleAlert    <- ssl3_HandleRecord.
-**              ssl3_HandleChangeCipherSpecs <- ssl3_HandleRecord
-**              ssl3_ConsumeHandshakeVariable <-
-**              ssl3_HandleHelloRequest <-
-**              ssl3_HandleServerHello  <-
-**              ssl3_HandleServerKeyExchange <-
-**              ssl3_HandleCertificateRequest <-
-**              ssl3_HandleServerHelloDone <-
-**              ssl3_HandleClientHello  <-
-**              ssl3_HandleV2ClientHello <-
-**              ssl3_HandleCertificateVerify <-
-**              ssl3_HandleClientKeyExchange <-
-**              ssl3_HandleCertificate  <-
-**              ssl3_HandleFinished <-
-**              ssl3_HandleHandshakeMessage <-
-**              ssl3_HandlePostHelloHandshakeMessage <-
-**              ssl3_HandleRecord   <-
-**
-*/
-SECStatus
-SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc)
-{
-    PRUint8 bytes[2];
-    SECStatus rv;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: send alert record, level=%d desc=%d",
-                SSL_GETPID(), ss->fd, level, desc));
-
-    bytes[0] = level;
-    bytes[1] = desc;
-
-    ssl_GetSSL3HandshakeLock(ss);
-    if (level == alert_fatal) {
-        if (!ss->opt.noCache && ss->sec.ci.sid && ss->sec.uncache) {
-            ss->sec.uncache(ss->sec.ci.sid);
-        }
-    }
-    ssl_GetXmitBufLock(ss);
-    rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
-    if (rv == SECSuccess) {
-        PRInt32 sent;
-        sent = ssl3_SendRecord(ss, 0, content_alert, bytes, 2,
-                               desc == no_certificate ? ssl_SEND_FLAG_FORCE_INTO_BUFFER : 0);
-        rv = (sent >= 0) ? SECSuccess : (SECStatus)sent;
-    }
-    if (level == alert_fatal) {
-        ss->ssl3.fatalAlertSent = PR_TRUE;
-    }
-    ssl_ReleaseXmitBufLock(ss);
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    return rv; /* error set by ssl3_FlushHandshake or ssl3_SendRecord */
-}
-
-/*
- * Send illegal_parameter alert.  Set generic error number.
- */
-static SECStatus
-ssl3_IllegalParameter(sslSocket *ss)
-{
-    (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
-    PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT
-                                   : SSL_ERROR_BAD_SERVER);
-    return SECFailure;
-}
-
-/*
- * Send handshake_Failure alert.  Set generic error number.
- */
-static SECStatus
-ssl3_HandshakeFailure(sslSocket *ss)
-{
-    (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure);
-    PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT
-                                   : SSL_ERROR_BAD_SERVER);
-    return SECFailure;
-}
-
-static void
-ssl3_SendAlertForCertError(sslSocket *ss, PRErrorCode errCode)
-{
-    SSL3AlertDescription desc = bad_certificate;
-    PRBool isTLS = ss->version >= SSL_LIBRARY_VERSION_3_1_TLS;
-
-    switch (errCode) {
-        case SEC_ERROR_LIBRARY_FAILURE:
-            desc = unsupported_certificate;
-            break;
-        case SEC_ERROR_EXPIRED_CERTIFICATE:
-            desc = certificate_expired;
-            break;
-        case SEC_ERROR_REVOKED_CERTIFICATE:
-            desc = certificate_revoked;
-            break;
-        case SEC_ERROR_INADEQUATE_KEY_USAGE:
-        case SEC_ERROR_INADEQUATE_CERT_TYPE:
-            desc = certificate_unknown;
-            break;
-        case SEC_ERROR_UNTRUSTED_CERT:
-            desc = isTLS ? access_denied : certificate_unknown;
-            break;
-        case SEC_ERROR_UNKNOWN_ISSUER:
-        case SEC_ERROR_UNTRUSTED_ISSUER:
-            desc = isTLS ? unknown_ca : certificate_unknown;
-            break;
-        case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
-            desc = isTLS ? unknown_ca : certificate_expired;
-            break;
-
-        case SEC_ERROR_CERT_NOT_IN_NAME_SPACE:
-        case SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID:
-        case SEC_ERROR_CA_CERT_INVALID:
-        case SEC_ERROR_BAD_SIGNATURE:
-        default:
-            desc = bad_certificate;
-            break;
-    }
-    SSL_DBG(("%d: SSL3[%d]: peer certificate is no good: error=%d",
-             SSL_GETPID(), ss->fd, errCode));
-
-    (void)SSL3_SendAlert(ss, alert_fatal, desc);
-}
-
-/*
- * Send decode_error alert.  Set generic error number.
- */
-SECStatus
-ssl3_DecodeError(sslSocket *ss)
-{
-    (void)SSL3_SendAlert(ss, alert_fatal,
-                         ss->version > SSL_LIBRARY_VERSION_3_0 ? decode_error
-                                                               : illegal_parameter);
-    PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT
-                                   : SSL_ERROR_BAD_SERVER);
-    return SECFailure;
-}
-
-/* Called from ssl3_HandleRecord.
-** Caller must hold both RecvBuf and Handshake locks.
-*/
-static SECStatus
-ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf)
-{
-    SSL3AlertLevel level;
-    SSL3AlertDescription desc;
-    int error;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    SSL_TRC(3, ("%d: SSL3[%d]: handle alert record", SSL_GETPID(), ss->fd));
-
-    if (buf->len != 2) {
-        (void)ssl3_DecodeError(ss);
-        PORT_SetError(SSL_ERROR_RX_MALFORMED_ALERT);
-        return SECFailure;
-    }
-    level = (SSL3AlertLevel)buf->buf[0];
-    desc = (SSL3AlertDescription)buf->buf[1];
-    buf->len = 0;
-    SSL_TRC(5, ("%d: SSL3[%d] received alert, level = %d, description = %d",
-                SSL_GETPID(), ss->fd, level, desc));
-
-    switch (desc) {
-        case close_notify:
-            ss->recvdCloseNotify = 1;
-            error = SSL_ERROR_CLOSE_NOTIFY_ALERT;
-            break;
-        case unexpected_message:
-            error = SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT;
-            break;
-        case bad_record_mac:
-            error = SSL_ERROR_BAD_MAC_ALERT;
-            break;
-        case decryption_failed_RESERVED:
-            error = SSL_ERROR_DECRYPTION_FAILED_ALERT;
-            break;
-        case record_overflow:
-            error = SSL_ERROR_RECORD_OVERFLOW_ALERT;
-            break;
-        case decompression_failure:
-            error = SSL_ERROR_DECOMPRESSION_FAILURE_ALERT;
-            break;
-        case handshake_failure:
-            error = SSL_ERROR_HANDSHAKE_FAILURE_ALERT;
-            break;
-        case no_certificate:
-            error = SSL_ERROR_NO_CERTIFICATE;
-            break;
-        case bad_certificate:
-            error = SSL_ERROR_BAD_CERT_ALERT;
-            break;
-        case unsupported_certificate:
-            error = SSL_ERROR_UNSUPPORTED_CERT_ALERT;
-            break;
-        case certificate_revoked:
-            error = SSL_ERROR_REVOKED_CERT_ALERT;
-            break;
-        case certificate_expired:
-            error = SSL_ERROR_EXPIRED_CERT_ALERT;
-            break;
-        case certificate_unknown:
-            error = SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT;
-            break;
-        case illegal_parameter:
-            error = SSL_ERROR_ILLEGAL_PARAMETER_ALERT;
-            break;
-        case inappropriate_fallback:
-            error = SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT;
-            break;
-
-        /* All alerts below are TLS only. */
-        case unknown_ca:
-            error = SSL_ERROR_UNKNOWN_CA_ALERT;
-            break;
-        case access_denied:
-            error = SSL_ERROR_ACCESS_DENIED_ALERT;
-            break;
-        case decode_error:
-            error = SSL_ERROR_DECODE_ERROR_ALERT;
-            break;
-        case decrypt_error:
-            error = SSL_ERROR_DECRYPT_ERROR_ALERT;
-            break;
-        case export_restriction:
-            error = SSL_ERROR_EXPORT_RESTRICTION_ALERT;
-            break;
-        case protocol_version:
-            error = SSL_ERROR_PROTOCOL_VERSION_ALERT;
-            break;
-        case insufficient_security:
-            error = SSL_ERROR_INSUFFICIENT_SECURITY_ALERT;
-            break;
-        case internal_error:
-            error = SSL_ERROR_INTERNAL_ERROR_ALERT;
-            break;
-        case user_canceled:
-            error = SSL_ERROR_USER_CANCELED_ALERT;
-            break;
-        case no_renegotiation:
-            error = SSL_ERROR_NO_RENEGOTIATION_ALERT;
-            break;
-
-        /* Alerts for TLS client hello extensions */
-        case missing_extension:
-            error = SSL_ERROR_MISSING_EXTENSION_ALERT;
-            break;
-        case unsupported_extension:
-            error = SSL_ERROR_UNSUPPORTED_EXTENSION_ALERT;
-            break;
-        case certificate_unobtainable:
-            error = SSL_ERROR_CERTIFICATE_UNOBTAINABLE_ALERT;
-            break;
-        case unrecognized_name:
-            error = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
-            break;
-        case bad_certificate_status_response:
-            error = SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT;
-            break;
-        case bad_certificate_hash_value:
-            error = SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT;
-            break;
-        default:
-            error = SSL_ERROR_RX_UNKNOWN_ALERT;
-            break;
-    }
-    if (level == alert_fatal) {
-        if (!ss->opt.noCache) {
-            if (ss->sec.uncache)
-                ss->sec.uncache(ss->sec.ci.sid);
-        }
-        if ((ss->ssl3.hs.ws == wait_server_hello) &&
-            (desc == handshake_failure)) {
-            /* XXX This is a hack.  We're assuming that any handshake failure
-             * XXX on the client hello is a failure to match ciphers.
-             */
-            error = SSL_ERROR_NO_CYPHER_OVERLAP;
-        }
-        PORT_SetError(error);
-        return SECFailure;
-    }
-    if ((desc == no_certificate) && (ss->ssl3.hs.ws == wait_client_cert)) {
-        /* I'm a server. I've requested a client cert. He hasn't got one. */
-        SECStatus rv;
-
-        PORT_Assert(ss->sec.isServer);
-        ss->ssl3.hs.ws = wait_client_key;
-        rv = ssl3_HandleNoCertificate(ss);
-        return rv;
-    }
-    return SECSuccess;
-}
-
-/*
- * Change Cipher Specs
- * Called from ssl3_HandleServerHelloDone,
- *             ssl3_HandleClientHello,
- * and         ssl3_HandleFinished
- *
- * Acquires and releases spec write lock, to protect switching the current
- * and pending write spec pointers.
- */
-
-static SECStatus
-ssl3_SendChangeCipherSpecs(sslSocket *ss)
-{
-    PRUint8 change = change_cipher_spec_choice;
-    ssl3CipherSpec *pwSpec;
-    SECStatus rv;
-    PRInt32 sent;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: send change_cipher_spec record",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
-    if (rv != SECSuccess) {
-        return rv; /* error code set by ssl3_FlushHandshake */
-    }
-    if (!IS_DTLS(ss)) {
-        sent = ssl3_SendRecord(ss, 0, content_change_cipher_spec, &change, 1,
-                               ssl_SEND_FLAG_FORCE_INTO_BUFFER);
-        if (sent < 0) {
-            return (SECStatus)sent; /* error code set by ssl3_SendRecord */
-        }
-    } else {
-        rv = dtls_QueueMessage(ss, content_change_cipher_spec, &change, 1);
-        if (rv != SECSuccess) {
-            return rv;
-        }
-    }
-
-    /* swap the pending and current write specs. */
-    ssl_GetSpecWriteLock(ss); /**************************************/
-    pwSpec = ss->ssl3.pwSpec;
-
-    ss->ssl3.pwSpec = ss->ssl3.cwSpec;
-    ss->ssl3.cwSpec = pwSpec;
-
-    SSL_TRC(3, ("%d: SSL3[%d] Set Current Write Cipher Suite to Pending",
-                SSL_GETPID(), ss->fd));
-
-    /* We need to free up the contexts, keys and certs ! */
-    /* If we are really through with the old cipher spec
-     * (Both the read and write sides have changed) destroy it.
-     */
-    if (ss->ssl3.prSpec == ss->ssl3.pwSpec) {
-        if (!IS_DTLS(ss)) {
-            ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE /*freeSrvName*/);
-        } else {
-            /* With DTLS, we need to set a holddown timer in case the final
-             * message got lost */
-            ss->ssl3.hs.rtTimeoutMs = DTLS_FINISHED_TIMER_MS;
-            dtls_StartTimer(ss, dtls_FinishedTimerCb);
-        }
-    }
-    ssl_ReleaseSpecWriteLock(ss); /**************************************/
-
-    return SECSuccess;
-}
-
-/* Called from ssl3_HandleRecord.
-** Caller must hold both RecvBuf and Handshake locks.
- *
- * Acquires and releases spec write lock, to protect switching the current
- * and pending write spec pointers.
-*/
-static SECStatus
-ssl3_HandleChangeCipherSpecs(sslSocket *ss, sslBuffer *buf)
-{
-    ssl3CipherSpec *prSpec;
-    SSL3WaitState ws = ss->ssl3.hs.ws;
-    SSL3ChangeCipherSpecChoice change;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    SSL_TRC(3, ("%d: SSL3[%d]: handle change_cipher_spec record",
-                SSL_GETPID(), ss->fd));
-
-    if (ws != wait_change_cipher) {
-        if (IS_DTLS(ss)) {
-            /* Ignore this because it's out of order. */
-            SSL_TRC(3, ("%d: SSL3[%d]: discard out of order "
-                        "DTLS change_cipher_spec",
-                        SSL_GETPID(), ss->fd));
-            buf->len = 0;
-            return SECSuccess;
-        }
-        (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-        PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER);
-        return SECFailure;
-    }
-
-    if (buf->len != 1) {
-        (void)ssl3_DecodeError(ss);
-        PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
-        return SECFailure;
-    }
-    change = (SSL3ChangeCipherSpecChoice)buf->buf[0];
-    if (change != change_cipher_spec_choice) {
-        /* illegal_parameter is correct here for both SSL3 and TLS. */
-        (void)ssl3_IllegalParameter(ss);
-        PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
-        return SECFailure;
-    }
-    buf->len = 0;
-
-    /* Swap the pending and current read specs. */
-    ssl_GetSpecWriteLock(ss); /*************************************/
-    prSpec = ss->ssl3.prSpec;
-
-    ss->ssl3.prSpec = ss->ssl3.crSpec;
-    ss->ssl3.crSpec = prSpec;
-    ss->ssl3.hs.ws = wait_finished;
-
-    SSL_TRC(3, ("%d: SSL3[%d] Set Current Read Cipher Suite to Pending",
-                SSL_GETPID(), ss->fd));
-
-    /* If we are really through with the old cipher prSpec
-     * (Both the read and write sides have changed) destroy it.
-     */
-    if (ss->ssl3.prSpec == ss->ssl3.pwSpec) {
-        ssl3_DestroyCipherSpec(ss->ssl3.prSpec, PR_FALSE /*freeSrvName*/);
-    }
-    ssl_ReleaseSpecWriteLock(ss); /*************************************/
-    return SECSuccess;
-}
-
-/* This method completes the derivation of the MS from the PMS.
-**
-** 1. Derive the MS, if possible, else return an error.
-**
-** 2. Check the version if |pms_version| is non-zero and if wrong,
-**    return an error.
-**
-** 3. If |msp| is nonzero, return MS in |*msp|.
-
-** Called from:
-**   ssl3_ComputeMasterSecretInt
-**   tls_ComputeExtendedMasterSecretInt
-*/
-static SECStatus
-ssl3_ComputeMasterSecretFinish(sslSocket *ss,
-                               CK_MECHANISM_TYPE master_derive,
-                               CK_MECHANISM_TYPE key_derive,
-                               CK_VERSION *pms_version,
-                               SECItem *params, CK_FLAGS keyFlags,
-                               PK11SymKey *pms, PK11SymKey **msp)
-{
-    PK11SymKey *ms = NULL;
-
-    ms = PK11_DeriveWithFlags(pms, master_derive,
-                              params, key_derive,
-                              CKA_DERIVE, 0, keyFlags);
-    if (!ms) {
-        ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
-        return SECFailure;
-    }
-
-    if (pms_version && ss->opt.detectRollBack) {
-        SSL3ProtocolVersion client_version;
-        client_version = pms_version->major << 8 | pms_version->minor;
-
-        if (IS_DTLS(ss)) {
-            client_version = dtls_DTLSVersionToTLSVersion(client_version);
-        }
-
-        if (client_version != ss->clientHelloVersion) {
-            /* Destroy MS.  Version roll-back detected. */
-            PK11_FreeSymKey(ms);
-            ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
-            return SECFailure;
-        }
-    }
-
-    if (msp) {
-        *msp = ms;
-    } else {
-        PK11_FreeSymKey(ms);
-    }
-
-    return SECSuccess;
-}
-
-/*  Compute the ordinary (pre draft-ietf-tls-session-hash) master
- ** secret and return it in |*msp|.
- **
- ** Called from: ssl3_ComputeMasterSecret
- */
-static SECStatus
-ssl3_ComputeMasterSecretInt(sslSocket *ss, PK11SymKey *pms,
-                            PK11SymKey **msp)
-{
-    ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
-    const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
-    unsigned char *cr = (unsigned char *)&ss->ssl3.hs.client_random;
-    unsigned char *sr = (unsigned char *)&ss->ssl3.hs.server_random;
-    PRBool isTLS = (PRBool)(kea_def->tls_keygen ||
-                            (pwSpec->version > SSL_LIBRARY_VERSION_3_0));
-    PRBool isTLS12 =
-        (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
-    /*
-     * Whenever isDH is true, we need to use CKM_TLS_MASTER_KEY_DERIVE_DH
-     * which, unlike CKM_TLS_MASTER_KEY_DERIVE, converts arbitrary size
-     * data into a 48-byte value, and does not expect to return the version.
-     */
-    PRBool isDH = (PRBool)((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) ||
-                           (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh));
-    CK_MECHANISM_TYPE master_derive;
-    CK_MECHANISM_TYPE key_derive;
-    SECItem params;
-    CK_FLAGS keyFlags;
-    CK_VERSION pms_version;
-    CK_VERSION *pms_version_ptr = NULL;
-    /* master_params may be used as a CK_SSL3_MASTER_KEY_DERIVE_PARAMS */
-    CK_TLS12_MASTER_KEY_DERIVE_PARAMS master_params;
-    unsigned int master_params_len;
-
-    if (isTLS12) {
-        if (isDH)
-            master_derive = CKM_TLS12_MASTER_KEY_DERIVE_DH;
-        else
-            master_derive = CKM_TLS12_MASTER_KEY_DERIVE;
-        key_derive = CKM_TLS12_KEY_AND_MAC_DERIVE;
-        keyFlags = CKF_SIGN | CKF_VERIFY;
-    } else if (isTLS) {
-        if (isDH)
-            master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH;
-        else
-            master_derive = CKM_TLS_MASTER_KEY_DERIVE;
-        key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
-        keyFlags = CKF_SIGN | CKF_VERIFY;
-    } else {
-        if (isDH)
-            master_derive = CKM_SSL3_MASTER_KEY_DERIVE_DH;
-        else
-            master_derive = CKM_SSL3_MASTER_KEY_DERIVE;
-        key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE;
-        keyFlags = 0;
-    }
-
-    if (!isDH) {
-        pms_version_ptr = &pms_version;
-    }
-
-    master_params.pVersion = pms_version_ptr;
-    master_params.RandomInfo.pClientRandom = cr;
-    master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
-    master_params.RandomInfo.pServerRandom = sr;
-    master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;
-    if (isTLS12) {
-        master_params.prfHashMechanism = CKM_SHA256;
-        master_params_len = sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS);
-    } else {
-        /* prfHashMechanism is not relevant with this PRF */
-        master_params_len = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS);
-    }
-
-    params.data = (unsigned char *)&master_params;
-    params.len = master_params_len;
-
-    return ssl3_ComputeMasterSecretFinish(ss, master_derive, key_derive,
-                                          pms_version_ptr, &params,
-                                          keyFlags, pms, msp);
-}
-
-/* Compute the draft-ietf-tls-session-hash master
-** secret and return it in |*msp|.
-**
-** Called from: ssl3_ComputeMasterSecret
-*/
-static SECStatus
-tls_ComputeExtendedMasterSecretInt(sslSocket *ss, PK11SymKey *pms,
-                                   PK11SymKey **msp)
-{
-    ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
-    CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS extended_master_params;
-    SSL3Hashes hashes;
-    /*
-     * Determine whether to use the DH/ECDH or RSA derivation modes.
-     */
-    /*
-     * TODO(ekr@rtfm.com): Verify that the slot can handle this key expansion
-     *  mode. Bug 1198298 */
-    PRBool isDH = (PRBool)((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) ||
-                           (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh));
-    CK_MECHANISM_TYPE master_derive;
-    CK_MECHANISM_TYPE key_derive;
-    SECItem params;
-    const CK_FLAGS keyFlags = CKF_SIGN | CKF_VERIFY;
-    CK_VERSION pms_version;
-    CK_VERSION *pms_version_ptr = NULL;
-    SECStatus rv;
-
-    rv = ssl3_ComputeHandshakeHashes(ss, pwSpec, &hashes, 0);
-    if (rv != SECSuccess) {
-        PORT_Assert(0); /* Should never fail */
-        ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
-        return SECFailure;
-    }
-
-    if (isDH) {
-        master_derive = CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH;
-    } else {
-        master_derive = CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE;
-        pms_version_ptr = &pms_version;
-    }
-
-    if (pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
-        /* TLS 1.2 */
-        extended_master_params.prfHashMechanism = CKM_SHA256;
-        key_derive = CKM_TLS12_KEY_AND_MAC_DERIVE;
-    } else {
-        /* TLS < 1.2 */
-        extended_master_params.prfHashMechanism = CKM_TLS_PRF;
-        key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
-    }
-
-    extended_master_params.pVersion = pms_version_ptr;
-    extended_master_params.pSessionHash = hashes.u.raw;
-    extended_master_params.ulSessionHashLen = hashes.len;
-
-    params.data = (unsigned char *)&extended_master_params;
-    params.len = sizeof extended_master_params;
-
-    return ssl3_ComputeMasterSecretFinish(ss, master_derive, key_derive,
-                                          pms_version_ptr, &params,
-                                          keyFlags, pms, msp);
-}
-
-/* Wrapper method to compute the master secret and return it in |*msp|.
-**
-** Called from ssl3_ComputeMasterSecret
-*/
-static SECStatus
-ssl3_ComputeMasterSecret(sslSocket *ss, PK11SymKey *pms,
-                         PK11SymKey **msp)
-{
-    PORT_Assert(pms != NULL);
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
-
-    if (ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) {
-        return tls_ComputeExtendedMasterSecretInt(ss, pms, msp);
-    } else {
-        return ssl3_ComputeMasterSecretInt(ss, pms, msp);
-    }
-}
-
-/* This method uses PKCS11 to derive the MS from the PMS, where PMS
-** is a PKCS11 symkey. We call ssl3_ComputeMasterSecret to do the
-** computations and then modify the pwSpec->state as a side effect.
-**
-** This is used in all cases except the "triple bypass" with RSA key
-** exchange.
-**
-** Called from ssl3_InitPendingCipherSpec.   prSpec is pwSpec.
-*/
-static SECStatus
-ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms)
-{
-    SECStatus rv;
-    PK11SymKey *ms = NULL;
-    ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
-    PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
-
-    if (pms) {
-        rv = ssl3_ComputeMasterSecret(ss, pms, &ms);
-        pwSpec->master_secret = ms;
-        if (rv != SECSuccess)
-            return rv;
-    }
-
-#ifndef NO_PKCS11_BYPASS
-    if (ss->opt.bypassPKCS11) {
-        SECItem *keydata;
-        /* In hope of doing a "double bypass",
-         * need to extract the master secret's value from the key object
-         * and store it raw in the sslSocket struct.
-         */
-        rv = PK11_ExtractKeyValue(pwSpec->master_secret);
-        if (rv != SECSuccess) {
-            return rv;
-        }
-        /* This returns the address of the secItem inside the key struct,
-         * not a copy or a reference.  So, there's no need to free it.
-         */
-        keydata = PK11_GetKeyData(pwSpec->master_secret);
-        if (keydata && keydata->len <= sizeof pwSpec->raw_master_secret) {
-            memcpy(pwSpec->raw_master_secret, keydata->data, keydata->len);
-            pwSpec->msItem.data = pwSpec->raw_master_secret;
-            pwSpec->msItem.len = keydata->len;
-        } else {
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            return SECFailure;
-        }
-    }
-#endif
-
-    return SECSuccess;
-}
-
-/*
- * Derive encryption and MAC Keys (and IVs) from master secret
- * Sets a useful error code when returning SECFailure.
- *
- * Called only from ssl3_InitPendingCipherSpec(),
- * which in turn is called from
- *              sendRSAClientKeyExchange        (for Full handshake)
- *              sendDHClientKeyExchange         (for Full handshake)
- *              ssl3_HandleClientKeyExchange    (for Full handshake)
- *              ssl3_HandleServerHello          (for session restart)
- *              ssl3_HandleClientHello          (for session restart)
- * Caller MUST hold the specWriteLock, and SSL3HandshakeLock.
- * ssl3_InitPendingCipherSpec does that.
- *
- */
-static SECStatus
-ssl3_DeriveConnectionKeysPKCS11(sslSocket *ss)
-{
-    ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
-    const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
-    unsigned char *cr = (unsigned char *)&ss->ssl3.hs.client_random;
-    unsigned char *sr = (unsigned char *)&ss->ssl3.hs.server_random;
-    PRBool isTLS = (PRBool)(kea_def->tls_keygen ||
-                            (pwSpec->version > SSL_LIBRARY_VERSION_3_0));
-    PRBool isTLS12 =
-        (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
-    /* following variables used in PKCS11 path */
-    const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def;
-    PK11SlotInfo *slot = NULL;
-    PK11SymKey *symKey = NULL;
-    void *pwArg = ss->pkcs11PinArg;
-    int keySize;
-    CK_TLS12_KEY_MAT_PARAMS key_material_params; /* may be used as a
-                                                  * CK_SSL3_KEY_MAT_PARAMS */
-    unsigned int key_material_params_len;
-    CK_SSL3_KEY_MAT_OUT returnedKeys;
-    CK_MECHANISM_TYPE key_derive;
-    CK_MECHANISM_TYPE bulk_mechanism;
-    SSLCipherAlgorithm calg;
-    SECItem params;
-    PRBool skipKeysAndIVs = (PRBool)(cipher_def->calg == calg_null);
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
-    PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
-
-    if (!pwSpec->master_secret) {
-        PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
-        return SECFailure;
-    }
-    /*
-     * generate the key material
-     */
-    key_material_params.ulMacSizeInBits = pwSpec->mac_size * BPB;
-    key_material_params.ulKeySizeInBits = cipher_def->secret_key_size * BPB;
-    key_material_params.ulIVSizeInBits = cipher_def->iv_size * BPB;
-    if (cipher_def->type == type_block &&
-        pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
-        /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */
-        key_material_params.ulIVSizeInBits = 0;
-        memset(pwSpec->client.write_iv, 0, cipher_def->iv_size);
-        memset(pwSpec->server.write_iv, 0, cipher_def->iv_size);
-    }
-
-    key_material_params.bIsExport = (CK_BBOOL)(kea_def->is_limited);
-
-    key_material_params.RandomInfo.pClientRandom = cr;
-    key_material_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
-    key_material_params.RandomInfo.pServerRandom = sr;
-    key_material_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;
-    key_material_params.pReturnedKeyMaterial = &returnedKeys;
-
-    returnedKeys.pIVClient = pwSpec->client.write_iv;
-    returnedKeys.pIVServer = pwSpec->server.write_iv;
-    keySize = cipher_def->key_size;
-
-    if (skipKeysAndIVs) {
-        keySize = 0;
-        key_material_params.ulKeySizeInBits = 0;
-        key_material_params.ulIVSizeInBits = 0;
-        returnedKeys.pIVClient = NULL;
-        returnedKeys.pIVServer = NULL;
-    }
-
-    calg = cipher_def->calg;
-    bulk_mechanism = ssl3_Alg2Mech(calg);
-
-    if (isTLS12) {
-        key_derive = CKM_TLS12_KEY_AND_MAC_DERIVE;
-        key_material_params.prfHashMechanism = CKM_SHA256;
-        key_material_params_len = sizeof(CK_TLS12_KEY_MAT_PARAMS);
-    } else if (isTLS) {
-        key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
-        key_material_params_len = sizeof(CK_SSL3_KEY_MAT_PARAMS);
-    } else {
-        key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE;
-        key_material_params_len = sizeof(CK_SSL3_KEY_MAT_PARAMS);
-    }
-
-    params.data = (unsigned char *)&key_material_params;
-    params.len = key_material_params_len;
-
-    /* CKM_SSL3_KEY_AND_MAC_DERIVE is defined to set ENCRYPT, DECRYPT, and
-     * DERIVE by DEFAULT */
-    symKey = PK11_Derive(pwSpec->master_secret, key_derive, &params,
-                         bulk_mechanism, CKA_ENCRYPT, keySize);
-    if (!symKey) {
-        ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
-        return SECFailure;
-    }
-    /* we really should use the actual mac'ing mechanism here, but we
-     * don't because these types are used to map keytype anyway and both
-     * mac's map to the same keytype.
-     */
-    slot = PK11_GetSlotFromKey(symKey);
-
-    PK11_FreeSlot(slot); /* slot is held until the key is freed */
-    pwSpec->client.write_mac_key =
-        PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,
-                              CKM_SSL3_SHA1_MAC, returnedKeys.hClientMacSecret, PR_TRUE, pwArg);
-    if (pwSpec->client.write_mac_key == NULL) {
-        goto loser; /* loser sets err */
-    }
-    pwSpec->server.write_mac_key =
-        PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,
-                              CKM_SSL3_SHA1_MAC, returnedKeys.hServerMacSecret, PR_TRUE, pwArg);
-    if (pwSpec->server.write_mac_key == NULL) {
-        goto loser; /* loser sets err */
-    }
-    if (!skipKeysAndIVs) {
-        pwSpec->client.write_key =
-            PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,
-                                  bulk_mechanism, returnedKeys.hClientKey, PR_TRUE, pwArg);
-        if (pwSpec->client.write_key == NULL) {
-            goto loser; /* loser sets err */
-        }
-        pwSpec->server.write_key =
-            PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,
-                                  bulk_mechanism, returnedKeys.hServerKey, PR_TRUE, pwArg);
-        if (pwSpec->server.write_key == NULL) {
-            goto loser; /* loser sets err */
-        }
-    }
-    PK11_FreeSymKey(symKey);
-    return SECSuccess;
-
-loser:
-    if (symKey)
-        PK11_FreeSymKey(symKey);
-    ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
-    return SECFailure;
-}
-
-/* ssl3_InitHandshakeHashes creates handshake hash contexts and hashes in
- * buffered messages in ss->ssl3.hs.messages. */
-static SECStatus
-ssl3_InitHandshakeHashes(sslSocket *ss)
-{
-    SSL_TRC(30, ("%d: SSL3[%d]: start handshake hashes", SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->ssl3.hs.hashType == handshake_hash_unknown);
-#ifndef NO_PKCS11_BYPASS
-    if (ss->opt.bypassPKCS11) {
-        PORT_Assert(!ss->ssl3.hs.sha_obj && !ss->ssl3.hs.sha_clone);
-        if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
-            /* If we ever support ciphersuites where the PRF hash isn't SHA-256
-             * then this will need to be updated. */
-            ss->ssl3.hs.sha_obj = HASH_GetRawHashObject(HASH_AlgSHA256);
-            if (!ss->ssl3.hs.sha_obj) {
-                ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
-                return SECFailure;
-            }
-            ss->ssl3.hs.sha_clone = (void (*)(void *, void *))SHA256_Clone;
-            ss->ssl3.hs.hashType = handshake_hash_single;
-            ss->ssl3.hs.sha_obj->begin(ss->ssl3.hs.sha_cx);
-        } else {
-            ss->ssl3.hs.hashType = handshake_hash_combo;
-            MD5_Begin((MD5Context *)ss->ssl3.hs.md5_cx);
-            SHA1_Begin((SHA1Context *)ss->ssl3.hs.sha_cx);
-        }
-    } else
-#endif
-    {
-        PORT_Assert(!ss->ssl3.hs.md5 && !ss->ssl3.hs.sha);
-        /*
-         * note: We should probably lookup an SSL3 slot for these
-         * handshake hashes in hopes that we wind up with the same slots
-         * that the master secret will wind up in ...
-         */
-        if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
-            /* If we ever support ciphersuites where the PRF hash isn't SHA-256
-             * then this will need to be updated. */
-            ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA256);
-            if (ss->ssl3.hs.sha == NULL) {
-                ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
-                return SECFailure;
-            }
-            ss->ssl3.hs.hashType = handshake_hash_single;
-
-            if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) {
-                ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
-                return SECFailure;
-            }
-
-            /* Create a backup SHA-1 hash for a potential client auth
-             * signature.
-             *
-             * In TLS 1.2, ssl3_ComputeHandshakeHashes always uses the
-             * handshake hash function (SHA-256). If the server or the client
-             * does not support SHA-256 as a signature hash, we can either
-             * maintain a backup SHA-1 handshake hash or buffer all handshake
-             * messages.
-             */
-            if (!ss->sec.isServer) {
-                ss->ssl3.hs.backupHash = PK11_CreateDigestContext(SEC_OID_SHA1);
-                if (ss->ssl3.hs.backupHash == NULL) {
-                    ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
-                    return SECFailure;
-                }
-
-                if (PK11_DigestBegin(ss->ssl3.hs.backupHash) != SECSuccess) {
-                    ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
-                    return SECFailure;
-                }
-            }
-        } else {
-            /* Both ss->ssl3.hs.md5 and ss->ssl3.hs.sha should be NULL or
-             * created successfully. */
-            ss->ssl3.hs.md5 = PK11_CreateDigestContext(SEC_OID_MD5);
-            if (ss->ssl3.hs.md5 == NULL) {
-                ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
-                return SECFailure;
-            }
-            ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA1);
-            if (ss->ssl3.hs.sha == NULL) {
-                PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
-                ss->ssl3.hs.md5 = NULL;
-                ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
-                return SECFailure;
-            }
-            ss->ssl3.hs.hashType = handshake_hash_combo;
-
-            if (PK11_DigestBegin(ss->ssl3.hs.md5) != SECSuccess) {
-                ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
-                return SECFailure;
-            }
-            if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) {
-                ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
-                return SECFailure;
-            }
-        }
-    }
-
-    if (ss->ssl3.hs.messages.len > 0) {
-        if (ssl3_UpdateHandshakeHashes(ss, ss->ssl3.hs.messages.buf,
-                                       ss->ssl3.hs.messages.len) !=
-            SECSuccess) {
-            return SECFailure;
-        }
-        PORT_Free(ss->ssl3.hs.messages.buf);
-        ss->ssl3.hs.messages.buf = NULL;
-        ss->ssl3.hs.messages.len = 0;
-        ss->ssl3.hs.messages.space = 0;
-    }
-
-    return SECSuccess;
-}
-
-static SECStatus
-ssl3_RestartHandshakeHashes(sslSocket *ss)
-{
-    SECStatus rv = SECSuccess;
-
-    SSL_TRC(30, ("%d: SSL3[%d]: reset handshake hashes",
-                 SSL_GETPID(), ss->fd));
-    ss->ssl3.hs.hashType = handshake_hash_unknown;
-    ss->ssl3.hs.messages.len = 0;
-#ifndef NO_PKCS11_BYPASS
-    ss->ssl3.hs.sha_obj = NULL;
-    ss->ssl3.hs.sha_clone = NULL;
-#endif
-    if (ss->ssl3.hs.md5) {
-        PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
-        ss->ssl3.hs.md5 = NULL;
-    }
-    if (ss->ssl3.hs.sha) {
-        PK11_DestroyContext(ss->ssl3.hs.sha, PR_TRUE);
-        ss->ssl3.hs.sha = NULL;
-    }
-    return rv;
-}
-
-/*
- * Handshake messages
- */
-/* Called from  ssl3_InitHandshakeHashes()
-**      ssl3_AppendHandshake()
-**      ssl3_StartHandshakeHash()
-**      ssl3_HandleV2ClientHello()
-**      ssl3_HandleHandshakeMessage()
-** Caller must hold the ssl3Handshake lock.
-*/
-static SECStatus
-ssl3_UpdateHandshakeHashes(sslSocket *ss, const unsigned char *b,
-                           unsigned int l)
-{
-    SECStatus rv = SECSuccess;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    /* We need to buffer the handshake messages until we have established
-     * which handshake hash function to use. */
-    if (ss->ssl3.hs.hashType == handshake_hash_unknown) {
-        return sslBuffer_Append(&ss->ssl3.hs.messages, b, l);
-    }
-
-    PRINT_BUF(90, (NULL, "handshake hash input:", b, l));
-
-#ifndef NO_PKCS11_BYPASS
-    if (ss->opt.bypassPKCS11) {
-        if (ss->ssl3.hs.hashType == handshake_hash_single) {
-            ss->ssl3.hs.sha_obj->update(ss->ssl3.hs.sha_cx, b, l);
-        } else {
-            MD5_Update((MD5Context *)ss->ssl3.hs.md5_cx, b, l);
-            SHA1_Update((SHA1Context *)ss->ssl3.hs.sha_cx, b, l);
-        }
-        return rv;
-    }
-#endif
-    if (ss->ssl3.hs.hashType == handshake_hash_single) {
-        rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l);
-        if (rv != SECSuccess) {
-            ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
-            return rv;
-        }
-        if (ss->ssl3.hs.backupHash) {
-            rv = PK11_DigestOp(ss->ssl3.hs.backupHash, b, l);
-            if (rv != SECSuccess) {
-                ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
-                return rv;
-            }
-        }
-    } else {
-        rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l);
-        if (rv != SECSuccess) {
-            ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
-            return rv;
-        }
-        rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l);
-        if (rv != SECSuccess) {
-            ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
-            return rv;
-        }
-    }
-    return rv;
-}
-
-/**************************************************************************
- * Append Handshake functions.
- * All these functions set appropriate error codes.
- * Most rely on ssl3_AppendHandshake to set the error code.
- **************************************************************************/
-SECStatus
-ssl3_AppendHandshake(sslSocket *ss, const void *void_src, PRInt32 bytes)
-{
-    unsigned char *src = (unsigned char *)void_src;
-    int room = ss->sec.ci.sendBuf.space - ss->sec.ci.sendBuf.len;
-    SECStatus rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); /* protects sendBuf. */
-
-    if (!bytes)
-        return SECSuccess;
-    if (ss->sec.ci.sendBuf.space < MAX_SEND_BUF_LENGTH && room < bytes) {
-        rv = sslBuffer_Grow(&ss->sec.ci.sendBuf, PR_MAX(MIN_SEND_BUF_LENGTH,
-                                                        PR_MIN(MAX_SEND_BUF_LENGTH, ss->sec.ci.sendBuf.len + bytes)));
-        if (rv != SECSuccess)
-            return rv; /* sslBuffer_Grow has set a memory error code. */
-        room = ss->sec.ci.sendBuf.space - ss->sec.ci.sendBuf.len;
-    }
-
-    PRINT_BUF(60, (ss, "Append to Handshake", (unsigned char *)void_src, bytes));
-    rv = ssl3_UpdateHandshakeHashes(ss, src, bytes);
-    if (rv != SECSuccess)
-        return rv; /* error code set by ssl3_UpdateHandshakeHashes */
-
-    while (bytes > room) {
-        if (room > 0)
-            PORT_Memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, src,
-                        room);
-        ss->sec.ci.sendBuf.len += room;
-        rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
-        if (rv != SECSuccess) {
-            return rv; /* error code set by ssl3_FlushHandshake */
-        }
-        bytes -= room;
-        src += room;
-        room = ss->sec.ci.sendBuf.space;
-        PORT_Assert(ss->sec.ci.sendBuf.len == 0);
-    }
-    PORT_Memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, src, bytes);
-    ss->sec.ci.sendBuf.len += bytes;
-    return SECSuccess;
-}
-
-SECStatus
-ssl3_AppendHandshakeNumber(sslSocket *ss, PRInt32 num, PRInt32 lenSize)
-{
-    SECStatus rv;
-    PRUint8 b[4];
-    PRUint8 *p = b;
-
-    PORT_Assert(lenSize <= 4 && lenSize > 0);
-    if (lenSize < 4 && num >= (1L << (lenSize * 8))) {
-        PORT_SetError(SSL_ERROR_TX_RECORD_TOO_LONG);
-        return SECFailure;
-    }
-
-    switch (lenSize) {
-        case 4:
-            *p++ = (num >> 24) & 0xff;
-        case 3:
-            *p++ = (num >> 16) & 0xff;
-        case 2:
-            *p++ = (num >> 8) & 0xff;
-        case 1:
-            *p = num & 0xff;
-    }
-    SSL_TRC(60, ("%d: number:", SSL_GETPID()));
-    rv = ssl3_AppendHandshake(ss, &b[0], lenSize);
-    return rv; /* error code set by AppendHandshake, if applicable. */
-}
-
-SECStatus
-ssl3_AppendHandshakeVariable(
-    sslSocket *ss, const SSL3Opaque *src, PRInt32 bytes, PRInt32 lenSize)
-{
-    SECStatus rv;
-
-    PORT_Assert((bytes < (1 << 8) && lenSize == 1) ||
-                (bytes < (1L << 16) && lenSize == 2) ||
-                (bytes < (1L << 24) && lenSize == 3));
-
-    SSL_TRC(60, ("%d: append variable:", SSL_GETPID()));
-    rv = ssl3_AppendHandshakeNumber(ss, bytes, lenSize);
-    if (rv != SECSuccess) {
-        return rv; /* error code set by AppendHandshake, if applicable. */
-    }
-    SSL_TRC(60, ("data:"));
-    rv = ssl3_AppendHandshake(ss, src, bytes);
-    return rv; /* error code set by AppendHandshake, if applicable. */
-}
-
-SECStatus
-ssl3_AppendHandshakeHeader(sslSocket *ss, SSL3HandshakeType t, PRUint32 length)
-{
-    SECStatus rv;
-
-    /* If we already have a message in place, we need to enqueue it.
-     * This empties the buffer. This is a convenient place to call
-     * dtls_StageHandshakeMessage to mark the message boundary.
-     */
-    if (IS_DTLS(ss)) {
-        rv = dtls_StageHandshakeMessage(ss);
-        if (rv != SECSuccess) {
-            return rv;
-        }
-    }
-
-    SSL_TRC(30, ("%d: SSL3[%d]: append handshake header: type %s",
-                 SSL_GETPID(), ss->fd, ssl3_DecodeHandshakeType(t)));
-
-    rv = ssl3_AppendHandshakeNumber(ss, t, 1);
-    if (rv != SECSuccess) {
-        return rv; /* error code set by AppendHandshake, if applicable. */
-    }
-    rv = ssl3_AppendHandshakeNumber(ss, length, 3);
-    if (rv != SECSuccess) {
-        return rv; /* error code set by AppendHandshake, if applicable. */
-    }
-
-    if (IS_DTLS(ss)) {
-        /* Note that we make an unfragmented message here. We fragment in the
-         * transmission code, if necessary */
-        rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.sendMessageSeq, 2);
-        if (rv != SECSuccess) {
-            return rv; /* error code set by AppendHandshake, if applicable. */
-        }
-        ss->ssl3.hs.sendMessageSeq++;
-
-        /* 0 is the fragment offset, because it's not fragmented yet */
-        rv = ssl3_AppendHandshakeNumber(ss, 0, 3);
-        if (rv != SECSuccess) {
-            return rv; /* error code set by AppendHandshake, if applicable. */
-        }
-
-        /* Fragment length -- set to the packet length because not fragmented */
-        rv = ssl3_AppendHandshakeNumber(ss, length, 3);
-        if (rv != SECSuccess) {
-            return rv; /* error code set by AppendHandshake, if applicable. */
-        }
-    }
-
-    return rv; /* error code set by AppendHandshake, if applicable. */
-}
-
-/* ssl3_AppendSignatureAndHashAlgorithm appends the serialisation of
- * |sigAndHash| to the current handshake message. */
-SECStatus
-ssl3_AppendSignatureAndHashAlgorithm(
-    sslSocket *ss, const SSLSignatureAndHashAlg *sigAndHash)
-{
-    PRUint8 serialized[2];
-
-    serialized[0] = (PRUint8)sigAndHash->hashAlg;
-    serialized[1] = (PRUint8)sigAndHash->sigAlg;
-
-    return ssl3_AppendHandshake(ss, serialized, sizeof(serialized));
-}
-
-/**************************************************************************
- * Consume Handshake functions.
- *
- * All data used in these functions is protected by two locks,
- * the RecvBufLock and the SSL3HandshakeLock
- **************************************************************************/
-
-/* Read up the next "bytes" number of bytes from the (decrypted) input
- * stream "b" (which is *length bytes long). Copy them into buffer "v".
- * Reduces *length by bytes.  Advances *b by bytes.
- *
- * If this function returns SECFailure, it has already sent an alert,
- * and has set a generic error code.  The caller should probably
- * override the generic error code by setting another.
- */
-SECStatus
-ssl3_ConsumeHandshake(sslSocket *ss, void *v, PRInt32 bytes, SSL3Opaque **b,
-                      PRUint32 *length)
-{
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if ((PRUint32)bytes > *length) {
-        return ssl3_DecodeError(ss);
-    }
-    PORT_Memcpy(v, *b, bytes);
-    PRINT_BUF(60, (ss, "consume bytes:", *b, bytes));
-    *b += bytes;
-    *length -= bytes;
-    return SECSuccess;
-}
-
-/* Read up the next "bytes" number of bytes from the (decrypted) input
- * stream "b" (which is *length bytes long), and interpret them as an
- * integer in network byte order.  Returns the received value.
- * Reduces *length by bytes.  Advances *b by bytes.
- *
- * Returns SECFailure (-1) on failure.
- * This value is indistinguishable from the equivalent received value.
- * Only positive numbers are to be received this way.
- * Thus, the largest value that may be sent this way is 0x7fffffff.
- * On error, an alert has been sent, and a generic error code has been set.
- */
-PRInt32
-ssl3_ConsumeHandshakeNumber(sslSocket *ss, PRInt32 bytes, SSL3Opaque **b,
-                            PRUint32 *length)
-{
-    PRUint8 *buf = *b;
-    int i;
-    PRInt32 num = 0;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(bytes <= sizeof num);
-
-    if ((PRUint32)bytes > *length) {
-        return ssl3_DecodeError(ss);
-    }
-    PRINT_BUF(60, (ss, "consume bytes:", *b, bytes));
-
-    for (i = 0; i < bytes; i++)
-        num = (num << 8) + buf[i];
-    *b += bytes;
-    *length -= bytes;
-    return num;
-}
-
-/* Read in two values from the incoming decrypted byte stream "b", which is
- * *length bytes long.  The first value is a number whose size is "bytes"
- * bytes long.  The second value is a byte-string whose size is the value
- * of the first number received.  The latter byte-string, and its length,
- * is returned in the SECItem i.
- *
- * Returns SECFailure (-1) on failure.
- * On error, an alert has been sent, and a generic error code has been set.
- *
- * RADICAL CHANGE for NSS 3.11.  All callers of this function make copies
- * of the data returned in the SECItem *i, so making a copy of it here
- * is simply wasteful.  So, This function now just sets SECItem *i to
- * point to the values in the buffer **b.
- */
-SECStatus
-ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, PRInt32 bytes,
-                              SSL3Opaque **b, PRUint32 *length)
-{
-    PRInt32 count;
-
-    PORT_Assert(bytes <= 3);
-    i->len = 0;
-    i->data = NULL;
-    i->type = siBuffer;
-    count = ssl3_ConsumeHandshakeNumber(ss, bytes, b, length);
-    if (count < 0) { /* Can't test for SECSuccess here. */
-        return SECFailure;
-    }
-    if (count > 0) {
-        if ((PRUint32)count > *length) {
-            return ssl3_DecodeError(ss);
-        }
-        i->data = *b;
-        i->len = count;
-        *b += count;
-        *length -= count;
-    }
-    return SECSuccess;
-}
-
-/* tlsHashOIDMap contains the mapping between TLS hash identifiers and the
- * SECOidTag used internally by NSS. */
-static const struct {
-    SSLHashType tlsHash;
-    SECOidTag oid;
-} tlsHashOIDMap[] = {
-    { ssl_hash_sha1, SEC_OID_SHA1 },
-    { ssl_hash_sha256, SEC_OID_SHA256 },
-    { ssl_hash_sha384, SEC_OID_SHA384 },
-    { ssl_hash_sha512, SEC_OID_SHA512 }
-};
-
-/* ssl3_TLSHashAlgorithmToOID converts a TLS hash identifier into an OID value.
- * If the hash is not recognised, SEC_OID_UNKNOWN is returned.
- *
- * See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
-SECOidTag
-ssl3_TLSHashAlgorithmToOID(SSLHashType hashFunc)
-{
-    unsigned int i;
-
-    for (i = 0; i < PR_ARRAY_SIZE(tlsHashOIDMap); i++) {
-        if (hashFunc == tlsHashOIDMap[i].tlsHash) {
-            return tlsHashOIDMap[i].oid;
-        }
-    }
-    return SEC_OID_UNKNOWN;
-}
-
-/* ssl3_TLSSignatureAlgorithmForKeyType returns the TLS 1.2 signature algorithm
- * identifier for a given KeyType. */
-static SECStatus
-ssl3_TLSSignatureAlgorithmForKeyType(KeyType keyType, SSLSignType *out)
-{
-    switch (keyType) {
-        case rsaKey:
-            *out = ssl_sign_rsa;
-            return SECSuccess;
-        case dsaKey:
-            *out = ssl_sign_dsa;
-            return SECSuccess;
-        case ecKey:
-            *out = ssl_sign_ecdsa;
-            return SECSuccess;
-        default:
-            PORT_SetError(SEC_ERROR_INVALID_KEY);
-            return SECFailure;
-    }
-}
-
-/* ssl3_TLSSignatureAlgorithmForCertificate returns the TLS 1.2 signature
- * algorithm identifier for the given certificate. */
-static SECStatus
-ssl3_TLSSignatureAlgorithmForCertificate(CERTCertificate *cert,
-                                         SSLSignType *out)
-{
-    SECKEYPublicKey *key;
-    KeyType keyType;
-
-    key = CERT_ExtractPublicKey(cert);
-    if (key == NULL) {
-        ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
-        return SECFailure;
-    }
-
-    keyType = key->keyType;
-    SECKEY_DestroyPublicKey(key);
-    return ssl3_TLSSignatureAlgorithmForKeyType(keyType, out);
-}
-
-/* ssl3_CheckSignatureAndHashAlgorithmConsistency checks that the signature
- * algorithm identifier in |sigAndHash| is consistent with the public key in
- * |cert|. It also checks the hash algorithm against the configured signature
- * algorithms.  If all the tests pass, SECSuccess is returned. Otherwise,
- * PORT_SetError is called and SECFailure is returned. */
-SECStatus
-ssl3_CheckSignatureAndHashAlgorithmConsistency(
-    sslSocket *ss, const SSLSignatureAndHashAlg *sigAndHash,
-    CERTCertificate *cert)
-{
-    SECStatus rv;
-    SSLSignType sigAlg;
-    unsigned int i;
-
-    /* If we're a client, check that the signature algorithm matches the signing
-     * key type of the cipher suite. */
-    if (!ss->sec.isServer &&
-        ss->ssl3.hs.kea_def->signKeyType != sigAndHash->sigAlg) {
-        PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
-        return SECFailure;
-    }
-
-    /* Verify that the signature algorithm used for the
-     * signature matches the signing key. */
-    rv = ssl3_TLSSignatureAlgorithmForCertificate(cert, &sigAlg);
-    if (rv != SECSuccess) {
-        return rv;
-    }
-    if (sigAlg != sigAndHash->sigAlg) {
-        PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
-        return SECFailure;
-    }
-
-    for (i = 0; i < ss->ssl3.signatureAlgorithmCount; ++i) {
-        const SSLSignatureAndHashAlg *alg = &ss->ssl3.signatureAlgorithms[i];
-        if (sigAndHash->sigAlg == alg->sigAlg &&
-            sigAndHash->hashAlg == alg->hashAlg) {
-            return SECSuccess;
-        }
-    }
-    PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
-    return SECFailure;
-}
-
-PRBool
-ssl3_IsSupportedSignatureAlgorithm(const SSLSignatureAndHashAlg *alg)
-{
-    static const SSLHashType supportedHashes[] = {
-        ssl_hash_sha1,
-        ssl_hash_sha256,
-        ssl_hash_sha384,
-        ssl_hash_sha512
-    };
-
-    static const SSLSignType supportedSigAlgs[] = {
-        ssl_sign_rsa,
-#ifndef NSS_DISABLE_ECC
-        ssl_sign_ecdsa,
-#endif
-        ssl_sign_dsa
-    };
-
-    unsigned int i;
-    PRBool hashOK = PR_FALSE;
-    PRBool signOK = PR_FALSE;
-
-    for (i = 0; i < PR_ARRAY_SIZE(supportedHashes); ++i) {
-        if (alg->hashAlg == supportedHashes[i]) {
-            hashOK = PR_TRUE;
-            break;
-        }
-    }
-
-    for (i = 0; i < PR_ARRAY_SIZE(supportedSigAlgs); ++i) {
-        if (alg->sigAlg == supportedSigAlgs[i]) {
-            signOK = PR_TRUE;
-            break;
-        }
-    }
-
-    return hashOK && signOK;
-}
-
-/* ssl3_ConsumeSignatureAndHashAlgorithm reads a SignatureAndHashAlgorithm
- * structure from |b| and puts the resulting value into |out|. |b| and |length|
- * are updated accordingly.
- *
- * See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
-SECStatus
-ssl3_ConsumeSignatureAndHashAlgorithm(sslSocket *ss,
-                                      SSL3Opaque **b,
-                                      PRUint32 *length,
-                                      SSLSignatureAndHashAlg *out)
-{
-    PRUint8 bytes[2];
-    SECStatus rv;
-
-    rv = ssl3_ConsumeHandshake(ss, bytes, sizeof(bytes), b, length);
-    if (rv != SECSuccess) {
-        return rv;
-    }
-
-    out->hashAlg = (SSLHashType)bytes[0];
-    out->sigAlg = (SSLSignType)bytes[1];
-    if (!ssl3_IsSupportedSignatureAlgorithm(out)) {
-        PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
-        return SECFailure;
-    }
-    return SECSuccess;
-}
-
-/**************************************************************************
- * end of Consume Handshake functions.
- **************************************************************************/
-
-/* Extract the hashes of handshake messages to this point.
- * Called from ssl3_SendCertificateVerify
- *             ssl3_SendFinished
- *             ssl3_HandleHandshakeMessage
- *
- * Caller must hold the SSL3HandshakeLock.
- * Caller must hold a read or write lock on the Spec R/W lock.
- *  (There is presently no way to assert on a Read lock.)
- */
-SECStatus
-ssl3_ComputeHandshakeHashes(sslSocket *ss,
-                            ssl3CipherSpec *spec, /* uses ->master_secret */
-                            SSL3Hashes *hashes,   /* output goes here. */
-                            PRUint32 sender)
-{
-    SECStatus rv = SECSuccess;
-    PRBool isTLS = (PRBool)(spec->version > SSL_LIBRARY_VERSION_3_0);
-    unsigned int outLength;
-    SSL3Opaque md5_inner[MAX_MAC_LENGTH];
-    SSL3Opaque sha_inner[MAX_MAC_LENGTH];
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    if (ss->ssl3.hs.hashType == handshake_hash_unknown) {
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        return SECFailure;
-    }
-
-    hashes->hashAlg = ssl_hash_none;
-
-#ifndef NO_PKCS11_BYPASS
-    if (ss->opt.bypassPKCS11 &&
-        ss->ssl3.hs.hashType == handshake_hash_single) {
-        /* compute them without PKCS11 */
-        PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS];
-
-        ss->ssl3.hs.sha_clone(sha_cx, ss->ssl3.hs.sha_cx);
-        ss->ssl3.hs.sha_obj->end(sha_cx, hashes->u.raw, &hashes->len,
-                                 sizeof(hashes->u.raw));
-
-        PRINT_BUF(60, (NULL, "SHA-256: result", hashes->u.raw, hashes->len));
-
-        /* If we ever support ciphersuites where the PRF hash isn't SHA-256
-         * then this will need to be updated. */
-        hashes->hashAlg = ssl_hash_sha256;
-        rv = SECSuccess;
-    } else if (ss->opt.bypassPKCS11) {
-        /* compute them without PKCS11 */
-        PRUint64 md5_cx[MAX_MAC_CONTEXT_LLONGS];
-        PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS];
-
-#define md5cx ((MD5Context *)md5_cx)
-#define shacx ((SHA1Context *)sha_cx)
-
-        MD5_Clone(md5cx, (MD5Context *)ss->ssl3.hs.md5_cx);
-        SHA1_Clone(shacx, (SHA1Context *)ss->ssl3.hs.sha_cx);
-
-        if (!isTLS) {
-            /* compute hashes for SSL3. */
-            unsigned char s[4];
-
-            if (!spec->msItem.data) {
-                PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE);
-                return SECFailure;
-            }
-
-            s[0] = (unsigned char)(sender >> 24);
-            s[1] = (unsigned char)(sender >> 16);
-            s[2] = (unsigned char)(sender >> 8);
-            s[3] = (unsigned char)sender;
-
-            if (sender != 0) {
-                MD5_Update(md5cx, s, 4);
-                PRINT_BUF(95, (NULL, "MD5 inner: sender", s, 4));
-            }
-
-            PRINT_BUF(95, (NULL, "MD5 inner: MAC Pad 1", mac_pad_1,
-                           mac_defs[mac_md5].pad_size));
-
-            MD5_Update(md5cx, spec->msItem.data, spec->msItem.len);
-            MD5_Update(md5cx, mac_pad_1, mac_defs[mac_md5].pad_size);
-            MD5_End(md5cx, md5_inner, &outLength, MD5_LENGTH);
-
-            PRINT_BUF(95, (NULL, "MD5 inner: result", md5_inner, outLength));
-
-            if (sender != 0) {
-                SHA1_Update(shacx, s, 4);
-                PRINT_BUF(95, (NULL, "SHA inner: sender", s, 4));
-            }
-
-            PRINT_BUF(95, (NULL, "SHA inner: MAC Pad 1", mac_pad_1,
-                           mac_defs[mac_sha].pad_size));
-
-            SHA1_Update(shacx, spec->msItem.data, spec->msItem.len);
-            SHA1_Update(shacx, mac_pad_1, mac_defs[mac_sha].pad_size);
-            SHA1_End(shacx, sha_inner, &outLength, SHA1_LENGTH);
-
-            PRINT_BUF(95, (NULL, "SHA inner: result", sha_inner, outLength));
-            PRINT_BUF(95, (NULL, "MD5 outer: MAC Pad 2", mac_pad_2,
-                           mac_defs[mac_md5].pad_size));
-            PRINT_BUF(95, (NULL, "MD5 outer: MD5 inner", md5_inner, MD5_LENGTH));
-
-            MD5_Begin(md5cx);
-            MD5_Update(md5cx, spec->msItem.data, spec->msItem.len);
-            MD5_Update(md5cx, mac_pad_2, mac_defs[mac_md5].pad_size);
-            MD5_Update(md5cx, md5_inner, MD5_LENGTH);
-        }
-        MD5_End(md5cx, hashes->u.s.md5, &outLength, MD5_LENGTH);
-
-        PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->u.s.md5, MD5_LENGTH));
-
-        if (!isTLS) {
-            PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2,
-                           mac_defs[mac_sha].pad_size));
-            PRINT_BUF(95, (NULL, "SHA outer: SHA inner", sha_inner, SHA1_LENGTH));
-
-            SHA1_Begin(shacx);
-            SHA1_Update(shacx, spec->msItem.data, spec->msItem.len);
-            SHA1_Update(shacx, mac_pad_2, mac_defs[mac_sha].pad_size);
-            SHA1_Update(shacx, sha_inner, SHA1_LENGTH);
-        }
-        SHA1_End(shacx, hashes->u.s.sha, &outLength, SHA1_LENGTH);
-
-        PRINT_BUF(60, (NULL, "SHA outer: result", hashes->u.s.sha, SHA1_LENGTH));
-
-        hashes->len = MD5_LENGTH + SHA1_LENGTH;
-        rv = SECSuccess;
-#undef md5cx
-#undef shacx
-    } else
-#endif
-        if (ss->ssl3.hs.hashType == handshake_hash_single) {
-        /* compute hashes with PKCS11 */
-        PK11Context *h;
-        unsigned int stateLen;
-        unsigned char stackBuf[1024];
-        unsigned char *stateBuf = NULL;
-
-        h = ss->ssl3.hs.sha;
-        stateBuf = PK11_SaveContextAlloc(h, stackBuf,
-                                         sizeof(stackBuf), &stateLen);
-        if (stateBuf == NULL) {
-            ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
-            goto tls12_loser;
-        }
-        rv |= PK11_DigestFinal(h, hashes->u.raw, &hashes->len,
-                               sizeof(hashes->u.raw));
-        if (rv != SECSuccess) {
-            ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
-            rv = SECFailure;
-            goto tls12_loser;
-        }
-        /* If we ever support ciphersuites where the PRF hash isn't SHA-256
-         * then this will need to be updated. */
-        hashes->hashAlg = ssl_hash_sha256;
-        rv = SECSuccess;
-
-    tls12_loser:
-        if (stateBuf) {
-            if (PK11_RestoreContext(h, stateBuf, stateLen) != SECSuccess) {
-                ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
-                rv = SECFailure;
-            }
-            if (stateBuf != stackBuf) {
-                PORT_ZFree(stateBuf, stateLen);
-            }
-        }
-    } else {
-        /* compute hashes with PKCS11 */
-        PK11Context *md5;
-        PK11Context *sha = NULL;
-        unsigned char *md5StateBuf = NULL;
-        unsigned char *shaStateBuf = NULL;
-        unsigned int md5StateLen, shaStateLen;
-        unsigned char md5StackBuf[256];
-        unsigned char shaStackBuf[512];
-
-        md5StateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.md5, md5StackBuf,
-                                            sizeof md5StackBuf, &md5StateLen);
-        if (md5StateBuf == NULL) {
-            ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
-            goto loser;
-        }
-        md5 = ss->ssl3.hs.md5;
-
-        shaStateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.sha, shaStackBuf,
-                                            sizeof shaStackBuf, &shaStateLen);
-        if (shaStateBuf == NULL) {
-            ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
-            goto loser;
-        }
-        sha = ss->ssl3.hs.sha;
-
-        if (!isTLS) {
-            /* compute hashes for SSL3. */
-            unsigned char s[4];
-
-            if (!spec->master_secret) {
-                PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE);
-                rv = SECFailure;
-                goto loser;
-            }
-
-            s[0] = (unsigned char)(sender >> 24);
-            s[1] = (unsigned char)(sender >> 16);
-            s[2] = (unsigned char)(sender >> 8);
-            s[3] = (unsigned char)sender;
-
-            if (sender != 0) {
-                rv |= PK11_DigestOp(md5, s, 4);
-                PRINT_BUF(95, (NULL, "MD5 inner: sender", s, 4));
-            }
-
-            PRINT_BUF(95, (NULL, "MD5 inner: MAC Pad 1", mac_pad_1,
-                           mac_defs[mac_md5].pad_size));
-
-            rv |= PK11_DigestKey(md5, spec->master_secret);
-            rv |= PK11_DigestOp(md5, mac_pad_1, mac_defs[mac_md5].pad_size);
-            rv |= PK11_DigestFinal(md5, md5_inner, &outLength, MD5_LENGTH);
-            PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH);
-            if (rv != SECSuccess) {
-                ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
-                rv = SECFailure;
-                goto loser;
-            }
-
-            PRINT_BUF(95, (NULL, "MD5 inner: result", md5_inner, outLength));
-
-            if (sender != 0) {
-                rv |= PK11_DigestOp(sha, s, 4);
-                PRINT_BUF(95, (NULL, "SHA inner: sender", s, 4));
-            }
-
-            PRINT_BUF(95, (NULL, "SHA inner: MAC Pad 1", mac_pad_1,
-                           mac_defs[mac_sha].pad_size));
-
-            rv |= PK11_DigestKey(sha, spec->master_secret);
-            rv |= PK11_DigestOp(sha, mac_pad_1, mac_defs[mac_sha].pad_size);
-            rv |= PK11_DigestFinal(sha, sha_inner, &outLength, SHA1_LENGTH);
-            PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH);
-            if (rv != SECSuccess) {
-                ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
-                rv = SECFailure;
-                goto loser;
-            }
-
-            PRINT_BUF(95, (NULL, "SHA inner: result", sha_inner, outLength));
-
-            PRINT_BUF(95, (NULL, "MD5 outer: MAC Pad 2", mac_pad_2,
-                           mac_defs[mac_md5].pad_size));
-            PRINT_BUF(95, (NULL, "MD5 outer: MD5 inner", md5_inner, MD5_LENGTH));
-
-            rv |= PK11_DigestBegin(md5);
-            rv |= PK11_DigestKey(md5, spec->master_secret);
-            rv |= PK11_DigestOp(md5, mac_pad_2, mac_defs[mac_md5].pad_size);
-            rv |= PK11_DigestOp(md5, md5_inner, MD5_LENGTH);
-        }
-        rv |= PK11_DigestFinal(md5, hashes->u.s.md5, &outLength, MD5_LENGTH);
-        PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH);
-        if (rv != SECSuccess) {
-            ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
-            rv = SECFailure;
-            goto loser;
-        }
-
-        PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->u.s.md5, MD5_LENGTH));
-
-        if (!isTLS) {
-            PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2,
-                           mac_defs[mac_sha].pad_size));
-            PRINT_BUF(95, (NULL, "SHA outer: SHA inner", sha_inner, SHA1_LENGTH));
-
-            rv |= PK11_DigestBegin(sha);
-            rv |= PK11_DigestKey(sha, spec->master_secret);
-            rv |= PK11_DigestOp(sha, mac_pad_2, mac_defs[mac_sha].pad_size);
-            rv |= PK11_DigestOp(sha, sha_inner, SHA1_LENGTH);
-        }
-        rv |= PK11_DigestFinal(sha, hashes->u.s.sha, &outLength, SHA1_LENGTH);
-        PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH);
-        if (rv != SECSuccess) {
-            ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
-            rv = SECFailure;
-            goto loser;
-        }
-
-        PRINT_BUF(60, (NULL, "SHA outer: result", hashes->u.s.sha, SHA1_LENGTH));
-
-        hashes->len = MD5_LENGTH + SHA1_LENGTH;
-        rv = SECSuccess;
-
-    loser:
-        if (md5StateBuf) {
-            if (PK11_RestoreContext(ss->ssl3.hs.md5, md5StateBuf, md5StateLen) !=
-                SECSuccess) {
-                ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
-                rv = SECFailure;
-            }
-            if (md5StateBuf != md5StackBuf) {
-                PORT_ZFree(md5StateBuf, md5StateLen);
-            }
-        }
-        if (shaStateBuf) {
-            if (PK11_RestoreContext(ss->ssl3.hs.sha, shaStateBuf, shaStateLen) !=
-                SECSuccess) {
-                ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
-                rv = SECFailure;
-            }
-            if (shaStateBuf != shaStackBuf) {
-                PORT_ZFree(shaStateBuf, shaStateLen);
-            }
-        }
-    }
-    return rv;
-}
-
-static SECStatus
-ssl3_ComputeBackupHandshakeHashes(sslSocket *ss,
-                                  SSL3Hashes *hashes) /* output goes here. */
-{
-    SECStatus rv = SECSuccess;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(!ss->sec.isServer);
-    PORT_Assert(ss->ssl3.hs.hashType == handshake_hash_single);
-
-    rv = PK11_DigestFinal(ss->ssl3.hs.backupHash, hashes->u.raw, &hashes->len,
-                          sizeof(hashes->u.raw));
-    if (rv != SECSuccess) {
-        ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
-        rv = SECFailure;
-        goto loser;
-    }
-    hashes->hashAlg = ssl_hash_sha1;
-
-loser:
-    PK11_DestroyContext(ss->ssl3.hs.backupHash, PR_TRUE);
-    ss->ssl3.hs.backupHash = NULL;
-    return rv;
-}
-
-/*
- * SSL 2 based implementations pass in the initial outbound buffer
- * so that the handshake hash can contain the included information.
- *
- * Called from ssl2_BeginClientHandshake() in sslcon.c
- */
-SECStatus
-ssl3_StartHandshakeHash(sslSocket *ss, unsigned char *buf, int length)
-{
-    SECStatus rv;
-
-    ssl_GetSSL3HandshakeLock(ss); /**************************************/
-
-    rv = ssl3_InitState(ss);
-    if (rv != SECSuccess) {
-        goto done; /* ssl3_InitState has set the error code. */
-    }
-    rv = ssl3_RestartHandshakeHashes(ss);
-    if (rv != SECSuccess) {
-        goto done;
-    }
-
-    PORT_Memset(&ss->ssl3.hs.client_random, 0, SSL3_RANDOM_LENGTH);
-    PORT_Memcpy(
-        &ss->ssl3.hs.client_random.rand[SSL3_RANDOM_LENGTH - SSL_CHALLENGE_BYTES],
-        &ss->sec.ci.clientChallenge,
-        SSL_CHALLENGE_BYTES);
-
-    rv = ssl3_UpdateHandshakeHashes(ss, buf, length);
-    /* if it failed, ssl3_UpdateHandshakeHashes has set the error code. */
-
-done:
-    ssl_ReleaseSSL3HandshakeLock(ss); /**************************************/
-    return rv;
-}
-
-/**************************************************************************
- * end of Handshake Hash functions.
- * Begin Send and Handle functions for handshakes.
- **************************************************************************/
-
-/* Called from ssl3_HandleHelloRequest(),
- *             ssl3_RedoHandshake()
- *             ssl2_BeginClientHandshake (when resuming ssl3 session)
- *             dtls_HandleHelloVerifyRequest(with resending=PR_TRUE)
- */
-SECStatus
-ssl3_SendClientHello(sslSocket *ss, PRBool resending)
-{
-    sslSessionID *sid;
-    ssl3CipherSpec *cwSpec;
-    SECStatus rv;
-    int i;
-    int length;
-    int num_suites;
-    int actual_count = 0;
-    PRBool isTLS = PR_FALSE;
-    PRBool requestingResume = PR_FALSE, fallbackSCSV = PR_FALSE;
-    PRInt32 total_exten_len = 0;
-    unsigned paddingExtensionLen;
-    unsigned numCompressionMethods;
-    PRInt32 flags;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: send client_hello handshake", SSL_GETPID(),
-                ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    rv = ssl3_InitState(ss);
-    if (rv != SECSuccess) {
-        return rv; /* ssl3_InitState has set the error code. */
-    }
-    /* These must be reset every handshake. */
-    ss->ssl3.hs.sendingSCSV = PR_FALSE;
-    ss->ssl3.hs.preliminaryInfo = 0;
-    PORT_Assert(IS_DTLS(ss) || !resending);
-
-    SECITEM_FreeItem(&ss->ssl3.hs.newSessionTicket.ticket, PR_FALSE);
-    ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE;
-
-    /* We might be starting a session renegotiation in which case we should
-     * clear previous state.
-     */
-    PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData));
-
-    rv = ssl3_RestartHandshakeHashes(ss);
-    if (rv != SECSuccess) {
-        return rv;
-    }
-
-    /*
-     * During a renegotiation, ss->clientHelloVersion will be used again to
-     * work around a Windows SChannel bug. Ensure that it is still enabled.
-     */
-    if (ss->firstHsDone) {
-        if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
-            PORT_SetError(SSL_ERROR_SSL_DISABLED);
-            return SECFailure;
-        }
-
-        if (ss->clientHelloVersion < ss->vrange.min ||
-            ss->clientHelloVersion > ss->vrange.max) {
-            PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
-            return SECFailure;
-        }
-    }
-
-    /* We ignore ss->sec.ci.sid here, and use ssl_Lookup because Lookup
-     * handles expired entries and other details.
-     * XXX If we've been called from ssl2_BeginClientHandshake, then
-     * this lookup is duplicative and wasteful.
-     */
-    sid = (ss->opt.noCache) ? NULL
-                            : ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID, ss->url);
-
-    /* We can't resume based on a different token. If the sid exists,
-     * make sure the token that holds the master secret still exists ...
-     * If we previously did client-auth, make sure that the token that holds
-     * the private key still exists, is logged in, hasn't been removed, etc.
-     */
-    if (sid) {
-        PRBool sidOK = PR_TRUE;
-        if (sid->u.ssl3.keys.msIsWrapped) {
-            /* Session key was wrapped, which means it was using PKCS11, */
-            PK11SlotInfo *slot = NULL;
-            if (sid->u.ssl3.masterValid && !ss->opt.bypassPKCS11) {
-                slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID,
-                                         sid->u.ssl3.masterSlotID);
-            }
-            if (slot == NULL) {
-                sidOK = PR_FALSE;
-            } else {
-                PK11SymKey *wrapKey = NULL;
-                if (!PK11_IsPresent(slot) ||
-                    ((wrapKey = PK11_GetWrapKey(slot,
-                                                sid->u.ssl3.masterWrapIndex,
-                                                sid->u.ssl3.masterWrapMech,
-                                                sid->u.ssl3.masterWrapSeries,
-                                                ss->pkcs11PinArg)) == NULL)) {
-                    sidOK = PR_FALSE;
-                }
-                if (wrapKey)
-                    PK11_FreeSymKey(wrapKey);
-                PK11_FreeSlot(slot);
-                slot = NULL;
-            }
-        }
-        /* If we previously did client-auth, make sure that the token that
-        ** holds the private key still exists, is logged in, hasn't been
-        ** removed, etc.
-        */
-        if (sidOK && !ssl3_ClientAuthTokenPresent(sid)) {
-            sidOK = PR_FALSE;
-        }
-
-        if (sidOK) {
-            /* Set ss->version based on the session cache */
-            if (ss->firstHsDone) {
-                /*
-                 * Windows SChannel compares the client_version inside the RSA
-                 * EncryptedPreMasterSecret of a renegotiation with the
-                 * client_version of the initial ClientHello rather than the
-                 * ClientHello in the renegotiation. To work around this bug, we
-                 * continue to use the client_version used in the initial
-                 * ClientHello when renegotiating.
-                 *
-                 * The client_version of the initial ClientHello is still
-                 * available in ss->clientHelloVersion. Ensure that
-                 * sid->version is bounded within
-                 * [ss->vrange.min, ss->clientHelloVersion], otherwise we
-                 * can't use sid.
-                 */
-                if (sid->version >= ss->vrange.min &&
-                    sid->version <= ss->clientHelloVersion) {
-                    ss->version = ss->clientHelloVersion;
-                } else {
-                    sidOK = PR_FALSE;
-                }
-            } else {
-                /*
-                 * Check sid->version is OK first.
-                 * Previously, we would cap the version based on sid->version,
-                 * but that prevents negotiation of a higher version if the
-                 * previous session was reduced (e.g., with version fallback)
-                 */
-                if (sid->version < ss->vrange.min ||
-                    sid->version > ss->vrange.max) {
-                    sidOK = PR_FALSE;
-                } else {
-                    rv = ssl3_NegotiateVersion(ss, SSL_LIBRARY_VERSION_MAX_SUPPORTED,
-                                               PR_TRUE);
-                    if (rv != SECSuccess) {
-                        return rv; /* error code was set */
-                    }
-                }
-            }
-        }
-
-        if (!sidOK) {
-            SSL_AtomicIncrementLong(&ssl3stats.sch_sid_cache_not_ok);
-            if (ss->sec.uncache)
-                (*ss->sec.uncache)(sid);
-            ssl_FreeSID(sid);
-            sid = NULL;
-        }
-    }
-
-    if (sid) {
-        requestingResume = PR_TRUE;
-        SSL_AtomicIncrementLong(&ssl3stats.sch_sid_cache_hits);
-
-        PRINT_BUF(4, (ss, "client, found session-id:", sid->u.ssl3.sessionID,
-                      sid->u.ssl3.sessionIDLength));
-
-        ss->ssl3.policy = sid->u.ssl3.policy;
-    } else {
-        SSL_AtomicIncrementLong(&ssl3stats.sch_sid_cache_misses);
-
-        /*
-         * Windows SChannel compares the client_version inside the RSA
-         * EncryptedPreMasterSecret of a renegotiation with the
-         * client_version of the initial ClientHello rather than the
-         * ClientHello in the renegotiation. To work around this bug, we
-         * continue to use the client_version used in the initial
-         * ClientHello when renegotiating.
-         */
-        if (ss->firstHsDone) {
-            ss->version = ss->clientHelloVersion;
-        } else {
-            rv = ssl3_NegotiateVersion(ss, SSL_LIBRARY_VERSION_MAX_SUPPORTED,
-                                       PR_TRUE);
-            if (rv != SECSuccess)
-                return rv; /* error code was set */
-        }
-
-        sid = ssl3_NewSessionID(ss, PR_FALSE);
-        if (!sid) {
-            return SECFailure; /* memory error is set */
-        }
-    }
-
-    if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
-        rv = tls13_SetupClientHello(ss);
-        if (rv != SECSuccess) {
-            if (sid) {
-                ssl_FreeSID(sid);
-            }
-            return rv;
-        }
-    }
-
-    isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0);
-    ssl_GetSpecWriteLock(ss);
-    cwSpec = ss->ssl3.cwSpec;
-    if (cwSpec->mac_def->mac == mac_null) {
-        /* SSL records are not being MACed. */
-        cwSpec->version = ss->version;
-    }
-    ssl_ReleaseSpecWriteLock(ss);
-
-    if (ss->sec.ci.sid != NULL) {
-        ssl_FreeSID(ss->sec.ci.sid); /* decrement ref count, free if zero */
-    }
-    ss->sec.ci.sid = sid;
-
-    ss->sec.send = ssl3_SendApplicationData;
-
-    /* shouldn't get here if SSL3 is disabled, but ... */
-    if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
-        PR_NOT_REACHED("No versions of SSL 3.0 or later are enabled");
-        PORT_SetError(SSL_ERROR_SSL_DISABLED);
-        return SECFailure;
-    }
-
-    /* how many suites does our PKCS11 support (regardless of policy)? */
-    num_suites = ssl3_config_match_init(ss);
-    if (!num_suites)
-        return SECFailure; /* ssl3_config_match_init has set error code. */
-
-    /* HACK for SCSV in SSL 3.0.  On initial handshake, prepend SCSV,
-     * only if TLS is disabled.
-     */
-    if (!ss->firstHsDone && !isTLS) {
-        /* Must set this before calling Hello Extension Senders,
-         * to suppress sending of empty RI extension.
-         */
-        ss->ssl3.hs.sendingSCSV = PR_TRUE;
-    }
-
-    /* When we attempt session resumption (only), we must lock the sid to
-     * prevent races with other resumption connections that receive a
-     * NewSessionTicket that will cause the ticket in the sid to be replaced.
-     * Once we've copied the session ticket into our ClientHello message, it
-     * is OK for the ticket to change, so we just need to make sure we hold
-     * the lock across the calls to ssl3_CallHelloExtensionSenders.
-     */
-    if (sid->u.ssl3.lock) {
-        PR_RWLock_Rlock(sid->u.ssl3.lock);
-    }
-
-    if (isTLS || (ss->firstHsDone && ss->peerRequestedProtection)) {
-        PRUint32 maxBytes = 65535; /* 2^16 - 1 */
-        PRInt32 extLen;
-
-        extLen = ssl3_CallHelloExtensionSenders(ss, PR_FALSE, maxBytes, NULL);
-        if (extLen < 0) {
-            if (sid->u.ssl3.lock) {
-                PR_RWLock_Unlock(sid->u.ssl3.lock);
-            }
-            return SECFailure;
-        }
-        total_exten_len += extLen;
-
-        if (total_exten_len > 0)
-            total_exten_len += 2;
-    }
-
-#ifndef NSS_DISABLE_ECC
-    if (!total_exten_len || !isTLS) {
-        /* not sending the elliptic_curves and ec_point_formats extensions */
-        ssl3_DisableECCSuites(ss, NULL); /* disable all ECC suites */
-    }
-#endif /* NSS_DISABLE_ECC */
-
-    if (IS_DTLS(ss)) {
-        ssl3_DisableNonDTLSSuites(ss);
-    }
-
-    /* how many suites are permitted by policy and user preference? */
-    num_suites = count_cipher_suites(ss, ss->ssl3.policy, PR_TRUE);
-    if (!num_suites) {
-        if (sid->u.ssl3.lock) {
-            PR_RWLock_Unlock(sid->u.ssl3.lock);
-        }
-        return SECFailure; /* count_cipher_suites has set error code. */
-    }
-
-    fallbackSCSV = ss->opt.enableFallbackSCSV && (!requestingResume ||
-                                                  ss->version < sid->version);
-    /* make room for SCSV */
-    if (ss->ssl3.hs.sendingSCSV) {
-        ++num_suites;
-    }
-    if (fallbackSCSV) {
-        ++num_suites;
-    }
-
-    /* count compression methods */
-    numCompressionMethods = 0;
-    for (i = 0; i < compressionMethodsCount; i++) {
-        if (compressionEnabled(ss, compressions[i]))
-            numCompressionMethods++;
-    }
-
-    length = sizeof(SSL3ProtocolVersion) + SSL3_RANDOM_LENGTH +
-             1 + ((sid == NULL) ? 0 : sid->u.ssl3.sessionIDLength) +
-             2 + num_suites * sizeof(ssl3CipherSuite) +
-             1 + numCompressionMethods + total_exten_len;
-    if (IS_DTLS(ss)) {
-        length += 1 + ss->ssl3.hs.cookieLen;
-    }
-
-    /* A padding extension may be included to ensure that the record containing
-     * the ClientHello doesn't have a length between 256 and 511 bytes
-     * (inclusive). Initial, ClientHello records with such lengths trigger bugs
-     * in F5 devices.
-     *
-     * This is not done for DTLS nor for renegotiation. */
-    if (!IS_DTLS(ss) && isTLS && !ss->firstHsDone) {
-        paddingExtensionLen = ssl3_CalculatePaddingExtensionLength(length);
-        total_exten_len += paddingExtensionLen;
-        length += paddingExtensionLen;
-    } else {
-        paddingExtensionLen = 0;
-    }
-
-    rv = ssl3_AppendHandshakeHeader(ss, client_hello, length);
-    if (rv != SECSuccess) {
-        if (sid->u.ssl3.lock) {
-            PR_RWLock_Unlock(sid->u.ssl3.lock);
-        }
-        return rv; /* err set by ssl3_AppendHandshake* */
-    }
-
-    if (ss->firstHsDone) {
-        /* The client hello version must stay unchanged to work around
-         * the Windows SChannel bug described above. */
-        PORT_Assert(ss->version == ss->clientHelloVersion);
-    }
-    ss->clientHelloVersion = ss->version;
-    if (IS_DTLS(ss)) {
-        PRUint16 version;
-
-        version = dtls_TLSVersionToDTLSVersion(ss->clientHelloVersion);
-        rv = ssl3_AppendHandshakeNumber(ss, version, 2);
-    } else {
-        rv = ssl3_AppendHandshakeNumber(ss, ss->clientHelloVersion, 2);
-    }
-    if (rv != SECSuccess) {
-        if (sid->u.ssl3.lock) {
-            PR_RWLock_Unlock(sid->u.ssl3.lock);
-        }
-        return rv; /* err set by ssl3_AppendHandshake* */
-    }
-
-    if (!resending) { /* Don't re-generate if we are in DTLS re-sending mode */
-        rv = ssl3_GetNewRandom(&ss->ssl3.hs.client_random);
-        if (rv != SECSuccess) {
-            if (sid->u.ssl3.lock) {
-                PR_RWLock_Unlock(sid->u.ssl3.lock);
-            }
-            return rv; /* err set by GetNewRandom. */
-        }
-    }
-    rv = ssl3_AppendHandshake(ss, &ss->ssl3.hs.client_random,
-                              SSL3_RANDOM_LENGTH);
-    if (rv != SECSuccess) {
-        if (sid->u.ssl3.lock) {
-            PR_RWLock_Unlock(sid->u.ssl3.lock);
-        }
-        return rv; /* err set by ssl3_AppendHandshake* */
-    }
-
-    if (sid)
-        rv = ssl3_AppendHandshakeVariable(
-            ss, sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength, 1);
-    else
-        rv = ssl3_AppendHandshakeNumber(ss, 0, 1);
-    if (rv != SECSuccess) {
-        if (sid->u.ssl3.lock) {
-            PR_RWLock_Unlock(sid->u.ssl3.lock);
-        }
-        return rv; /* err set by ssl3_AppendHandshake* */
-    }
-
-    if (IS_DTLS(ss)) {
-        rv = ssl3_AppendHandshakeVariable(
-            ss, ss->ssl3.hs.cookie, ss->ssl3.hs.cookieLen, 1);
-        if (rv != SECSuccess) {
-            if (sid->u.ssl3.lock) {
-                PR_RWLock_Unlock(sid->u.ssl3.lock);
-            }
-            return rv; /* err set by ssl3_AppendHandshake* */
-        }
-    }
-
-    rv = ssl3_AppendHandshakeNumber(ss, num_suites * sizeof(ssl3CipherSuite), 2);
-    if (rv != SECSuccess) {
-        if (sid->u.ssl3.lock) {
-            PR_RWLock_Unlock(sid->u.ssl3.lock);
-        }
-        return rv; /* err set by ssl3_AppendHandshake* */
-    }
-
-    if (ss->ssl3.hs.sendingSCSV) {
-        /* Add the actual SCSV */
-        rv = ssl3_AppendHandshakeNumber(ss, TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
-                                        sizeof(ssl3CipherSuite));
-        if (rv != SECSuccess) {
-            if (sid->u.ssl3.lock) {
-                PR_RWLock_Unlock(sid->u.ssl3.lock);
-            }
-            return rv; /* err set by ssl3_AppendHandshake* */
-        }
-        actual_count++;
-    }
-    if (fallbackSCSV) {
-        rv = ssl3_AppendHandshakeNumber(ss, TLS_FALLBACK_SCSV,
-                                        sizeof(ssl3CipherSuite));
-        if (rv != SECSuccess) {
-            if (sid->u.ssl3.lock) {
-                PR_RWLock_Unlock(sid->u.ssl3.lock);
-            }
-            return rv; /* err set by ssl3_AppendHandshake* */
-        }
-        actual_count++;
-    }
-    for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
-        ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
-        if (config_match(suite, ss->ssl3.policy, PR_TRUE, &ss->vrange, ss)) {
-            actual_count++;
-            if (actual_count > num_suites) {
-                if (sid->u.ssl3.lock) {
-                    PR_RWLock_Unlock(sid->u.ssl3.lock);
-                }
-                /* set error card removal/insertion error */
-                PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
-                return SECFailure;
-            }
-            rv = ssl3_AppendHandshakeNumber(ss, suite->cipher_suite,
-                                            sizeof(ssl3CipherSuite));
-            if (rv != SECSuccess) {
-                if (sid->u.ssl3.lock) {
-                    PR_RWLock_Unlock(sid->u.ssl3.lock);
-                }
-                return rv; /* err set by ssl3_AppendHandshake* */
-            }
-        }
-    }
-
-    /* if cards were removed or inserted between count_cipher_suites and
-     * generating our list, detect the error here rather than send it off to
-     * the server.. */
-    if (actual_count != num_suites) {
-        /* Card removal/insertion error */
-        if (sid->u.ssl3.lock) {
-            PR_RWLock_Unlock(sid->u.ssl3.lock);
-        }
-        PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
-        return SECFailure;
-    }
-
-    rv = ssl3_AppendHandshakeNumber(ss, numCompressionMethods, 1);
-    if (rv != SECSuccess) {
-        if (sid->u.ssl3.lock) {
-            PR_RWLock_Unlock(sid->u.ssl3.lock);
-        }
-        return rv; /* err set by ssl3_AppendHandshake* */
-    }
-    for (i = 0; i < compressionMethodsCount; i++) {
-        if (!compressionEnabled(ss, compressions[i]))
-            continue;
-        rv = ssl3_AppendHandshakeNumber(ss, compressions[i], 1);
-        if (rv != SECSuccess) {
-            if (sid->u.ssl3.lock) {
-                PR_RWLock_Unlock(sid->u.ssl3.lock);
-            }
-            return rv; /* err set by ssl3_AppendHandshake* */
-        }
-    }
-
-    if (total_exten_len) {
-        PRUint32 maxBytes = total_exten_len - 2;
-        PRInt32 extLen;
-
-        rv = ssl3_AppendHandshakeNumber(ss, maxBytes, 2);
-        if (rv != SECSuccess) {
-            if (sid->u.ssl3.lock) {
-                PR_RWLock_Unlock(sid->u.ssl3.lock);
-            }
-            return rv; /* err set by AppendHandshake. */
-        }
-
-        extLen = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, maxBytes, NULL);
-        if (extLen < 0) {
-            if (sid->u.ssl3.lock) {
-                PR_RWLock_Unlock(sid->u.ssl3.lock);
-            }
-            return SECFailure;
-        }
-        maxBytes -= extLen;
-
-        extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes);
-        if (extLen < 0) {
-            if (sid->u.ssl3.lock) {
-                PR_RWLock_Unlock(sid->u.ssl3.lock);
-            }
-            return SECFailure;
-        }
-        maxBytes -= extLen;
-
-        PORT_Assert(!maxBytes);
-    }
-
-    if (sid->u.ssl3.lock) {
-        PR_RWLock_Unlock(sid->u.ssl3.lock);
-    }
-
-    if (ss->xtnData.sentSessionTicketInClientHello) {
-        SSL_AtomicIncrementLong(&ssl3stats.sch_sid_stateless_resumes);
-    }
-
-    if (ss->ssl3.hs.sendingSCSV) {
-        /* Since we sent the SCSV, pretend we sent empty RI extension. */
-        TLSExtensionData *xtnData = &ss->xtnData;
-        xtnData->advertised[xtnData->numAdvertised++] =
-            ssl_renegotiation_info_xtn;
-    }
-
-    flags = 0;
-    if (!ss->firstHsDone && !IS_DTLS(ss)) {
-        flags |= ssl_SEND_FLAG_CAP_RECORD_VERSION;
-    }
-    rv = ssl3_FlushHandshake(ss, flags);
-    if (rv != SECSuccess) {
-        return rv; /* error code set by ssl3_FlushHandshake */
-    }
-
-    ss->ssl3.hs.ws = wait_server_hello;
-    return rv;
-}
-
-/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered a
- * complete ssl3 Hello Request.
- * Caller must hold Handshake and RecvBuf locks.
- */
-static SECStatus
-ssl3_HandleHelloRequest(sslSocket *ss)
-{
-    sslSessionID *sid = ss->sec.ci.sid;
-    SECStatus rv;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: handle hello_request handshake",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3);
-
-    if (ss->ssl3.hs.ws == wait_server_hello)
-        return SECSuccess;
-    if (ss->ssl3.hs.ws != idle_handshake || ss->sec.isServer) {
-        (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-        PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST);
-        return SECFailure;
-    }
-    if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) {
-        (void)SSL3_SendAlert(ss, alert_warning, no_renegotiation);
-        PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
-        return SECFailure;
-    }
-
-    if (sid) {
-        if (ss->sec.uncache)
-            ss->sec.uncache(sid);
-        ssl_FreeSID(sid);
-        ss->sec.ci.sid = NULL;
-    }
-
-    if (IS_DTLS(ss)) {
-        dtls_RehandshakeCleanup(ss);
-    }
-
-    ssl_GetXmitBufLock(ss);
-    rv = ssl3_SendClientHello(ss, PR_FALSE);
-    ssl_ReleaseXmitBufLock(ss);
-
-    return rv;
-}
-
-#define UNKNOWN_WRAP_MECHANISM 0x7fffffff
-
-static const CK_MECHANISM_TYPE wrapMechanismList[SSL_NUM_WRAP_MECHS] = {
-    CKM_DES3_ECB,
-    CKM_CAST5_ECB,
-    CKM_DES_ECB,
-    CKM_KEY_WRAP_LYNKS,
-    CKM_IDEA_ECB,
-    CKM_CAST3_ECB,
-    CKM_CAST_ECB,
-    CKM_RC5_ECB,
-    CKM_RC2_ECB,
-    CKM_CDMF_ECB,
-    CKM_SKIPJACK_WRAP,
-    CKM_SKIPJACK_CBC64,
-    CKM_AES_ECB,
-    CKM_CAMELLIA_ECB,
-    CKM_SEED_ECB,
-    UNKNOWN_WRAP_MECHANISM
-};
-
-static int
-ssl_FindIndexByWrapMechanism(CK_MECHANISM_TYPE mech)
-{
-    const CK_MECHANISM_TYPE *pMech = wrapMechanismList;
-
-    while (mech != *pMech && *pMech != UNKNOWN_WRAP_MECHANISM) {
-        ++pMech;
-    }
-    return (*pMech == UNKNOWN_WRAP_MECHANISM) ? -1
-                                              : (pMech - wrapMechanismList);
-}
-
-static PK11SymKey *
-ssl_UnwrapSymWrappingKey(
-    SSLWrappedSymWrappingKey *pWswk,
-    SECKEYPrivateKey *svrPrivKey,
-    SSL3KEAType exchKeyType,
-    CK_MECHANISM_TYPE masterWrapMech,
-    void *pwArg)
-{
-    PK11SymKey *unwrappedWrappingKey = NULL;
-    SECItem wrappedKey;
-#ifndef NSS_DISABLE_ECC
-    PK11SymKey *Ks;
-    SECKEYPublicKey pubWrapKey;
-    ECCWrappedKeyInfo *ecWrapped;
-#endif /* NSS_DISABLE_ECC */
-
-    /* found the wrapping key on disk. */
-    PORT_Assert(pWswk->symWrapMechanism == masterWrapMech);
-    PORT_Assert(pWswk->exchKeyType == exchKeyType);
-    if (pWswk->symWrapMechanism != masterWrapMech ||
-        pWswk->exchKeyType != exchKeyType) {
-        goto loser;
-    }
-    wrappedKey.type = siBuffer;
-    wrappedKey.data = pWswk->wrappedSymmetricWrappingkey;
-    wrappedKey.len = pWswk->wrappedSymKeyLen;
-    PORT_Assert(wrappedKey.len <= sizeof pWswk->wrappedSymmetricWrappingkey);
-
-    switch (exchKeyType) {
-
-        case kt_rsa:
-            unwrappedWrappingKey =
-                PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey,
-                                     masterWrapMech, CKA_UNWRAP, 0);
-            break;
-
-#ifndef NSS_DISABLE_ECC
-        case kt_ecdh:
-            /*
-             * For kt_ecdh, we first create an EC public key based on
-             * data stored with the wrappedSymmetricWrappingkey. Next,
-             * we do an ECDH computation involving this public key and
-             * the SSL server's (long-term) EC private key. The resulting
-             * shared secret is treated the same way as Fortezza's Ks, i.e.,
-             * it is used to recover the symmetric wrapping key.
-             *
-             * The data in wrappedSymmetricWrappingkey is laid out as defined
-             * in the ECCWrappedKeyInfo structure.
-             */
-            ecWrapped = (ECCWrappedKeyInfo *)pWswk->wrappedSymmetricWrappingkey;
-
-            PORT_Assert(ecWrapped->encodedParamLen + ecWrapped->pubValueLen +
-                            ecWrapped->wrappedKeyLen <= MAX_EC_WRAPPED_KEY_BUFLEN);
-
-            if (ecWrapped->encodedParamLen + ecWrapped->pubValueLen +
-                    ecWrapped->wrappedKeyLen > MAX_EC_WRAPPED_KEY_BUFLEN) {
-                PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-                goto loser;
-            }
-
-            pubWrapKey.keyType = ecKey;
-            pubWrapKey.u.ec.size = ecWrapped->size;
-            pubWrapKey.u.ec.DEREncodedParams.len = ecWrapped->encodedParamLen;
-            pubWrapKey.u.ec.DEREncodedParams.data = ecWrapped->var;
-            pubWrapKey.u.ec.publicValue.len = ecWrapped->pubValueLen;
-            pubWrapKey.u.ec.publicValue.data = ecWrapped->var +
-                                               ecWrapped->encodedParamLen;
-
-            wrappedKey.len = ecWrapped->wrappedKeyLen;
-            wrappedKey.data = ecWrapped->var + ecWrapped->encodedParamLen +
-                              ecWrapped->pubValueLen;
-
-            /* Derive Ks using ECDH */
-            Ks = PK11_PubDeriveWithKDF(svrPrivKey, &pubWrapKey, PR_FALSE, NULL,
-                                       NULL, CKM_ECDH1_DERIVE, masterWrapMech,
-                                       CKA_DERIVE, 0, CKD_NULL, NULL, NULL);
-            if (Ks == NULL) {
-                goto loser;
-            }
-
-            /*  Use Ks to unwrap the wrapping key */
-            unwrappedWrappingKey = PK11_UnwrapSymKey(Ks, masterWrapMech, NULL,
-                                                     &wrappedKey, masterWrapMech,
-                                                     CKA_UNWRAP, 0);
-            PK11_FreeSymKey(Ks);
-
-            break;
-#endif
-
-        default:
-            /* Assert? */
-            SET_ERROR_CODE
-            goto loser;
-    }
-loser:
-    return unwrappedWrappingKey;
-}
-
-/* Each process sharing the server session ID cache has its own array of
- * SymKey pointers for the symmetric wrapping keys that are used to wrap
- * the master secrets.  There is one key for each KEA type.  These Symkeys
- * correspond to the wrapped SymKeys kept in the server session cache.
- */
-
-typedef struct {
-    PK11SymKey *symWrapKey[kt_kea_size];
-} ssl3SymWrapKey;
-
-static PZLock *symWrapKeysLock = NULL;
-static ssl3SymWrapKey symWrapKeys[SSL_NUM_WRAP_MECHS];
-
-SECStatus
-ssl_FreeSymWrapKeysLock(void)
-{
-    if (symWrapKeysLock) {
-        PZ_DestroyLock(symWrapKeysLock);
-        symWrapKeysLock = NULL;
-        return SECSuccess;
-    }
-    PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
-    return SECFailure;
-}
-
-SECStatus
-SSL3_ShutdownServerCache(void)
-{
-    int i, j;
-
-    if (!symWrapKeysLock)
-        return SECSuccess; /* lock was never initialized */
-    PZ_Lock(symWrapKeysLock);
-    /* get rid of all symWrapKeys */
-    for (i = 0; i < SSL_NUM_WRAP_MECHS; ++i) {
-        for (j = 0; j < kt_kea_size; ++j) {
-            PK11SymKey **pSymWrapKey;
-            pSymWrapKey = &symWrapKeys[i].symWrapKey[j];
-            if (*pSymWrapKey) {
-                PK11_FreeSymKey(*pSymWrapKey);
-                *pSymWrapKey = NULL;
-            }
-        }
-    }
-
-    PZ_Unlock(symWrapKeysLock);
-    return SECSuccess;
-}
-
-SECStatus
-ssl_InitSymWrapKeysLock(void)
-{
-    symWrapKeysLock = PZ_NewLock(nssILockOther);
-    return symWrapKeysLock ? SECSuccess : SECFailure;
-}
-
-/* Try to get wrapping key for mechanism from in-memory array.
- * If that fails, look for one on disk.
- * If that fails, generate a new one, put the new one on disk,
- * Put the new key in the in-memory array.
- */
-static PK11SymKey *
-getWrappingKey(sslSocket *ss,
-               PK11SlotInfo *masterSecretSlot,
-               SSL3KEAType exchKeyType,
-               CK_MECHANISM_TYPE masterWrapMech,
-               void *pwArg)
-{
-    SECKEYPrivateKey *svrPrivKey;
-    SECKEYPublicKey *svrPubKey = NULL;
-    PK11SymKey *unwrappedWrappingKey = NULL;
-    PK11SymKey **pSymWrapKey;
-    CK_MECHANISM_TYPE asymWrapMechanism = CKM_INVALID_MECHANISM;
-    int length;
-    int symWrapMechIndex;
-    SECStatus rv;
-    SECItem wrappedKey;
-    SSLWrappedSymWrappingKey wswk;
-#ifndef NSS_DISABLE_ECC
-    PK11SymKey *Ks = NULL;
-    SECKEYPublicKey *pubWrapKey = NULL;
-    SECKEYPrivateKey *privWrapKey = NULL;
-    ECCWrappedKeyInfo *ecWrapped;
-#endif /* NSS_DISABLE_ECC */
-
-    svrPrivKey = ss->serverCerts[exchKeyType].SERVERKEY;
-    PORT_Assert(svrPrivKey != NULL);
-    if (!svrPrivKey) {
-        return NULL; /* why are we here?!? */
-    }
-
-    symWrapMechIndex = ssl_FindIndexByWrapMechanism(masterWrapMech);
-    PORT_Assert(symWrapMechIndex >= 0);
-    if (symWrapMechIndex < 0)
-        return NULL; /* invalid masterWrapMech. */
-
-    pSymWrapKey = &symWrapKeys[symWrapMechIndex].symWrapKey[exchKeyType];
-
-    ssl_InitSessionCacheLocks();
-
-    PZ_Lock(symWrapKeysLock);
-
-    unwrappedWrappingKey = *pSymWrapKey;
-    if (unwrappedWrappingKey != NULL) {
-        if (PK11_VerifyKeyOK(unwrappedWrappingKey)) {
-            unwrappedWrappingKey = PK11_ReferenceSymKey(unwrappedWrappingKey);
-            goto done;
-        }
-        /* slot series has changed, so this key is no good any more. */
-        PK11_FreeSymKey(unwrappedWrappingKey);
-        *pSymWrapKey = unwrappedWrappingKey = NULL;
-    }
-
-    /* Try to get wrapped SymWrapping key out of the (disk) cache. */
-    /* Following call fills in wswk on success. */
-    if (ssl_GetWrappingKey(symWrapMechIndex, exchKeyType, &wswk)) {
-        /* found the wrapped sym wrapping key on disk. */
-        unwrappedWrappingKey =
-            ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, exchKeyType,
-                                     masterWrapMech, pwArg);
-        if (unwrappedWrappingKey) {
-            goto install;
-        }
-    }
-
-    if (!masterSecretSlot) /* caller doesn't want to create a new one. */
-        goto loser;
-
-    length = PK11_GetBestKeyLength(masterSecretSlot, masterWrapMech);
-    /* Zero length means fixed key length algorithm, or error.
-     * It's ambiguous.
-     */
-    unwrappedWrappingKey = PK11_KeyGen(masterSecretSlot, masterWrapMech, NULL,
-                                       length, pwArg);
-    if (!unwrappedWrappingKey) {
-        goto loser;
-    }
-
-    /* Prepare the buffer to receive the wrappedWrappingKey,
-     * the symmetric wrapping key wrapped using the server's pub key.
-     */
-    PORT_Memset(&wswk, 0, sizeof wswk); /* eliminate UMRs. */
-
-    if (ss->serverCerts[exchKeyType].serverKeyPair) {
-        svrPubKey = ss->serverCerts[exchKeyType].serverKeyPair->pubKey;
-    }
-    if (svrPubKey == NULL) {
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        goto loser;
-    }
-    wrappedKey.type = siBuffer;
-    wrappedKey.len = SECKEY_PublicKeyStrength(svrPubKey);
-    wrappedKey.data = wswk.wrappedSymmetricWrappingkey;
-
-    PORT_Assert(wrappedKey.len <= sizeof wswk.wrappedSymmetricWrappingkey);
-    if (wrappedKey.len > sizeof wswk.wrappedSymmetricWrappingkey)
-        goto loser;
-
-    /* wrap symmetric wrapping key in server's public key. */
-    switch (exchKeyType) {
-        case kt_rsa:
-            asymWrapMechanism = CKM_RSA_PKCS;
-            rv = PK11_PubWrapSymKey(asymWrapMechanism, svrPubKey,
-                                    unwrappedWrappingKey, &wrappedKey);
-            break;
-
-#ifndef NSS_DISABLE_ECC
-        case kt_ecdh:
-            /*
-             * We generate an ephemeral EC key pair. Perform an ECDH
-             * computation involving this ephemeral EC public key and
-             * the SSL server's (long-term) EC private key. The resulting
-             * shared secret is treated in the same way as Fortezza's Ks,
-             * i.e., it is used to wrap the wrapping key. To facilitate
-             * unwrapping in ssl_UnwrapWrappingKey, we also store all
-             * relevant info about the ephemeral EC public key in
-             * wswk.wrappedSymmetricWrappingkey and lay it out as
-             * described in the ECCWrappedKeyInfo structure.
-             */
-            PORT_Assert(svrPubKey->keyType == ecKey);
-            if (svrPubKey->keyType != ecKey) {
-                /* something is wrong in sslsecur.c if this isn't an ecKey */
-                PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-                rv = SECFailure;
-                goto ec_cleanup;
-            }
-
-            privWrapKey = SECKEY_CreateECPrivateKey(
-                &svrPubKey->u.ec.DEREncodedParams, &pubWrapKey, NULL);
-            if ((privWrapKey == NULL) || (pubWrapKey == NULL)) {
-                rv = SECFailure;
-                goto ec_cleanup;
-            }
-
-            /* Set the key size in bits */
-            if (pubWrapKey->u.ec.size == 0) {
-                pubWrapKey->u.ec.size = SECKEY_PublicKeyStrengthInBits(svrPubKey);
-            }
-
-            PORT_Assert(pubWrapKey->u.ec.DEREncodedParams.len +
-                            pubWrapKey->u.ec.publicValue.len < MAX_EC_WRAPPED_KEY_BUFLEN);
-            if (pubWrapKey->u.ec.DEREncodedParams.len +
-                    pubWrapKey->u.ec.publicValue.len >= MAX_EC_WRAPPED_KEY_BUFLEN) {
-                PORT_SetError(SEC_ERROR_INVALID_KEY);
-                rv = SECFailure;
-                goto ec_cleanup;
-            }
-
-            /* Derive Ks using ECDH */
-            Ks = PK11_PubDeriveWithKDF(svrPrivKey, pubWrapKey, PR_FALSE, NULL,
-                                       NULL, CKM_ECDH1_DERIVE, masterWrapMech,
-                                       CKA_DERIVE, 0, CKD_NULL, NULL, NULL);
-            if (Ks == NULL) {
-                rv = SECFailure;
-                goto ec_cleanup;
-            }
-
-            ecWrapped = (ECCWrappedKeyInfo *)(wswk.wrappedSymmetricWrappingkey);
-            ecWrapped->size = pubWrapKey->u.ec.size;
-            ecWrapped->encodedParamLen = pubWrapKey->u.ec.DEREncodedParams.len;
-            PORT_Memcpy(ecWrapped->var, pubWrapKey->u.ec.DEREncodedParams.data,
-                        pubWrapKey->u.ec.DEREncodedParams.len);
-
-            ecWrapped->pubValueLen = pubWrapKey->u.ec.publicValue.len;
-            PORT_Memcpy(ecWrapped->var + ecWrapped->encodedParamLen,
-                        pubWrapKey->u.ec.publicValue.data,
-                        pubWrapKey->u.ec.publicValue.len);
-
-            wrappedKey.len = MAX_EC_WRAPPED_KEY_BUFLEN -
-                             (ecWrapped->encodedParamLen + ecWrapped->pubValueLen);
-            wrappedKey.data = ecWrapped->var + ecWrapped->encodedParamLen +
-                              ecWrapped->pubValueLen;
-
-            /* wrap symmetricWrapping key with the local Ks */
-            rv = PK11_WrapSymKey(masterWrapMech, NULL, Ks,
-                                 unwrappedWrappingKey, &wrappedKey);
-
-            if (rv != SECSuccess) {
-                goto ec_cleanup;
-            }
-
-            /* Write down the length of wrapped key in the buffer
-             * wswk.wrappedSymmetricWrappingkey at the appropriate offset
-             */
-            ecWrapped->wrappedKeyLen = wrappedKey.len;
-
-        ec_cleanup:
-            if (privWrapKey)
-                SECKEY_DestroyPrivateKey(privWrapKey);
-            if (pubWrapKey)
-                SECKEY_DestroyPublicKey(pubWrapKey);
-            if (Ks)
-                PK11_FreeSymKey(Ks);
-            asymWrapMechanism = masterWrapMech;
-            break;
-#endif /* NSS_DISABLE_ECC */
-
-        default:
-            rv = SECFailure;
-            break;
-    }
-
-    if (rv != SECSuccess) {
-        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
-        goto loser;
-    }
-
-    PORT_Assert(asymWrapMechanism != CKM_INVALID_MECHANISM);
-
-    wswk.symWrapMechanism = masterWrapMech;
-    wswk.symWrapMechIndex = symWrapMechIndex;
-    wswk.asymWrapMechanism = asymWrapMechanism;
-    wswk.exchKeyType = exchKeyType;
-    wswk.wrappedSymKeyLen = wrappedKey.len;
-
-    /* put it on disk. */
-    /* If the wrapping key for this KEA type has already been set,
-     * then abandon the value we just computed and
-     * use the one we got from the disk.
-     */
-    if (ssl_SetWrappingKey(&wswk)) {
-        /* somebody beat us to it.  The original contents of our wswk
-         * has been replaced with the content on disk.  Now, discard
-         * the key we just created and unwrap this new one.
-         */
-        PK11_FreeSymKey(unwrappedWrappingKey);
-
-        unwrappedWrappingKey =
-            ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, exchKeyType,
-                                     masterWrapMech, pwArg);
-    }
-
-install:
-    if (unwrappedWrappingKey) {
-        *pSymWrapKey = PK11_ReferenceSymKey(unwrappedWrappingKey);
-    }
-
-loser:
-done:
-    PZ_Unlock(symWrapKeysLock);
-    return unwrappedWrappingKey;
-}
-
-/* hexEncode hex encodes |length| bytes from |in| and writes it as |length*2|
- * bytes to |out|. */
-static void
-hexEncode(char *out, const unsigned char *in, unsigned int length)
-{
-    static const char hextable[] = "0123456789abcdef";
-    unsigned int i;
-
-    for (i = 0; i < length; i++) {
-        *(out++) = hextable[in[i] >> 4];
-        *(out++) = hextable[in[i] & 15];
-    }
-}
-
-/* Called from ssl3_SendClientKeyExchange(). */
-/* Presently, this always uses PKCS11.  There is no bypass for this. */
-static SECStatus
-sendRSAClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey)
-{
-    PK11SymKey *pms = NULL;
-    SECStatus rv = SECFailure;
-    SECItem enc_pms = { siBuffer, NULL, 0 };
-    PRBool isTLS;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    /* Generate the pre-master secret ...  */
-    ssl_GetSpecWriteLock(ss);
-    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
-
-    pms = ssl3_GenerateRSAPMS(ss, ss->ssl3.pwSpec, NULL);
-    ssl_ReleaseSpecWriteLock(ss);
-    if (pms == NULL) {
-        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
-        goto loser;
-    }
-
-    /* Get the wrapped (encrypted) pre-master secret, enc_pms */
-    enc_pms.len = SECKEY_PublicKeyStrength(svrPubKey);
-    enc_pms.data = (unsigned char *)PORT_Alloc(enc_pms.len);
-    if (enc_pms.data == NULL) {
-        goto loser; /* err set by PORT_Alloc */
-    }
-
-    /* wrap pre-master secret in server's public key. */
-    rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, svrPubKey, pms, &enc_pms);
-    if (rv != SECSuccess) {
-        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
-        goto loser;
-    }
-
-    if (ssl_keylog_iob) {
-        SECStatus extractRV = PK11_ExtractKeyValue(pms);
-        if (extractRV == SECSuccess) {
-            SECItem *keyData = PK11_GetKeyData(pms);
-            if (keyData && keyData->data && keyData->len) {
-#ifdef TRACE
-                if (ssl_trace >= 100) {
-                    ssl_PrintBuf(ss, "Pre-Master Secret",
-                                 keyData->data, keyData->len);
-                }
-#endif
-                if (ssl_keylog_iob && enc_pms.len >= 8 && keyData->len == 48) {
-                    /* https://developer.mozilla.org/en/NSS_Key_Log_Format */
-
-                    /* There could be multiple, concurrent writers to the
-                     * keylog, so we have to do everything in a single call to
-                     * fwrite. */
-                    char buf[4 + 8 * 2 + 1 + 48 * 2 + 1];
-
-                    strcpy(buf, "RSA ");
-                    hexEncode(buf + 4, enc_pms.data, 8);
-                    buf[20] = ' ';
-                    hexEncode(buf + 21, keyData->data, 48);
-                    buf[sizeof(buf) - 1] = '\n';
-
-                    fwrite(buf, sizeof(buf), 1, ssl_keylog_iob);
-                    fflush(ssl_keylog_iob);
-                }
-            }
-        }
-    }
-
-    rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
-                                    isTLS ? enc_pms.len + 2
-                                          : enc_pms.len);
-    if (rv != SECSuccess) {
-        goto loser; /* err set by ssl3_AppendHandshake* */
-    }
-    if (isTLS) {
-        rv = ssl3_AppendHandshakeVariable(ss, enc_pms.data, enc_pms.len, 2);
-    } else {
-        rv = ssl3_AppendHandshake(ss, enc_pms.data, enc_pms.len);
-    }
-    if (rv != SECSuccess) {
-        goto loser; /* err set by ssl3_AppendHandshake* */
-    }
-
-    rv = ssl3_InitPendingCipherSpec(ss, pms);
-    PK11_FreeSymKey(pms);
-    pms = NULL;
-
-    if (rv != SECSuccess) {
-        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
-        goto loser;
-    }
-
-    rv = SECSuccess;
-
-loser:
-    if (enc_pms.data != NULL) {
-        PORT_Free(enc_pms.data);
-    }
-    if (pms != NULL) {
-        PK11_FreeSymKey(pms);
-    }
-    return rv;
-}
-
-/* Called from ssl3_SendClientKeyExchange(). */
-/* Presently, this always uses PKCS11.  There is no bypass for this. */
-static SECStatus
-sendDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey)
-{
-    PK11SymKey *pms = NULL;
-    SECStatus rv = SECFailure;
-    PRBool isTLS;
-    CK_MECHANISM_TYPE target;
-
-    SECKEYDHParams dhParam;           /* DH parameters */
-    SECKEYPublicKey *pubKey = NULL;   /* Ephemeral DH key */
-    SECKEYPrivateKey *privKey = NULL; /* Ephemeral DH key */
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
-
-    /* Copy DH parameters from server key */
-
-    if (svrPubKey->keyType != dhKey) {
-        PORT_SetError(SEC_ERROR_BAD_KEY);
-        goto loser;
-    }
-    dhParam.prime.data = svrPubKey->u.dh.prime.data;
-    dhParam.prime.len = svrPubKey->u.dh.prime.len;
-    dhParam.base.data = svrPubKey->u.dh.base.data;
-    dhParam.base.len = svrPubKey->u.dh.base.len;
-
-    /* Generate ephemeral DH keypair */
-    privKey = SECKEY_CreateDHPrivateKey(&dhParam, &pubKey, NULL);
-    if (!privKey || !pubKey) {
-        ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
-        rv = SECFailure;
-        goto loser;
-    }
-    PRINT_BUF(50, (ss, "DH public value:",
-                   pubKey->u.dh.publicValue.data,
-                   pubKey->u.dh.publicValue.len));
-
-    if (isTLS)
-        target = CKM_TLS_MASTER_KEY_DERIVE_DH;
-    else
-        target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
-
-    /* Determine the PMS */
-
-    pms = PK11_PubDerive(privKey, svrPubKey, PR_FALSE, NULL, NULL,
-                         CKM_DH_PKCS_DERIVE, target, CKA_DERIVE, 0, NULL);
-
-    if (pms == NULL) {
-        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
-        goto loser;
-    }
-
-    SECKEY_DestroyPrivateKey(privKey);
-    privKey = NULL;
-
-    rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
-                                    pubKey->u.dh.publicValue.len + 2);
-    if (rv != SECSuccess) {
-        goto loser; /* err set by ssl3_AppendHandshake* */
-    }
-    rv = ssl3_AppendHandshakeVariable(ss,
-                                      pubKey->u.dh.publicValue.data,
-                                      pubKey->u.dh.publicValue.len, 2);
-    SECKEY_DestroyPublicKey(pubKey);
-    pubKey = NULL;
-
-    if (rv != SECSuccess) {
-        goto loser; /* err set by ssl3_AppendHandshake* */
-    }
-
-    rv = ssl3_InitPendingCipherSpec(ss, pms);
-    PK11_FreeSymKey(pms);
-    pms = NULL;
-
-    if (rv != SECSuccess) {
-        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
-        goto loser;
-    }
-
-    rv = SECSuccess;
-
-loser:
-
-    if (pms)
-        PK11_FreeSymKey(pms);
-    if (privKey)
-        SECKEY_DestroyPrivateKey(privKey);
-    if (pubKey)
-        SECKEY_DestroyPublicKey(pubKey);
-    return rv;
-}
-
-/* Called from ssl3_HandleServerHelloDone(). */
-static SECStatus
-ssl3_SendClientKeyExchange(sslSocket *ss)
-{
-    SECKEYPublicKey *serverKey = NULL;
-    SECStatus rv = SECFailure;
-    PRBool isTLS;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: send client_key_exchange handshake",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if (ss->sec.peerKey == NULL) {
-        serverKey = CERT_ExtractPublicKey(ss->sec.peerCert);
-        if (serverKey == NULL) {
-            ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
-            return SECFailure;
-        }
-    } else {
-        serverKey = ss->sec.peerKey;
-        ss->sec.peerKey = NULL; /* we're done with it now */
-    }
-
-    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
-    /* enforce limits on kea key sizes. */
-    if (ss->ssl3.hs.kea_def->is_limited) {
-        unsigned int keyLen = SECKEY_PublicKeyStrengthInBits(serverKey);
-
-        if (keyLen > ss->ssl3.hs.kea_def->key_size_limit) {
-            if (isTLS)
-                (void)SSL3_SendAlert(ss, alert_fatal, export_restriction);
-            else
-                (void)ssl3_HandshakeFailure(ss);
-            PORT_SetError(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED);
-            goto loser;
-        }
-    }
-
-    ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
-    ss->sec.keaKeyBits = SECKEY_PublicKeyStrengthInBits(serverKey);
-
-    switch (ss->ssl3.hs.kea_def->exchKeyType) {
-        case kt_rsa:
-            rv = sendRSAClientKeyExchange(ss, serverKey);
-            break;
-
-        case kt_dh:
-            rv = sendDHClientKeyExchange(ss, serverKey);
-            break;
-
-#ifndef NSS_DISABLE_ECC
-        case kt_ecdh:
-            rv = ssl3_SendECDHClientKeyExchange(ss, serverKey);
-            break;
-#endif /* NSS_DISABLE_ECC */
-
-        default:
-            /* got an unknown or unsupported Key Exchange Algorithm.  */
-            SEND_ALERT
-            PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
-            break;
-    }
-
-    SSL_TRC(3, ("%d: SSL3[%d]: DONE sending client_key_exchange",
-                SSL_GETPID(), ss->fd));
-
-loser:
-    if (serverKey)
-        SECKEY_DestroyPublicKey(serverKey);
-    return rv; /* err code already set. */
-}
-
-/* Called from ssl3_HandleServerHelloDone(). */
-SECStatus
-ssl3_SendCertificateVerify(sslSocket *ss, SECKEYPrivateKey *privKey)
-{
-    SECStatus rv = SECFailure;
-    PRBool isTLS;
-    PRBool isTLS12;
-    PRBool isTLS13;
-    SECItem buf = { siBuffer, NULL, 0 };
-    SSL3Hashes hashes;
-    KeyType keyType;
-    unsigned int len;
-    SSLSignatureAndHashAlg sigAndHash;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    SSL_TRC(3, ("%d: SSL3[%d]: send certificate_verify handshake",
-                SSL_GETPID(), ss->fd));
-
-    isTLS13 = (PRBool)(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
-    ssl_GetSpecReadLock(ss);
-    if (ss->ssl3.hs.hashType == handshake_hash_single &&
-        ss->ssl3.hs.backupHash) {
-        PORT_Assert(!ss->ssl3.hs.backupHash);
-        PORT_Assert(!isTLS13);
-        /* TODO(ekr@rtfm.com): The backup hash here contains a SHA-1 hash
-         * but in TLS 1.3, we always sign H(Context, Hash(handshake))
-         * where:
-         *
-         * H is the negotiated signature hash and
-         * Hash is the cipher-suite specific handshake hash
-         * Generally this means that Hash is SHA-256.
-         *
-         * We need code to negotiate H but the current code is a mess.
-         */
-        if (isTLS13) {
-            /* rv is already set to SECFailure */
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        } else {
-            rv = ssl3_ComputeBackupHandshakeHashes(ss, &hashes);
-        }
-    } else {
-        ssl3CipherSpec *spec;
-
-        if (isTLS13) {
-            /* In TLS 1.3, we are already encrypted. */
-            spec = ss->ssl3.cwSpec;
-        } else {
-            spec = ss->ssl3.pwSpec;
-        }
-
-        rv = ssl3_ComputeHandshakeHashes(ss, spec, &hashes, 0);
-    }
-    ssl_ReleaseSpecReadLock(ss);
-    if (rv != SECSuccess) {
-        goto done; /* err code was set by ssl3_ComputeHandshakeHashes */
-    }
-
-    if (isTLS13) {
-        rv = tls13_AddContextToHashes(ss, &hashes, tls13_GetHash(ss), PR_TRUE);
-        if (rv != SECSuccess) {
-            goto done; /* err code was set by tls13_AddContextToHashes */
-        }
-    }
-
-    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
-    isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
-
-    keyType = privKey->keyType;
-    rv = ssl3_SignHashes(&hashes, privKey, &buf, isTLS);
-    if (rv == SECSuccess && !ss->sec.isServer) {
-        /* Remember the info about the slot that did the signing.
-        ** Later, when doing an SSL restart handshake, verify this.
-        ** These calls are mere accessors, and can't fail.
-        */
-        PK11SlotInfo *slot;
-        sslSessionID *sid = ss->sec.ci.sid;
-
-        slot = PK11_GetSlotFromPrivateKey(privKey);
-        sid->u.ssl3.clAuthSeries = PK11_GetSlotSeries(slot);
-        sid->u.ssl3.clAuthSlotID = PK11_GetSlotID(slot);
-        sid->u.ssl3.clAuthModuleID = PK11_GetModuleID(slot);
-        sid->u.ssl3.clAuthValid = PR_TRUE;
-        PK11_FreeSlot(slot);
-    }
-    if (rv != SECSuccess) {
-        goto done; /* err code was set by ssl3_SignHashes */
-    }
-
-    len = buf.len + 2 + (isTLS12 ? 2 : 0);
-
-    rv = ssl3_AppendHandshakeHeader(ss, certificate_verify, len);
-    if (rv != SECSuccess) {
-        goto done; /* error code set by AppendHandshake */
-    }
-    if (isTLS12) {
-        rv = ssl3_TLSSignatureAlgorithmForKeyType(keyType,
-                                                  &sigAndHash.sigAlg);
-        if (rv != SECSuccess) {
-            goto done;
-        }
-        sigAndHash.hashAlg = hashes.hashAlg;
-
-        rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash);
-        if (rv != SECSuccess) {
-            goto done; /* err set by AppendHandshake. */
-        }
-    }
-    rv = ssl3_AppendHandshakeVariable(ss, buf.data, buf.len, 2);
-    if (rv != SECSuccess) {
-        goto done; /* error code set by AppendHandshake */
-    }
-
-done:
-    if (buf.data)
-        PORT_Free(buf.data);
-    return rv;
-}
-
-/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
- * ssl3 ServerHello message.
- * Caller must hold Handshake and RecvBuf locks.
- */
-static SECStatus
-ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    sslSessionID *sid = ss->sec.ci.sid;
-    PRInt32 temp; /* allow for consume number failure */
-    PRBool suite_found = PR_FALSE;
-    int i;
-    int errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
-    SECStatus rv;
-    SECItem sidBytes = { siBuffer, NULL, 0 };
-    PRBool sid_match;
-    PRBool isTLS = PR_FALSE;
-    SSL3AlertDescription desc = illegal_parameter;
-    SSL3ProtocolVersion version;
-    SSL3ProtocolVersion downgradeCheckVersion;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello handshake",
-                SSL_GETPID(), ss->fd));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->ssl3.initialized);
-
-    if (ss->ssl3.hs.ws != wait_server_hello) {
-        errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO;
-        desc = unexpected_message;
-        goto alert_loser;
-    }
-
-    /* clean up anything left from previous handshake. */
-    if (ss->ssl3.clientCertChain != NULL) {
-        CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
-        ss->ssl3.clientCertChain = NULL;
-    }
-    if (ss->ssl3.clientCertificate != NULL) {
-        CERT_DestroyCertificate(ss->ssl3.clientCertificate);
-        ss->ssl3.clientCertificate = NULL;
-    }
-    if (ss->ssl3.clientPrivateKey != NULL) {
-        SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
-        ss->ssl3.clientPrivateKey = NULL;
-    }
-
-    if (ss->ssl3.channelID != NULL) {
-        SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
-        ss->ssl3.channelID = NULL;
-    }
-    if (ss->ssl3.channelIDPub != NULL) {
-        SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
-        ss->ssl3.channelIDPub = NULL;
-    }
-
-    temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
-    if (temp < 0) {
-        goto loser; /* alert has been sent */
-    }
-    version = (SSL3ProtocolVersion)temp;
-
-    if (IS_DTLS(ss)) {
-        /* RFC 4347 required that you verify that the server versions
-         * match (Section 4.2.1) in the HelloVerifyRequest and the
-         * ServerHello.
-         *
-         * RFC 6347 suggests (SHOULD) that servers always use 1.0
-         * in HelloVerifyRequest and allows the versions not to match,
-         * especially when 1.2 is being negotiated.
-         *
-         * Therefore we do not check for matching here.
-         */
-        version = dtls_DTLSVersionToTLSVersion(version);
-        if (version == 0) { /* Insane version number */
-            goto alert_loser;
-        }
-    }
-
-    rv = ssl3_NegotiateVersion(ss, version, PR_FALSE);
-    if (rv != SECSuccess) {
-        desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version
-                                                   : handshake_failure;
-        errCode = SSL_ERROR_UNSUPPORTED_VERSION;
-        goto alert_loser;
-    }
-    ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_version;
-    isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0);
-
-    rv = ssl3_InitHandshakeHashes(ss);
-    if (rv != SECSuccess) {
-        desc = internal_error;
-        errCode = PORT_GetError();
-        goto alert_loser;
-    }
-
-    rv = ssl3_ConsumeHandshake(
-        ss, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH, &b, &length);
-    if (rv != SECSuccess) {
-        goto loser; /* alert has been sent */
-    }
-
-    /* Check the ServerHello.random per
-     * [draft-ietf-tls-tls13-11 Section 6.3.1.1].
-     *
-     * TLS 1.3 clients receiving a TLS 1.2 or below ServerHello MUST check
-     * that the top eight octets are not equal to either of these values.
-     * TLS 1.2 clients SHOULD also perform this check if the ServerHello
-     * indicates TLS 1.1 or below.  If a match is found the client MUST
-     * abort the handshake with a fatal "illegal_parameter" alert.
-     */
-    downgradeCheckVersion = ss->ssl3.downgradeCheckVersion ? ss->ssl3.downgradeCheckVersion
-                                                           : ss->vrange.max;
-
-    if (downgradeCheckVersion >= SSL_LIBRARY_VERSION_TLS_1_2 &&
-        downgradeCheckVersion > ss->version) {
-        if (!PORT_Memcmp(ss->ssl3.hs.server_random.rand,
-                         tls13_downgrade_random,
-                         sizeof(tls13_downgrade_random)) ||
-            !PORT_Memcmp(ss->ssl3.hs.server_random.rand,
-                         tls12_downgrade_random,
-                         sizeof(tls12_downgrade_random))) {
-            desc = illegal_parameter;
-            errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
-            goto alert_loser;
-        }
-    }
-
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        rv = ssl3_ConsumeHandshakeVariable(ss, &sidBytes, 1, &b, &length);
-        if (rv != SECSuccess) {
-            goto loser; /* alert has been sent */
-        }
-        if (sidBytes.len > SSL3_SESSIONID_BYTES) {
-            if (isTLS)
-                desc = decode_error;
-            goto alert_loser; /* malformed. */
-        }
-    }
-
-    /* find selected cipher suite in our list. */
-    temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
-    if (temp < 0) {
-        goto loser; /* alert has been sent */
-    }
-    ssl3_config_match_init(ss);
-    for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
-        ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
-        if (temp == suite->cipher_suite) {
-            SSLVersionRange vrange = { ss->version, ss->version };
-            if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange, ss)) {
-                /* config_match already checks whether the cipher suite is
-                 * acceptable for the version, but the check is repeated here
-                 * in order to give a more precise error code. */
-                if (!ssl3_CipherSuiteAllowedForVersionRange(temp, &vrange)) {
-                    desc = handshake_failure;
-                    errCode = SSL_ERROR_CIPHER_DISALLOWED_FOR_VERSION;
-                    goto alert_loser;
-                }
-
-                break; /* failure */
-            }
-
-            suite_found = PR_TRUE;
-            break; /* success */
-        }
-    }
-    if (!suite_found) {
-        desc = handshake_failure;
-        errCode = SSL_ERROR_NO_CYPHER_OVERLAP;
-        goto alert_loser;
-    }
-    ss->ssl3.hs.cipher_suite = (ssl3CipherSuite)temp;
-    ss->ssl3.hs.suite_def = ssl_LookupCipherSuiteDef((ssl3CipherSuite)temp);
-    ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_cipher_suite;
-    PORT_Assert(ss->ssl3.hs.suite_def);
-    if (!ss->ssl3.hs.suite_def) {
-        errCode = SEC_ERROR_LIBRARY_FAILURE;
-        PORT_SetError(errCode);
-        goto loser; /* we don't send alerts for our screw-ups. */
-    }
-
-    ss->ssl3.hs.kea_def = &kea_defs[ss->ssl3.hs.suite_def->key_exchange_alg];
-
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        /* find selected compression method in our list. */
-        temp = ssl3_ConsumeHandshakeNumber(ss, 1, &b, &length);
-        if (temp < 0) {
-            goto loser; /* alert has been sent */
-        }
-        suite_found = PR_FALSE;
-        for (i = 0; i < compressionMethodsCount; i++) {
-            if (temp == compressions[i]) {
-                if (!compressionEnabled(ss, compressions[i])) {
-                    break; /* failure */
-                }
-                suite_found = PR_TRUE;
-                break; /* success */
-            }
-        }
-        if (!suite_found) {
-            desc = handshake_failure;
-            errCode = SSL_ERROR_NO_COMPRESSION_OVERLAP;
-            goto alert_loser;
-        }
-        ss->ssl3.hs.compression = (SSLCompressionMethod)temp;
-    } else {
-        ss->ssl3.hs.compression = ssl_compression_null;
-    }
-
-    /* Note that if !isTLS and the extra stuff is not extensions, we
-     * do NOT goto alert_loser.
-     * There are some old SSL 3.0 implementations that do send stuff
-     * after the end of the server hello, and we deliberately ignore
-     * such stuff in the interest of maximal interoperability (being
-     * "generous in what you accept").
-     * Update: Starting in NSS 3.12.6, we handle the renegotiation_info
-     * extension in SSL 3.0.
-     */
-    if (length != 0) {
-        SECItem extensions;
-        rv = ssl3_ConsumeHandshakeVariable(ss, &extensions, 2, &b, &length);
-        if (rv != SECSuccess || length != 0) {
-            if (isTLS)
-                goto alert_loser;
-        } else {
-            rv = ssl3_HandleHelloExtensions(ss, &extensions.data,
-                                            &extensions.len, server_hello);
-            if (rv != SECSuccess)
-                goto alert_loser;
-        }
-    }
-    if ((ss->opt.requireSafeNegotiation ||
-         (ss->firstHsDone && (ss->peerRequestedProtection ||
-                              ss->opt.enableRenegotiation ==
-                                  SSL_RENEGOTIATE_REQUIRES_XTN))) &&
-        !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
-        desc = handshake_failure;
-        errCode = ss->firstHsDone ? SSL_ERROR_RENEGOTIATION_NOT_ALLOWED
-                                  : SSL_ERROR_UNSAFE_NEGOTIATION;
-        goto alert_loser;
-    }
-
-    /* Any errors after this point are not "malformed" errors. */
-    desc = handshake_failure;
-
-    /* we need to call ssl3_SetupPendingCipherSpec here so we can check the
-     * key exchange algorithm. */
-    rv = ssl3_SetupPendingCipherSpec(ss);
-    if (rv != SECSuccess) {
-        goto alert_loser; /* error code is set. */
-    }
-
-    /* We may or may not have sent a session id, we may get one back or
-     * not and if so it may match the one we sent.
-     * Attempt to restore the master secret to see if this is so...
-     * Don't consider failure to find a matching SID an error.
-     */
-    sid_match = (PRBool)(sidBytes.len > 0 &&
-                         sidBytes.len ==
-                             sid->u.ssl3.sessionIDLength &&
-                         !PORT_Memcmp(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len));
-
-    if (sid_match &&
-        sid->version == ss->version &&
-        sid->u.ssl3.cipherSuite == ss->ssl3.hs.cipher_suite)
-        do {
-            ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
-
-            SECItem wrappedMS; /* wrapped master secret. */
-
-            /* [draft-ietf-tls-session-hash-06; Section 5.3]
-             *
-             * o  If the original session did not use the "extended_master_secret"
-             *    extension but the new ServerHello contains the extension, the
-             *    client MUST abort the handshake.
-             */
-            if (!sid->u.ssl3.keys.extendedMasterSecretUsed &&
-                ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) {
-                errCode = SSL_ERROR_UNEXPECTED_EXTENDED_MASTER_SECRET;
-                goto alert_loser;
-            }
-
-            /*
-             *   o  If the original session used an extended master secret but the new
-             *      ServerHello does not contain the "extended_master_secret"
-             *      extension, the client SHOULD abort the handshake.
-             *
-             * TODO(ekr@rtfm.com): Add option to refuse to resume when EMS is not
-             * used at all (bug 1176526).
-             */
-            if (sid->u.ssl3.keys.extendedMasterSecretUsed &&
-                !ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) {
-                errCode = SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET;
-                goto alert_loser;
-            }
-
-            ss->sec.authAlgorithm = sid->authAlgorithm;
-            ss->sec.authKeyBits = sid->authKeyBits;
-            ss->sec.keaType = sid->keaType;
-            ss->sec.keaKeyBits = sid->keaKeyBits;
-
-            /* 3 cases here:
-             * a) key is wrapped (implies using PKCS11)
-             * b) key is unwrapped, but we're still using PKCS11
-             * c) key is unwrapped, and we're bypassing PKCS11.
-             */
-            if (sid->u.ssl3.keys.msIsWrapped) {
-                PK11SlotInfo *slot;
-                PK11SymKey *wrapKey; /* wrapping key */
-                CK_FLAGS keyFlags = 0;
-
-#ifndef NO_PKCS11_BYPASS
-                if (ss->opt.bypassPKCS11) {
-                    /* we cannot restart a non-bypass session in a
-                    ** bypass socket.
-                    */
-                    break;
-                }
-#endif
-                /* unwrap master secret with PKCS11 */
-                slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID,
-                                         sid->u.ssl3.masterSlotID);
-                if (slot == NULL) {
-                    break; /* not considered an error. */
-                }
-                if (!PK11_IsPresent(slot)) {
-                    PK11_FreeSlot(slot);
-                    break; /* not considered an error. */
-                }
-                wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex,
-                                          sid->u.ssl3.masterWrapMech,
-                                          sid->u.ssl3.masterWrapSeries,
-                                          ss->pkcs11PinArg);
-                PK11_FreeSlot(slot);
-                if (wrapKey == NULL) {
-                    break; /* not considered an error. */
-                }
-
-                if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */
-                    keyFlags =
-                        CKF_SIGN | CKF_VERIFY;
-                }
-
-                wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
-                wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
-                pwSpec->master_secret =
-                    PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech,
-                                               NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE,
-                                               CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags);
-                errCode = PORT_GetError();
-                PK11_FreeSymKey(wrapKey);
-                if (pwSpec->master_secret == NULL) {
-                    break; /* errorCode set just after call to UnwrapSymKey. */
-                }
-#ifndef NO_PKCS11_BYPASS
-            } else if (ss->opt.bypassPKCS11) {
-                /* MS is not wrapped */
-                wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
-                wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
-                memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len);
-                pwSpec->msItem.data = pwSpec->raw_master_secret;
-                pwSpec->msItem.len = wrappedMS.len;
-#endif
-            } else {
-                /* We CAN restart a bypass session in a non-bypass socket. */
-                /* need to import the raw master secret to session object */
-                PK11SlotInfo *slot = PK11_GetInternalSlot();
-                wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
-                wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
-                pwSpec->master_secret =
-                    PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE,
-                                      PK11_OriginUnwrap, CKA_ENCRYPT,
-                                      &wrappedMS, NULL);
-                PK11_FreeSlot(slot);
-                if (pwSpec->master_secret == NULL) {
-                    break;
-                }
-            }
-
-            /* Got a Match */
-            SSL_AtomicIncrementLong(&ssl3stats.hsh_sid_cache_hits);
-
-            /* If we sent a session ticket, then this is a stateless resume. */
-            if (ss->xtnData.sentSessionTicketInClientHello)
-                SSL_AtomicIncrementLong(&ssl3stats.hsh_sid_stateless_resumes);
-
-            if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn))
-                ss->ssl3.hs.ws = wait_new_session_ticket;
-            else
-                ss->ssl3.hs.ws = wait_change_cipher;
-
-            ss->ssl3.hs.isResuming = PR_TRUE;
-
-            /* copy the peer cert from the SID */
-            if (sid->peerCert != NULL) {
-                ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
-                ssl3_CopyPeerCertsFromSID(ss, sid);
-            }
-
-            /* NULL value for PMS because we are reusing the old MS */
-            rv = ssl3_InitPendingCipherSpec(ss, NULL);
-            if (rv != SECSuccess) {
-                goto alert_loser; /* err code was set */
-            }
-            goto winner;
-        } while (0);
-
-    if (sid_match)
-        SSL_AtomicIncrementLong(&ssl3stats.hsh_sid_cache_not_ok);
-    else
-        SSL_AtomicIncrementLong(&ssl3stats.hsh_sid_cache_misses);
-
-    /* throw the old one away */
-    sid->u.ssl3.keys.resumable = PR_FALSE;
-    if (ss->sec.uncache)
-        (*ss->sec.uncache)(sid);
-    ssl_FreeSID(sid);
-
-    /* get a new sid */
-    ss->sec.ci.sid = sid = ssl3_NewSessionID(ss, PR_FALSE);
-    if (sid == NULL) {
-        goto alert_loser; /* memory error is set. */
-    }
-
-    sid->version = ss->version;
-    sid->u.ssl3.sessionIDLength = sidBytes.len;
-    PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len);
-
-    sid->u.ssl3.keys.extendedMasterSecretUsed =
-        ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn);
-
-    /* Copy Signed Certificate Timestamps, if any. */
-    if (ss->xtnData.signedCertTimestamps.data) {
-        rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.signedCertTimestamps,
-                              &ss->xtnData.signedCertTimestamps);
-        if (rv != SECSuccess)
-            goto loser;
-        /* Clean up the temporary pointer to the handshake buffer. */
-        ss->xtnData.signedCertTimestamps.data = NULL;
-        ss->xtnData.signedCertTimestamps.len = 0;
-    }
-
-    ss->ssl3.hs.isResuming = PR_FALSE;
-    if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
-        rv = tls13_HandleServerKeyShare(ss);
-        if (rv != SECSuccess)
-            goto alert_loser;
-        TLS13_SET_HS_STATE(ss, wait_encrypted_extensions);
-    } else if (ss->ssl3.hs.kea_def->signKeyType != ssl_sign_null) {
-        /* All current cipher suites other than those with ssl_sign_null (i.e.,
-         * (EC)DH_anon_* suites) require a certificate, so use that signal. */
-        ss->ssl3.hs.ws = wait_server_cert;
-    } else {
-        /* All the remaining cipher suites must be (EC)DH_anon_* and so
-         * must be ephemeral. Note, if we ever add PSK this might
-         * change. */
-        PORT_Assert(ss->ssl3.hs.kea_def->ephemeral);
-        ss->ssl3.hs.ws = wait_server_key;
-    }
-
-winner:
-    /* If we will need a ChannelID key then we make the callback now. This
-     * allows the handshake to be restarted cleanly if the callback returns
-     * SECWouldBlock. */
-    if (ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)) {
-        rv = ss->getChannelID(ss->getChannelIDArg, ss->fd,
-                              &ss->ssl3.channelIDPub, &ss->ssl3.channelID);
-        if (rv == SECWouldBlock) {
-            ssl3_SetAlwaysBlock(ss);
-            return rv;
-        }
-        if (rv != SECSuccess ||
-            ss->ssl3.channelIDPub == NULL ||
-            ss->ssl3.channelID == NULL) {
-            PORT_SetError(SSL_ERROR_GET_CHANNEL_ID_FAILED);
-            desc = internal_error;
-            goto alert_loser;
-        }
-    }
-
-    return SECSuccess;
-
-alert_loser:
-    (void)SSL3_SendAlert(ss, alert_fatal, desc);
-
-loser:
-    /* Clean up the temporary pointer to the handshake buffer. */
-    ss->xtnData.signedCertTimestamps.data = NULL;
-    ss->xtnData.signedCertTimestamps.len = 0;
-    ssl_MapLowLevelError(errCode);
-    return SECFailure;
-}
-
-/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered a
- * complete ssl3 ServerKeyExchange message.
- * Caller must hold Handshake and RecvBuf locks.
- */
-static SECStatus
-ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    PLArenaPool *arena = NULL;
-    SECKEYPublicKey *peerKey = NULL;
-    PRBool isTLS, isTLS12;
-    SECStatus rv;
-    int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
-    SSL3AlertDescription desc = illegal_parameter;
-    SSL3Hashes hashes;
-    SECItem signature = { siBuffer, NULL, 0 };
-    SSLSignatureAndHashAlg sigAndHash;
-
-    sigAndHash.hashAlg = ssl_hash_none;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: handle server_key_exchange handshake",
-                SSL_GETPID(), ss->fd));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if (ss->ssl3.hs.ws != wait_server_key) {
-        errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH;
-        desc = unexpected_message;
-        goto alert_loser;
-    }
-
-    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
-    isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
-
-    switch (ss->ssl3.hs.kea_def->exchKeyType) {
-
-        case kt_rsa: {
-            SECItem modulus = { siBuffer, NULL, 0 };
-            SECItem exponent = { siBuffer, NULL, 0 };
-
-            rv = ssl3_ConsumeHandshakeVariable(ss, &modulus, 2, &b, &length);
-            if (rv != SECSuccess) {
-                goto loser; /* malformed. */
-            }
-            /* This exchange method is only used by export cipher suites.
-             * Those are broken and so this code will eventually be removed. */
-            if (SECKEY_BigIntegerBitLength(&modulus) < 512) {
-                desc = isTLS ? insufficient_security : illegal_parameter;
-                goto alert_loser;
-            }
-            rv = ssl3_ConsumeHandshakeVariable(ss, &exponent, 2, &b, &length);
-            if (rv != SECSuccess) {
-                goto loser; /* malformed. */
-            }
-            if (isTLS12) {
-                rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
-                                                           &sigAndHash);
-                if (rv != SECSuccess) {
-                    goto loser; /* malformed or unsupported. */
-                }
-                rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(ss,
-                                                                    &sigAndHash, ss->sec.peerCert);
-                if (rv != SECSuccess) {
-                    goto loser;
-                }
-            }
-            rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
-            if (rv != SECSuccess) {
-                goto loser; /* malformed. */
-            }
-            if (length != 0) {
-                if (isTLS)
-                    desc =
-                        decode_error;
-                goto alert_loser; /* malformed. */
-            }
-
-            /* failures after this point are not malformed handshakes. */
-            /* TLS: send decrypt_error if signature failed. */
-            desc = isTLS ? decrypt_error : handshake_failure;
-
-            /*
-             *  check to make sure the hash is signed by right guy
-             */
-            rv = ssl3_ComputeExportRSAKeyHash(sigAndHash.hashAlg, modulus, exponent,
-                                              &ss->ssl3.hs.client_random,
-                                              &ss->ssl3.hs.server_random,
-                                              &hashes, ss->opt.bypassPKCS11);
-            if (rv != SECSuccess) {
-                errCode =
-                    ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-                goto alert_loser;
-            }
-            rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
-                                         isTLS, ss->pkcs11PinArg);
-            if (rv != SECSuccess) {
-                errCode =
-                    ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-                goto alert_loser;
-            }
-
-            /*
-             * we really need to build a new key here because we can no longer
-             * ignore calling SECKEY_DestroyPublicKey. Using the key may allocate
-             * pkcs11 slots and ID's.
-             */
-            arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-            if (arena == NULL) {
-                goto no_memory;
-            }
-
-            peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
-            if (peerKey == NULL) {
-                goto no_memory;
-            }
-
-            peerKey->arena = arena;
-            peerKey->keyType = rsaKey;
-            peerKey->pkcs11Slot = NULL;
-            peerKey->pkcs11ID = CK_INVALID_HANDLE;
-            if (SECITEM_CopyItem(arena, &peerKey->u.rsa.modulus, &modulus) ||
-                SECITEM_CopyItem(arena, &peerKey->u.rsa.publicExponent, &exponent)) {
-                goto no_memory;
-            }
-            ss->sec.peerKey = peerKey;
-            ss->ssl3.hs.ws = wait_cert_request;
-            return SECSuccess;
-        }
-
-        case kt_dh: {
-            SECItem dh_p = { siBuffer, NULL, 0 };
-            SECItem dh_g = { siBuffer, NULL, 0 };
-            SECItem dh_Ys = { siBuffer, NULL, 0 };
-            unsigned dh_p_bits;
-            unsigned dh_g_bits;
-            unsigned dh_Ys_bits;
-            PRInt32 minDH;
-
-            rv = ssl3_ConsumeHandshakeVariable(ss, &dh_p, 2, &b, &length);
-            if (rv != SECSuccess) {
-                goto loser; /* malformed. */
-            }
-
-            rv = NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &minDH);
-            if (rv != SECSuccess) {
-                minDH = SSL_DH_MIN_P_BITS;
-            }
-            dh_p_bits = SECKEY_BigIntegerBitLength(&dh_p);
-            if (dh_p_bits < minDH) {
-                errCode = SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY;
-                goto alert_loser;
-            }
-            rv = ssl3_ConsumeHandshakeVariable(ss, &dh_g, 2, &b, &length);
-            if (rv != SECSuccess) {
-                goto loser; /* malformed. */
-            }
-            /* Abort if dh_g is 0, 1, or obviously too big. */
-            dh_g_bits = SECKEY_BigIntegerBitLength(&dh_g);
-            if (dh_g_bits > dh_p_bits || dh_g_bits <= 1)
-                goto alert_loser;
-            rv = ssl3_ConsumeHandshakeVariable(ss, &dh_Ys, 2, &b, &length);
-            if (rv != SECSuccess) {
-                goto loser; /* malformed. */
-            }
-            dh_Ys_bits = SECKEY_BigIntegerBitLength(&dh_Ys);
-            if (dh_Ys_bits > dh_p_bits || dh_Ys_bits <= 1)
-                goto alert_loser;
-            if (isTLS12) {
-                rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
-                                                           &sigAndHash);
-                if (rv != SECSuccess) {
-                    goto loser; /* malformed or unsupported. */
-                }
-                rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(ss,
-                                                                    &sigAndHash, ss->sec.peerCert);
-                if (rv != SECSuccess) {
-                    goto loser;
-                }
-            }
-            rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
-            if (rv != SECSuccess) {
-                goto loser; /* malformed. */
-            }
-            if (length != 0) {
-                if (isTLS)
-                    desc =
-                        decode_error;
-                goto alert_loser; /* malformed. */
-            }
-
-            PRINT_BUF(60, (NULL, "Server DH p", dh_p.data, dh_p.len));
-            PRINT_BUF(60, (NULL, "Server DH g", dh_g.data, dh_g.len));
-            PRINT_BUF(60, (NULL, "Server DH Ys", dh_Ys.data, dh_Ys.len));
-
-            /* failures after this point are not malformed handshakes. */
-            /* TLS: send decrypt_error if signature failed. */
-            desc = isTLS ? decrypt_error : handshake_failure;
-
-            /*
-             *  check to make sure the hash is signed by right guy
-             */
-            rv = ssl3_ComputeDHKeyHash(sigAndHash.hashAlg, dh_p, dh_g, dh_Ys,
-                                       &ss->ssl3.hs.client_random,
-                                       &ss->ssl3.hs.server_random,
-                                       &hashes, ss->opt.bypassPKCS11);
-            if (rv != SECSuccess) {
-                errCode =
-                    ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-                goto alert_loser;
-            }
-            rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
-                                         isTLS, ss->pkcs11PinArg);
-            if (rv != SECSuccess) {
-                errCode =
-                    ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-                goto alert_loser;
-            }
-
-            /*
-             * we really need to build a new key here because we can no longer
-             * ignore calling SECKEY_DestroyPublicKey. Using the key may allocate
-             * pkcs11 slots and ID's.
-             */
-            arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-            if (arena == NULL) {
-                goto no_memory;
-            }
-
-            peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
-            if (peerKey == NULL) {
-                goto no_memory;
-            }
-
-            peerKey->arena = arena;
-            peerKey->keyType = dhKey;
-            peerKey->pkcs11Slot = NULL;
-            peerKey->pkcs11ID = CK_INVALID_HANDLE;
-
-            if (SECITEM_CopyItem(arena, &peerKey->u.dh.prime, &dh_p) ||
-                SECITEM_CopyItem(arena, &peerKey->u.dh.base, &dh_g) ||
-                SECITEM_CopyItem(arena, &peerKey->u.dh.publicValue, &dh_Ys)) {
-                goto no_memory;
-            }
-            ss->sec.peerKey = peerKey;
-            ss->ssl3.hs.ws = wait_cert_request;
-            return SECSuccess;
-        }
-
-#ifndef NSS_DISABLE_ECC
-        case kt_ecdh:
-            rv = ssl3_HandleECDHServerKeyExchange(ss, b, length);
-            return rv;
-#endif /* NSS_DISABLE_ECC */
-
-        default:
-            desc = handshake_failure;
-            errCode = SEC_ERROR_UNSUPPORTED_KEYALG;
-            break; /* goto alert_loser; */
-    }
-
-alert_loser:
-    (void)SSL3_SendAlert(ss, alert_fatal, desc);
-loser:
-    if (arena) {
-        PORT_FreeArena(arena, PR_FALSE);
-    }
-    PORT_SetError(errCode);
-    return SECFailure;
-
-no_memory: /* no-memory error has already been set. */
-    if (arena) {
-        PORT_FreeArena(arena, PR_FALSE);
-    }
-    ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-    return SECFailure;
-}
-
-/*
- * Returns the TLS signature algorithm for the client authentication key and
- * whether it is an RSA or DSA key that may be able to sign only SHA-1 hashes.
- */
-static SECStatus
-ssl3_ExtractClientKeyInfo(sslSocket *ss,
-                          SSLSignType *sigAlg,
-                          PRBool *preferSha1)
-{
-    SECStatus rv = SECSuccess;
-    SECKEYPublicKey *pubk;
-
-    pubk = CERT_ExtractPublicKey(ss->ssl3.clientCertificate);
-    if (pubk == NULL) {
-        rv = SECFailure;
-        goto done;
-    }
-
-    rv = ssl3_TLSSignatureAlgorithmForKeyType(pubk->keyType, sigAlg);
-    if (rv != SECSuccess) {
-        goto done;
-    }
-
-    /* If the key is a 1024-bit RSA or DSA key, assume conservatively that
-     * it may be unable to sign SHA-256 hashes. This is the case for older
-     * Estonian ID cards that have 1024-bit RSA keys. In FIPS 186-2 and
-     * older, DSA key size is at most 1024 bits and the hash function must
-     * be SHA-1.
-     */
-    if (pubk->keyType == rsaKey || pubk->keyType == dsaKey) {
-        *preferSha1 = SECKEY_PublicKeyStrength(pubk) <= 128;
-    } else {
-        *preferSha1 = PR_FALSE;
-    }
-
-done:
-    if (pubk)
-        SECKEY_DestroyPublicKey(pubk);
-    return rv;
-}
-
-/* Destroys the backup handshake hash context if we don't need it. Note that
- * this function selects the hash algorithm for client authentication
- * signatures; ssl3_SendCertificateVerify uses the presence of the backup hash
- * to determine whether to use SHA-1 or SHA-256. */
-static void
-ssl3_DestroyBackupHandshakeHashIfNotNeeded(sslSocket *ss,
-                                           const SECItem *algorithms)
-{
-    SECStatus rv;
-    SSLSignType sigAlg;
-    PRBool preferSha1 = PR_FALSE;
-    PRBool supportsSha1 = PR_FALSE;
-    PRBool supportsSha256 = PR_FALSE;
-    PRBool needBackupHash = PR_FALSE;
-    unsigned int i;
-
-#ifndef NO_PKCS11_BYPASS
-    /* Backup handshake hash is not supported in PKCS #11 bypass mode. */
-    if (ss->opt.bypassPKCS11) {
-        PORT_Assert(!ss->ssl3.hs.backupHash);
-        return;
-    }
-#endif
-    PORT_Assert(ss->ssl3.hs.backupHash);
-
-    /* Determine the key's signature algorithm and whether it prefers SHA-1. */
-    rv = ssl3_ExtractClientKeyInfo(ss, &sigAlg, &preferSha1);
-    if (rv != SECSuccess) {
-        goto done;
-    }
-
-    /* Determine the server's hash support for that signature algorithm. */
-    for (i = 0; i < algorithms->len; i += 2) {
-        if (algorithms->data[i + 1] == sigAlg) {
-            if (algorithms->data[i] == ssl_hash_sha1) {
-                supportsSha1 = PR_TRUE;
-            } else if (algorithms->data[i] == ssl_hash_sha256) {
-                supportsSha256 = PR_TRUE;
-            }
-        }
-    }
-
-    /* If either the server does not support SHA-256 or the client key prefers
-     * SHA-1, leave the backup hash. */
-    if (supportsSha1 && (preferSha1 || !supportsSha256)) {
-        needBackupHash = PR_TRUE;
-    }
-
-done:
-    if (!needBackupHash) {
-        PK11_DestroyContext(ss->ssl3.hs.backupHash, PR_TRUE);
-        ss->ssl3.hs.backupHash = NULL;
-    }
-}
-
-typedef struct dnameNode {
-    struct dnameNode *next;
-    SECItem name;
-} dnameNode;
-
-/*
- * Parse the ca_list structure in a CertificateRequest.
- *
- * Called from:
- * ssl3_HandleCertificateRequest
- * tls13_HandleCertificateRequest
- */
-SECStatus
-ssl3_ParseCertificateRequestCAs(sslSocket *ss, SSL3Opaque **b, PRUint32 *length,
-                                PLArenaPool *arena, CERTDistNames *ca_list)
-{
-    PRInt32 remaining;
-    int nnames = 0;
-    dnameNode *node;
-    int i;
-
-    remaining = ssl3_ConsumeHandshakeNumber(ss, 2, b, length);
-    if (remaining < 0)
-        return SECFailure; /* malformed, alert has been sent */
-
-    if ((PRUint32)remaining > *length)
-        goto alert_loser;
-
-    ca_list->head = node = PORT_ArenaZNew(arena, dnameNode);
-    if (node == NULL)
-        goto no_mem;
-
-    while (remaining > 0) {
-        PRInt32 len;
-
-        if (remaining < 2)
-            goto alert_loser; /* malformed */
-
-        node->name.len = len = ssl3_ConsumeHandshakeNumber(ss, 2, b, length);
-        if (len <= 0)
-            return SECFailure; /* malformed, alert has been sent */
-
-        remaining -= 2;
-        if (remaining < len)
-            goto alert_loser; /* malformed */
-
-        node->name.data = *b;
-        *b += len;
-        *length -= len;
-        remaining -= len;
-        nnames++;
-        if (remaining <= 0)
-            break; /* success */
-
-        node->next = PORT_ArenaZNew(arena, dnameNode);
-        node = node->next;
-        if (node == NULL)
-            goto no_mem;
-    }
-
-    ca_list->nnames = nnames;
-    ca_list->names = PORT_ArenaNewArray(arena, SECItem, nnames);
-    if (nnames > 0 && ca_list->names == NULL)
-        goto no_mem;
-
-    for (i = 0, node = (dnameNode *)ca_list->head;
-         i < nnames;
-         i++, node = node->next) {
-        ca_list->names[i] = node->name;
-    }
-
-    return SECSuccess;
-
-no_mem:
-    PORT_SetError(SEC_ERROR_NO_MEMORY);
-    return SECFailure;
-
-alert_loser:
-    (void)SSL3_SendAlert(ss, alert_fatal,
-                         ss->version < SSL_LIBRARY_VERSION_TLS_1_0 ? illegal_parameter
-                                                                   : decode_error);
-    PORT_SetError(SSL_ERROR_RX_MALFORMED_CERT_REQUEST);
-    return SECFailure;
-}
-
-/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered
- * a complete ssl3 Certificate Request message.
- * Caller must hold Handshake and RecvBuf locks.
- */
-static SECStatus
-ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    PLArenaPool *arena = NULL;
-    PRBool isTLS = PR_FALSE;
-    PRBool isTLS12 = PR_FALSE;
-    int errCode = SSL_ERROR_RX_MALFORMED_CERT_REQUEST;
-    SECStatus rv;
-    SSL3AlertDescription desc = illegal_parameter;
-    SECItem cert_types = { siBuffer, NULL, 0 };
-    SECItem algorithms = { siBuffer, NULL, 0 };
-    CERTDistNames ca_list;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_request handshake",
-                SSL_GETPID(), ss->fd));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if (ss->ssl3.hs.ws != wait_cert_request) {
-        desc = unexpected_message;
-        errCode = SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST;
-        goto alert_loser;
-    }
-
-    PORT_Assert(ss->ssl3.clientCertChain == NULL);
-    PORT_Assert(ss->ssl3.clientCertificate == NULL);
-    PORT_Assert(ss->ssl3.clientPrivateKey == NULL);
-
-    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
-    isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
-    rv = ssl3_ConsumeHandshakeVariable(ss, &cert_types, 1, &b, &length);
-    if (rv != SECSuccess)
-        goto loser; /* malformed, alert has been sent */
-
-    PORT_Assert(!ss->requestedCertTypes);
-    ss->requestedCertTypes = &cert_types;
-
-    if (isTLS12) {
-        rv = ssl3_ConsumeHandshakeVariable(ss, &algorithms, 2, &b, &length);
-        if (rv != SECSuccess)
-            goto loser; /* malformed, alert has been sent */
-        /* An empty or odd-length value is invalid.
-         *    SignatureAndHashAlgorithm
-         *      supported_signature_algorithms<2..2^16-2>;
-         */
-        if (algorithms.len == 0 || (algorithms.len & 1) != 0)
-            goto alert_loser;
-    }
-
-    arena = ca_list.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-    if (arena == NULL)
-        goto no_mem;
-
-    rv = ssl3_ParseCertificateRequestCAs(ss, &b, &length, arena, &ca_list);
-    if (rv != SECSuccess)
-        goto done; /* alert sent in ssl3_ParseCertificateRequestCAs */
-
-    if (length != 0)
-        goto alert_loser; /* malformed */
-
-    desc = no_certificate;
-
-    ss->ssl3.hs.ws = wait_hello_done;
-
-    rv = ssl3_CompleteHandleCertificateRequest(ss, &algorithms, &ca_list);
-    if (rv == SECFailure) {
-        PORT_Assert(0);
-        errCode = SEC_ERROR_LIBRARY_FAILURE;
-        desc = internal_error;
-        goto alert_loser;
-    }
-    goto done;
-
-no_mem:
-    rv = SECFailure;
-    PORT_SetError(SEC_ERROR_NO_MEMORY);
-    goto done;
-
-alert_loser:
-    if (isTLS && desc == illegal_parameter)
-        desc = decode_error;
-    (void)SSL3_SendAlert(ss, alert_fatal, desc);
-loser:
-    PORT_SetError(errCode);
-    rv = SECFailure;
-done:
-    ss->requestedCertTypes = NULL;
-    if (arena != NULL)
-        PORT_FreeArena(arena, PR_FALSE);
-    return rv;
-}
-
-SECStatus
-ssl3_CompleteHandleCertificateRequest(sslSocket *ss, SECItem *algorithms,
-                                      CERTDistNames *ca_list)
-{
-    SECStatus rv;
-
-    if (ss->getClientAuthData != NULL) {
-        PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
-                    ssl_preinfo_all);
-        /* XXX Should pass cert_types and algorithms in this call!! */
-        rv = (SECStatus)(*ss->getClientAuthData)(ss->getClientAuthDataArg,
-                                                 ss->fd, ca_list,
-                                                 &ss->ssl3.clientCertificate,
-                                                 &ss->ssl3.clientPrivateKey);
-    } else {
-        rv = SECFailure; /* force it to send a no_certificate alert */
-    }
-    switch (rv) {
-        case SECWouldBlock: /* getClientAuthData has put up a dialog box. */
-            ssl3_SetAlwaysBlock(ss);
-            break; /* not an error */
-
-        case SECSuccess:
-            /* check what the callback function returned */
-            if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) {
-                /* we are missing either the key or cert */
-                if (ss->ssl3.clientCertificate) {
-                    /* got a cert, but no key - free it */
-                    CERT_DestroyCertificate(ss->ssl3.clientCertificate);
-                    ss->ssl3.clientCertificate = NULL;
-                }
-                if (ss->ssl3.clientPrivateKey) {
-                    /* got a key, but no cert - free it */
-                    SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
-                    ss->ssl3.clientPrivateKey = NULL;
-                }
-                goto send_no_certificate;
-            }
-            /* Setting ssl3.clientCertChain non-NULL will cause
-             * ssl3_HandleServerHelloDone to call SendCertificate.
-             */
-            ss->ssl3.clientCertChain = CERT_CertChainFromCert(
-                ss->ssl3.clientCertificate,
-                certUsageSSLClient, PR_FALSE);
-            if (ss->ssl3.clientCertChain == NULL) {
-                CERT_DestroyCertificate(ss->ssl3.clientCertificate);
-                ss->ssl3.clientCertificate = NULL;
-                SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
-                ss->ssl3.clientPrivateKey = NULL;
-                goto send_no_certificate;
-            }
-            if (ss->ssl3.hs.hashType == handshake_hash_single) {
-                ssl3_DestroyBackupHandshakeHashIfNotNeeded(ss, algorithms);
-            }
-            break; /* not an error */
-
-        case SECFailure:
-        default:
-        send_no_certificate:
-            if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0) {
-                ss->ssl3.sendEmptyCert = PR_TRUE;
-            } else {
-                (void)SSL3_SendAlert(ss, alert_warning, no_certificate);
-            }
-            rv = SECSuccess;
-            break;
-    }
-
-    return rv;
-}
-
-/*
- * attempt to restart the handshake after asynchronously handling
- * a request for the client's certificate.
- *
- * inputs:
- *	cert	Client cert chosen by application.
- *		Note: ssl takes this reference, and does not bump the
- *		reference count.  The caller should drop its reference
- *		without calling CERT_DestroyCert after calling this function.
- *
- *	key	Private key associated with cert.  This function takes
- *		ownership of the private key, so the caller should drop its
- *		reference without destroying the private key after this
- *		function returns.
- *
- *	certChain  DER-encoded certs, client cert and its signers.
- *		Note: ssl takes this reference, and does not copy the chain.
- *		The caller should drop its reference without destroying the
- *		chain.  SSL will free the chain when it is done with it.
- *
- * Return value: XXX
- *
- * XXX This code only works on the initial handshake on a connection, XXX
- *     It does not work on a subsequent handshake (redo).
- *
- * Caller holds 1stHandshakeLock.
- */
-SECStatus
-ssl3_RestartHandshakeAfterCertReq(sslSocket *ss,
-                                  CERTCertificate *cert,
-                                  SECKEYPrivateKey *key,
-                                  CERTCertificateList *certChain)
-{
-    SECStatus rv = SECSuccess;
-
-    /* XXX This code only works on the initial handshake on a connection,
-    ** XXX It does not work on a subsequent handshake (redo).
-    */
-    if (ss->handshake != 0) {
-        ss->handshake = ssl_GatherRecord1stHandshake;
-        ss->ssl3.clientCertificate = cert;
-        ss->ssl3.clientPrivateKey = key;
-        ss->ssl3.clientCertChain = certChain;
-        if (!cert || !key || !certChain) {
-            /* we are missing the key, cert, or cert chain */
-            if (ss->ssl3.clientCertificate) {
-                CERT_DestroyCertificate(ss->ssl3.clientCertificate);
-                ss->ssl3.clientCertificate = NULL;
-            }
-            if (ss->ssl3.clientPrivateKey) {
-                SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
-                ss->ssl3.clientPrivateKey = NULL;
-            }
-            if (ss->ssl3.clientCertChain != NULL) {
-                CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
-                ss->ssl3.clientCertChain = NULL;
-            }
-            if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0) {
-                ss->ssl3.sendEmptyCert = PR_TRUE;
-            } else {
-                (void)SSL3_SendAlert(ss, alert_warning, no_certificate);
-            }
-        }
-    } else {
-        if (cert) {
-            CERT_DestroyCertificate(cert);
-        }
-        if (key) {
-            SECKEY_DestroyPrivateKey(key);
-        }
-        if (certChain) {
-            CERT_DestroyCertificateList(certChain);
-        }
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        rv = SECFailure;
-    }
-    return rv;
-}
-
-static SECStatus
-ssl3_CheckFalseStart(sslSocket *ss)
-{
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(!ss->ssl3.hs.authCertificatePending);
-    PORT_Assert(!ss->ssl3.hs.canFalseStart);
-
-    if (!ss->canFalseStartCallback) {
-        SSL_TRC(3, ("%d: SSL[%d]: no false start callback so no false start",
-                    SSL_GETPID(), ss->fd));
-    } else {
-        PRBool maybeFalseStart;
-        SECStatus rv;
-
-        /* An attacker can control the selected ciphersuite so we only wish to
-         * do False Start in the case that the selected ciphersuite is
-         * sufficiently strong that the attack can gain no advantage.
-         * Therefore we always require an 80-bit cipher. */
-        ssl_GetSpecReadLock(ss);
-        maybeFalseStart = ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10;
-        ssl_ReleaseSpecReadLock(ss);
-
-        if (!maybeFalseStart) {
-            SSL_TRC(3, ("%d: SSL[%d]: no false start due to weak cipher",
-                        SSL_GETPID(), ss->fd));
-        } else {
-            PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
-                        ssl_preinfo_all);
-            rv = (ss->canFalseStartCallback)(ss->fd,
-                                             ss->canFalseStartCallbackData,
-                                             &ss->ssl3.hs.canFalseStart);
-            if (rv == SECSuccess) {
-                SSL_TRC(3, ("%d: SSL[%d]: false start callback returned %s",
-                            SSL_GETPID(), ss->fd,
-                            ss->ssl3.hs.canFalseStart ? "TRUE"
-                                                      : "FALSE"));
-            } else {
-                SSL_TRC(3, ("%d: SSL[%d]: false start callback failed (%s)",
-                            SSL_GETPID(), ss->fd,
-                            PR_ErrorToName(PR_GetError())));
-            }
-            return rv;
-        }
-    }
-
-    ss->ssl3.hs.canFalseStart = PR_FALSE;
-    return SECSuccess;
-}
-
-PRBool
-ssl3_WaitingForServerSecondRound(sslSocket *ss)
-{
-    PRBool result;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    switch (ss->ssl3.hs.ws) {
-        case wait_new_session_ticket:
-        case wait_change_cipher:
-        case wait_finished:
-            result = PR_TRUE;
-            break;
-        default:
-            result = PR_FALSE;
-            break;
-    }
-
-    return result;
-}
-
-static SECStatus ssl3_SendClientSecondRound(sslSocket *ss);
-
-/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered
- * a complete ssl3 Server Hello Done message.
- * Caller must hold Handshake and RecvBuf locks.
- */
-static SECStatus
-ssl3_HandleServerHelloDone(sslSocket *ss)
-{
-    SECStatus rv;
-    SSL3WaitState ws = ss->ssl3.hs.ws;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello_done handshake",
-                SSL_GETPID(), ss->fd));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    /* Skipping CertificateRequest is always permitted. */
-    if (ws != wait_hello_done &&
-        ws != wait_cert_request) {
-        SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-        PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE);
-        return SECFailure;
-    }
-
-    rv = ssl3_SendClientSecondRound(ss);
-
-    return rv;
-}
-
-/* Called from ssl3_HandleServerHelloDone and ssl3_AuthCertificateComplete.
- *
- * Caller must hold Handshake and RecvBuf locks.
- */
-static SECStatus
-ssl3_SendClientSecondRound(sslSocket *ss)
-{
-    SECStatus rv;
-    PRBool sendClientCert;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    sendClientCert = !ss->ssl3.sendEmptyCert &&
-                     ss->ssl3.clientCertChain != NULL &&
-                     ss->ssl3.clientPrivateKey != NULL;
-
-    if (!sendClientCert &&
-        ss->ssl3.hs.hashType == handshake_hash_single &&
-        ss->ssl3.hs.backupHash) {
-        /* Don't need the backup handshake hash. */
-        PK11_DestroyContext(ss->ssl3.hs.backupHash, PR_TRUE);
-        ss->ssl3.hs.backupHash = NULL;
-    }
-
-    /* We must wait for the server's certificate to be authenticated before
-     * sending the client certificate in order to disclosing the client
-     * certificate to an attacker that does not have a valid cert for the
-     * domain we are connecting to.
-     *
-     * XXX: We should do the same for the NPN extension, but for that we
-     * need an option to give the application the ability to leak the NPN
-     * information to get better performance.
-     *
-     * During the initial handshake on a connection, we never send/receive
-     * application data until we have authenticated the server's certificate;
-     * i.e. we have fully authenticated the handshake before using the cipher
-     * specs agreed upon for that handshake. During a renegotiation, we may
-     * continue sending and receiving application data during the handshake
-     * interleaved with the handshake records. If we were to send the client's
-     * second round for a renegotiation before the server's certificate was
-     * authenticated, then the application data sent/received after this point
-     * would be using cipher spec that hadn't been authenticated. By waiting
-     * until the server's certificate has been authenticated during
-     * renegotiations, we ensure that renegotiations have the same property
-     * as initial handshakes; i.e. we have fully authenticated the handshake
-     * before using the cipher specs agreed upon for that handshake for
-     * application data.
-     */
-    if (ss->ssl3.hs.restartTarget) {
-        PR_NOT_REACHED("unexpected ss->ssl3.hs.restartTarget");
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        return SECFailure;
-    }
-    if (ss->ssl3.hs.authCertificatePending &&
-        (sendClientCert || ss->ssl3.sendEmptyCert || ss->firstHsDone)) {
-        SSL_TRC(3, ("%d: SSL3[%p]: deferring ssl3_SendClientSecondRound because"
-                    " certificate authentication is still pending.",
-                    SSL_GETPID(), ss->fd));
-        ss->ssl3.hs.restartTarget = ssl3_SendClientSecondRound;
-        return SECWouldBlock;
-    }
-
-    ssl_GetXmitBufLock(ss); /*******************************/
-
-    if (ss->ssl3.sendEmptyCert) {
-        ss->ssl3.sendEmptyCert = PR_FALSE;
-        rv = ssl3_SendEmptyCertificate(ss);
-        /* Don't send verify */
-        if (rv != SECSuccess) {
-            goto loser; /* error code is set. */
-        }
-    } else if (sendClientCert) {
-        rv = ssl3_SendCertificate(ss);
-        if (rv != SECSuccess) {
-            goto loser; /* error code is set. */
-        }
-    }
-
-    rv = ssl3_SendClientKeyExchange(ss);
-    if (rv != SECSuccess) {
-        goto loser; /* err is set. */
-    }
-
-    if (sendClientCert) {
-        rv = ssl3_SendCertificateVerify(ss, ss->ssl3.clientPrivateKey);
-        SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
-        ss->ssl3.clientPrivateKey = NULL;
-        if (rv != SECSuccess) {
-            goto loser; /* err is set. */
-        }
-    }
-
-    rv = ssl3_SendChangeCipherSpecs(ss);
-    if (rv != SECSuccess) {
-        goto loser; /* err code was set. */
-    }
-
-    /* This must be done after we've set ss->ssl3.cwSpec in
-     * ssl3_SendChangeCipherSpecs because SSL_GetChannelInfo uses information
-     * from cwSpec. This must be done before we call ssl3_CheckFalseStart
-     * because the false start callback (if any) may need the information from
-     * the functions that depend on this being set.
-     */
-    ss->enoughFirstHsDone = PR_TRUE;
-
-    if (!ss->firstHsDone) {
-        /* XXX: If the server's certificate hasn't been authenticated by this
-         * point, then we may be leaking this NPN message to an attacker.
-         */
-        rv = ssl3_SendNextProto(ss);
-        if (rv != SECSuccess) {
-            goto loser; /* err code was set. */
-        }
-    }
-
-    rv = ssl3_SendChannelIDEncryptedExtensions(ss);
-    if (rv != SECSuccess) {
-        goto loser; /* err code was set. */
-    }
-
-    if (!ss->firstHsDone) {
-        if (ss->opt.enableFalseStart) {
-            if (!ss->ssl3.hs.authCertificatePending) {
-                /* When we fix bug 589047, we will need to know whether we are
-                 * false starting before we try to flush the client second
-                 * round to the network. With that in mind, we purposefully
-                 * call ssl3_CheckFalseStart before calling ssl3_SendFinished,
-                 * which includes a call to ssl3_FlushHandshake, so that
-                 * no application develops a reliance on such flushing being
-                 * done before its false start callback is called.
-                 */
-                ssl_ReleaseXmitBufLock(ss);
-                rv = ssl3_CheckFalseStart(ss);
-                ssl_GetXmitBufLock(ss);
-                if (rv != SECSuccess) {
-                    goto loser;
-                }
-            } else {
-                /* The certificate authentication and the server's Finished
-                 * message are racing each other. If the certificate
-                 * authentication wins, then we will try to false start in
-                 * ssl3_AuthCertificateComplete.
-                 */
-                SSL_TRC(3, ("%d: SSL3[%p]: deferring false start check because"
-                            " certificate authentication is still pending.",
-                            SSL_GETPID(), ss->fd));
-            }
-        }
-    }
-
-    rv = ssl3_SendFinished(ss, 0);
-    if (rv != SECSuccess) {
-        goto loser; /* err code was set. */
-    }
-
-    ssl_ReleaseXmitBufLock(ss); /*******************************/
-
-    if (!ss->ssl3.hs.isResuming &&
-        ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)) {
-        /* If we are negotiating ChannelID on a full handshake then we record
-         * the handshake hashes in |sid| at this point. They will be needed in
-         * the event that we resume this session and use ChannelID on the
-         * resumption handshake. */
-        SSL3Hashes hashes;
-        SECItem *originalHandshakeHash =
-            &ss->sec.ci.sid->u.ssl3.originalHandshakeHash;
-        PORT_Assert(ss->sec.ci.sid->cached == never_cached);
-
-        ssl_GetSpecReadLock(ss);
-        PORT_Assert(ss->version > SSL_LIBRARY_VERSION_3_0);
-        rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.cwSpec, &hashes, 0);
-        ssl_ReleaseSpecReadLock(ss);
-        if (rv != SECSuccess) {
-            return rv;
-        }
-
-        PORT_Assert(originalHandshakeHash->len == 0);
-        originalHandshakeHash->data = PORT_Alloc(hashes.len);
-        if (!originalHandshakeHash->data)
-            return SECFailure;
-        originalHandshakeHash->len = hashes.len;
-        memcpy(originalHandshakeHash->data, hashes.u.raw, hashes.len);
-    }
-
-    if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn))
-        ss->ssl3.hs.ws = wait_new_session_ticket;
-    else
-        ss->ssl3.hs.ws = wait_change_cipher;
-
-    PORT_Assert(ssl3_WaitingForServerSecondRound(ss));
-
-    return SECSuccess;
-
-loser:
-    ssl_ReleaseXmitBufLock(ss);
-    return rv;
-}
-
-/*
- * Routines used by servers
- */
-static SECStatus
-ssl3_SendHelloRequest(sslSocket *ss)
-{
-    SECStatus rv;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: send hello_request handshake", SSL_GETPID(),
-                ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    rv = ssl3_AppendHandshakeHeader(ss, hello_request, 0);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake */
-    }
-    rv = ssl3_FlushHandshake(ss, 0);
-    if (rv != SECSuccess) {
-        return rv; /* error code set by ssl3_FlushHandshake */
-    }
-    ss->ssl3.hs.ws = wait_client_hello;
-    return SECSuccess;
-}
-
-/*
- * Called from:
- *  ssl3_HandleClientHello()
- */
-static SECComparison
-ssl3_ServerNameCompare(const SECItem *name1, const SECItem *name2)
-{
-    if (!name1 != !name2) {
-        return SECLessThan;
-    }
-    if (!name1) {
-        return SECEqual;
-    }
-    if (name1->type != name2->type) {
-        return SECLessThan;
-    }
-    return SECITEM_CompareItem(name1, name2);
-}
-
-/* Sets memory error when returning NULL.
- * Called from:
- *  ssl3_SendClientHello()
- *  ssl3_HandleServerHello()
- *  ssl3_HandleClientHello()
- *  ssl3_HandleV2ClientHello()
- */
-sslSessionID *
-ssl3_NewSessionID(sslSocket *ss, PRBool is_server)
-{
-    sslSessionID *sid;
-
-    sid = PORT_ZNew(sslSessionID);
-    if (sid == NULL)
-        return sid;
-
-    if (is_server) {
-        const SECItem *srvName;
-        SECStatus rv = SECSuccess;
-
-        ssl_GetSpecReadLock(ss); /********************************/
-        srvName = &ss->ssl3.prSpec->srvVirtName;
-        if (srvName->len && srvName->data) {
-            rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.srvName, srvName);
-        }
-        ssl_ReleaseSpecReadLock(ss); /************************************/
-        if (rv != SECSuccess) {
-            PORT_Free(sid);
-            return NULL;
-        }
-    }
-    sid->peerID = (ss->peerID == NULL) ? NULL : PORT_Strdup(ss->peerID);
-    sid->urlSvrName = (ss->url == NULL) ? NULL : PORT_Strdup(ss->url);
-    sid->addr = ss->sec.ci.peer;
-    sid->port = ss->sec.ci.port;
-    sid->references = 1;
-    sid->cached = never_cached;
-    sid->version = ss->version;
-
-    sid->u.ssl3.keys.resumable = PR_TRUE;
-    sid->u.ssl3.policy = SSL_ALLOWED;
-    sid->u.ssl3.clientWriteKey = NULL;
-    sid->u.ssl3.serverWriteKey = NULL;
-    sid->u.ssl3.keys.extendedMasterSecretUsed = PR_FALSE;
-
-    if (is_server) {
-        SECStatus rv;
-        int pid = SSL_GETPID();
-
-        sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES;
-        sid->u.ssl3.sessionID[0] = (pid >> 8) & 0xff;
-        sid->u.ssl3.sessionID[1] = pid & 0xff;
-        rv = PK11_GenerateRandom(sid->u.ssl3.sessionID + 2,
-                                 SSL3_SESSIONID_BYTES - 2);
-        if (rv != SECSuccess) {
-            ssl_FreeSID(sid);
-            ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE);
-            return NULL;
-        }
-    }
-    return sid;
-}
-
-/* Called from:  ssl3_HandleClientHello, ssl3_HandleV2ClientHello */
-static SECStatus
-ssl3_SendServerHelloSequence(sslSocket *ss)
-{
-    const ssl3KEADef *kea_def;
-    SECStatus rv;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: begin send server_hello sequence",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    rv = ssl3_SendServerHello(ss);
-    if (rv != SECSuccess) {
-        return rv; /* err code is set. */
-    }
-    rv = ssl3_SendCertificate(ss);
-    if (rv != SECSuccess) {
-        return rv; /* error code is set. */
-    }
-    rv = ssl3_SendCertificateStatus(ss);
-    if (rv != SECSuccess) {
-        return rv; /* error code is set. */
-    }
-    /* We have to do this after the call to ssl3_SendServerHello,
-     * because kea_def is set up by ssl3_SendServerHello().
-     */
-    kea_def = ss->ssl3.hs.kea_def;
-    ss->ssl3.hs.usedStepDownKey = PR_FALSE;
-
-    if (kea_def->is_limited && kea_def->exchKeyType == kt_rsa) {
-        /* see if we can legally use the key in the cert. */
-        unsigned int keyLen; /* bytes */
-
-        keyLen = PK11_GetPrivateModulusLen(
-            ss->serverCerts[kea_def->exchKeyType].SERVERKEY);
-
-        if (keyLen > 0 &&
-            keyLen * BPB <= kea_def->key_size_limit) {
-            /* XXX AND cert is not signing only!! */
-            /* just fall through and use it. */
-        } else if (ss->stepDownKeyPair != NULL) {
-            ss->ssl3.hs.usedStepDownKey = PR_TRUE;
-            rv = ssl3_SendServerKeyExchange(ss);
-            if (rv != SECSuccess) {
-                return rv; /* err code was set. */
-            }
-        } else {
-#ifndef HACKED_EXPORT_SERVER
-            PORT_SetError(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED);
-            return rv;
-#endif
-        }
-    } else if (kea_def->ephemeral) {
-        rv = ssl3_SendServerKeyExchange(ss);
-        if (rv != SECSuccess) {
-            return rv; /* err code was set. */
-        }
-    }
-
-    if (ss->opt.requestCertificate) {
-        rv = ssl3_SendCertificateRequest(ss);
-        if (rv != SECSuccess) {
-            return rv; /* err code is set. */
-        }
-    }
-    rv = ssl3_SendServerHelloDone(ss);
-    if (rv != SECSuccess) {
-        return rv; /* err code is set. */
-    }
-
-    ss->ssl3.hs.ws = (ss->opt.requestCertificate) ? wait_client_cert
-                                                  : wait_client_key;
-    return SECSuccess;
-}
-
-/* An empty TLS Renegotiation Info (RI) extension */
-static const PRUint8 emptyRIext[5] = { 0xff, 0x01, 0x00, 0x01, 0x00 };
-
-static PRBool
-ssl3_KEAAllowsSessionTicket(SSL3KeyExchangeAlgorithm kea)
-{
-    switch (kea) {
-        case kea_dhe_dss:
-        case kea_dhe_dss_export:
-        case kea_dh_dss_export:
-        case kea_dh_dss:
-            /* TODO: Fix session tickets for DSS. The server code rejects the
-             * session ticket received from the client. Bug 1174677 */
-            return PR_FALSE;
-        default:
-            return PR_TRUE;
-    };
-}
-
-static void
-ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid)
-{
-    PLArenaPool *arena;
-    ssl3CertNode *lastCert = NULL;
-    ssl3CertNode *certs = NULL;
-    int i;
-
-    if (!sid->peerCertChain[0])
-        return;
-    PORT_Assert(!ss->ssl3.peerCertArena);
-    PORT_Assert(!ss->ssl3.peerCertChain);
-    ss->ssl3.peerCertArena = arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-    for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) {
-        ssl3CertNode *c = PORT_ArenaNew(arena, ssl3CertNode);
-        c->cert = CERT_DupCertificate(sid->peerCertChain[i]);
-        c->next = NULL;
-        if (lastCert) {
-            lastCert->next = c;
-        } else {
-            certs = c;
-        }
-        lastCert = c;
-    }
-    ss->ssl3.peerCertChain = certs;
-}
-
-static void
-ssl3_CopyPeerCertsToSID(ssl3CertNode *certs, sslSessionID *sid)
-{
-    int i = 0;
-    ssl3CertNode *c = certs;
-    for (; i < MAX_PEER_CERT_CHAIN_SIZE && c; i++, c = c->next) {
-        PORT_Assert(!sid->peerCertChain[i]);
-        sid->peerCertChain[i] = CERT_DupCertificate(c->cert);
-    }
-}
-
-/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
- * ssl3 Client Hello message.
- * Caller must hold Handshake and RecvBuf locks.
- */
-static SECStatus
-ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    sslSessionID *sid = NULL;
-    PRInt32 tmp;
-    unsigned int i;
-    int j;
-    SECStatus rv;
-    int errCode = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO;
-    SSL3AlertDescription desc = illegal_parameter;
-    SSL3AlertLevel level = alert_fatal;
-    SSL3ProtocolVersion version;
-    SECItem sidBytes = { siBuffer, NULL, 0 };
-    SECItem cookieBytes = { siBuffer, NULL, 0 };
-    SECItem suites = { siBuffer, NULL, 0 };
-    SECItem comps = { siBuffer, NULL, 0 };
-    PRBool haveSpecWriteLock = PR_FALSE;
-    PRBool haveXmitBufLock = PR_FALSE;
-    PRBool canOfferSessionTicket = PR_FALSE;
-    PRBool isTLS13 = PR_FALSE;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: handle client_hello handshake",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->ssl3.initialized);
-    ss->ssl3.hs.preliminaryInfo = 0;
-
-    if (!ss->sec.isServer ||
-        (ss->ssl3.hs.ws != wait_client_hello &&
-         ss->ssl3.hs.ws != idle_handshake)) {
-        desc = unexpected_message;
-        errCode = SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO;
-        goto alert_loser;
-    }
-    if (ss->ssl3.hs.ws == idle_handshake) {
-        if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
-            desc = unexpected_message;
-            errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
-            goto alert_loser;
-        }
-        if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) {
-            desc = no_renegotiation;
-            level = alert_warning;
-            errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
-            goto alert_loser;
-        }
-    }
-
-    /* Get peer name of client */
-    rv = ssl_GetPeerInfo(ss);
-    if (rv != SECSuccess) {
-        return rv; /* error code is set. */
-    }
-
-    /* Clearing the handshake pointers so that ssl_Do1stHandshake won't
-     * call ssl2_HandleMessage.
-     *
-     * The issue here is that TLS ordinarily starts out in
-     * ssl2_HandleV3HandshakeRecord() because of the backward-compatibility
-     * code paths. That function zeroes these next pointers. But with DTLS,
-     * we don't even try to do the v2 ClientHello so we skip that function
-     * and need to reset these values here.
-     */
-    if (IS_DTLS(ss)) {
-        ss->nextHandshake = 0;
-        ss->securityHandshake = 0;
-    }
-
-    /* We might be starting session renegotiation in which case we should
-     * clear previous state.
-     */
-    PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData));
-    ss->statelessResume = PR_FALSE;
-
-    if (IS_DTLS(ss)) {
-        dtls_RehandshakeCleanup(ss);
-    }
-
-    tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
-    if (tmp < 0)
-        goto loser; /* malformed, alert already sent */
-
-    /* Translate the version */
-    if (IS_DTLS(ss)) {
-        ss->clientHelloVersion = version =
-            dtls_DTLSVersionToTLSVersion((SSL3ProtocolVersion)tmp);
-    } else {
-        ss->clientHelloVersion = version = (SSL3ProtocolVersion)tmp;
-    }
-
-    rv = ssl3_NegotiateVersion(ss, version, PR_TRUE);
-    if (rv != SECSuccess) {
-        desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version
-                                                   : handshake_failure;
-        errCode = SSL_ERROR_UNSUPPORTED_VERSION;
-        goto alert_loser;
-    }
-    isTLS13 = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3;
-    ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_version;
-
-    rv = ssl3_InitHandshakeHashes(ss);
-    if (rv != SECSuccess) {
-        desc = internal_error;
-        errCode = PORT_GetError();
-        goto alert_loser;
-    }
-
-    /* Generate the Server Random now so it is available
-     * when we process the ClientKeyShare in TLS 1.3 */
-    rv = ssl3_GetNewRandom(&ss->ssl3.hs.server_random);
-    if (rv != SECSuccess) {
-        errCode = SSL_ERROR_GENERATE_RANDOM_FAILURE;
-        goto loser;
-    }
-
-    /*
-     * [draft-ietf-tls-tls13-11 Section 6.3.1.1].
-     * TLS 1.3 server implementations which respond to a ClientHello with a
-     * client_version indicating TLS 1.2 or below MUST set the first eight
-     * bytes of their Random value to the bytes:
-     *
-     * 44 4F 57 4E 47 52 44 01
-     *
-     * TLS 1.2 server implementations which respond to a ClientHello with a
-     * client_version indicating TLS 1.1 or below SHOULD set the first eight
-     * bytes of their Random value to the bytes:
-     *
-     * 44 4F 57 4E 47 52 44 00
-     *
-     * TODO(ekr@rtfm.com): Note this change was not added in the SSLv2
-     * compat processing code since that will most likely be removed before
-     * we ship the final version of TLS 1.3.
-     */
-    if (ss->vrange.max > ss->version) {
-        switch (ss->vrange.max) {
-            case SSL_LIBRARY_VERSION_TLS_1_3:
-                PORT_Memcpy(ss->ssl3.hs.server_random.rand,
-                            tls13_downgrade_random,
-                            sizeof(tls13_downgrade_random));
-                break;
-            case SSL_LIBRARY_VERSION_TLS_1_2:
-                PORT_Memcpy(ss->ssl3.hs.server_random.rand,
-                            tls12_downgrade_random,
-                            sizeof(tls12_downgrade_random));
-                break;
-            default:
-                /* Do not change random. */
-                break;
-        }
-    }
-
-    /* grab the client random data. */
-    rv = ssl3_ConsumeHandshake(
-        ss, &ss->ssl3.hs.client_random, SSL3_RANDOM_LENGTH, &b, &length);
-    if (rv != SECSuccess) {
-        goto loser; /* malformed */
-    }
-
-    /* grab the client's SID, if present. */
-    rv = ssl3_ConsumeHandshakeVariable(ss, &sidBytes, 1, &b, &length);
-    if (rv != SECSuccess) {
-        goto loser; /* malformed */
-    }
-
-    /* grab the client's cookie, if present. */
-    if (IS_DTLS(ss)) {
-        rv = ssl3_ConsumeHandshakeVariable(ss, &cookieBytes, 1, &b, &length);
-        if (rv != SECSuccess) {
-            goto loser; /* malformed */
-        }
-    }
-
-    /* grab the list of cipher suites. */
-    rv = ssl3_ConsumeHandshakeVariable(ss, &suites, 2, &b, &length);
-    if (rv != SECSuccess) {
-        goto loser; /* malformed */
-    }
-
-    /* If the ClientHello version is less than our maximum version, check for a
-     * TLS_FALLBACK_SCSV and reject the connection if found. */
-    if (ss->vrange.max > ss->clientHelloVersion) {
-        for (i = 0; i + 1 < suites.len; i += 2) {
-            PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
-            if (suite_i != TLS_FALLBACK_SCSV)
-                continue;
-            desc = inappropriate_fallback;
-            errCode = SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT;
-            goto alert_loser;
-        }
-    }
-
-    /* grab the list of compression methods. */
-    rv = ssl3_ConsumeHandshakeVariable(ss, &comps, 1, &b, &length);
-    if (rv != SECSuccess) {
-        goto loser; /* malformed */
-    }
-
-    /* TLS 1.3 requires that compression be empty */
-    if (isTLS13) {
-        if (comps.len != 1 || comps.data[0] != ssl_compression_null) {
-            goto loser;
-        }
-    }
-    desc = handshake_failure;
-
-    /* Handle TLS hello extensions for SSL3 & TLS. We do not know if
-     * we are restarting a previous session until extensions have been
-     * parsed, since we might have received a SessionTicket extension.
-     * Note: we allow extensions even when negotiating SSL3 for the sake
-     * of interoperability (and backwards compatibility).
-     */
-
-    if (length) {
-        /* Get length of hello extensions */
-        PRInt32 extension_length;
-        extension_length = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
-        if (extension_length < 0) {
-            goto loser; /* alert already sent */
-        }
-        if (extension_length != length) {
-            ssl3_DecodeError(ss); /* send alert */
-            goto loser;
-        }
-        rv = ssl3_HandleHelloExtensions(ss, &b, &length, client_hello);
-        if (rv != SECSuccess) {
-            goto loser; /* malformed */
-        }
-    }
-    if (!ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
-        /* If we didn't receive an RI extension, look for the SCSV,
-         * and if found, treat it just like an empty RI extension
-         * by processing a local copy of an empty RI extension.
-         */
-        for (i = 0; i + 1 < suites.len; i += 2) {
-            PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
-            if (suite_i == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) {
-                SSL3Opaque *b2 = (SSL3Opaque *)emptyRIext;
-                PRUint32 L2 = sizeof emptyRIext;
-                (void)ssl3_HandleHelloExtensions(ss, &b2, &L2, client_hello);
-                break;
-            }
-        }
-    }
-    if (ss->firstHsDone &&
-        (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_REQUIRES_XTN ||
-         ss->opt.enableRenegotiation == SSL_RENEGOTIATE_TRANSITIONAL) &&
-        !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
-        desc = no_renegotiation;
-        level = alert_warning;
-        errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
-        goto alert_loser;
-    }
-    if ((ss->opt.requireSafeNegotiation ||
-         (ss->firstHsDone && ss->peerRequestedProtection)) &&
-        !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
-        desc = handshake_failure;
-        errCode = SSL_ERROR_UNSAFE_NEGOTIATION;
-        goto alert_loser;
-    }
-
-    /* We do stateful resumes only if either of the following
-     * conditions are satisfied: (1) the client does not support the
-     * session ticket extension, or (2) the client support the session
-     * ticket extension, but sent an empty ticket.
-     */
-    if (!ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) ||
-        ss->xtnData.emptySessionTicket) {
-        if (sidBytes.len > 0 && !ss->opt.noCache) {
-            SSL_TRC(7, ("%d: SSL3[%d]: server, lookup client session-id for 0x%08x%08x%08x%08x",
-                        SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0],
-                        ss->sec.ci.peer.pr_s6_addr32[1],
-                        ss->sec.ci.peer.pr_s6_addr32[2],
-                        ss->sec.ci.peer.pr_s6_addr32[3]));
-            if (ssl_sid_lookup) {
-                sid = (*ssl_sid_lookup)(&ss->sec.ci.peer, sidBytes.data,
-                                        sidBytes.len, ss->dbHandle);
-            } else {
-                errCode = SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED;
-                goto loser;
-            }
-        }
-    } else if (ss->statelessResume) {
-        /* Fill in the client's session ID if doing a stateless resume.
-         * (When doing stateless resumes, server echos client's SessionID.)
-         */
-        sid = ss->sec.ci.sid;
-        PORT_Assert(sid != NULL); /* Should have already been filled in.*/
-
-        if (sidBytes.len > 0 && sidBytes.len <= SSL3_SESSIONID_BYTES) {
-            sid->u.ssl3.sessionIDLength = sidBytes.len;
-            PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data,
-                        sidBytes.len);
-            sid->u.ssl3.sessionIDLength = sidBytes.len;
-        } else {
-            sid->u.ssl3.sessionIDLength = 0;
-        }
-        ss->sec.ci.sid = NULL;
-    }
-
-    /* We only send a session ticket extension if the client supports
-     * the extension and we are unable to do either a stateful or
-     * stateless resume.
-     *
-     * TODO: send a session ticket if performing a stateful
-     * resumption.  (As per RFC4507, a server may issue a session
-     * ticket while doing a (stateless or stateful) session resume,
-     * but OpenSSL-0.9.8g does not accept session tickets while
-     * resuming.)
-     */
-    if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) && sid == NULL) {
-        canOfferSessionTicket = PR_TRUE;
-    }
-
-    if (sid != NULL) {
-        /* We've found a session cache entry for this client.
-         * Now, if we're going to require a client-auth cert,
-         * and we don't already have this client's cert in the session cache,
-         * and this is the first handshake on this connection (not a redo),
-         * then drop this old cache entry and start a new session.
-         */
-        if ((sid->peerCert == NULL) && ss->opt.requestCertificate &&
-            ((ss->opt.requireCertificate == SSL_REQUIRE_ALWAYS) ||
-             (ss->opt.requireCertificate == SSL_REQUIRE_NO_ERROR) ||
-             ((ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE) &&
-              !ss->firstHsDone))) {
-
-            SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_not_ok);
-            if (ss->sec.uncache)
-                ss->sec.uncache(sid);
-            ssl_FreeSID(sid);
-            sid = NULL;
-        }
-    }
-
-#ifndef NSS_DISABLE_ECC
-    /* Disable any ECC cipher suites for which we have no cert. */
-    ssl3_FilterECCipherSuitesByServerCerts(ss);
-#endif
-
-    if (IS_DTLS(ss)) {
-        ssl3_DisableNonDTLSSuites(ss);
-    }
-
-#ifdef PARANOID
-    /* Look for a matching cipher suite. */
-    j = ssl3_config_match_init(ss);
-    if (j <= 0) {                  /* no ciphers are working/supported by PK11 */
-        errCode = PORT_GetError(); /* error code is already set. */
-        goto alert_loser;
-    }
-#endif
-
-    /* If we already have a session for this client, be sure to pick the
-    ** same cipher suite and compression method we picked before.
-    ** This is not a loop, despite appearances.
-    */
-    if (sid)
-        do {
-            ssl3CipherSuiteCfg *suite;
-#ifdef PARANOID
-            SSLVersionRange vrange = { ss->version, ss->version };
-#endif
-
-            /* Check that the cached compression method is still enabled. */
-            if (!compressionEnabled(ss, sid->u.ssl3.compression))
-                break;
-
-            /* Check that the cached compression method is in the client's list */
-            for (i = 0; i < comps.len; i++) {
-                if (comps.data[i] == sid->u.ssl3.compression)
-                    break;
-            }
-            if (i == comps.len)
-                break;
-
-            suite = ss->cipherSuites;
-            /* Find the entry for the cipher suite used in the cached session. */
-            for (j = ssl_V3_SUITES_IMPLEMENTED; j > 0; --j, ++suite) {
-                if (suite->cipher_suite == sid->u.ssl3.cipherSuite)
-                    break;
-            }
-            PORT_Assert(j > 0);
-            if (j <= 0)
-                break;
-#ifdef PARANOID
-            /* Double check that the cached cipher suite is still enabled,
-             * implemented, and allowed by policy.  Might have been disabled.
-             * The product policy won't change during the process lifetime.
-             * Implemented ("isPresent") shouldn't change for servers.
-             */
-            if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange, ss))
-                break;
-#else
-            if (!suite->enabled)
-                break;
-#endif
-            /* Double check that the cached cipher suite is in the client's list */
-            for (i = 0; i + 1 < suites.len; i += 2) {
-                PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
-                if (suite_i == suite->cipher_suite) {
-                    ss->ssl3.hs.cipher_suite =
-                        suite->cipher_suite;
-                    ss->ssl3.hs.suite_def =
-                        ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
-                    ss->ssl3.hs.kea_def =
-                        &kea_defs[ss->ssl3.hs.suite_def->key_exchange_alg];
-                    ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_cipher_suite;
-
-                    /* Use the cached compression method. */
-                    ss->ssl3.hs.compression =
-                        sid->u.ssl3.compression;
-                    goto compression_found;
-                }
-            }
-        } while (0);
-
-/* START A NEW SESSION */
-
-#ifndef PARANOID
-    /* Look for a matching cipher suite. */
-    j = ssl3_config_match_init(ss);
-    if (j <= 0) {                  /* no ciphers are working/supported by PK11 */
-        errCode = PORT_GetError(); /* error code is already set. */
-        goto alert_loser;
-    }
-#endif
-
-    /* Select a cipher suite.
-    **
-    ** NOTE: This suite selection algorithm should be the same as the one in
-    ** ssl3_HandleV2ClientHello().
-    **
-    ** If TLS 1.0 is enabled, we could handle the case where the client
-    ** offered TLS 1.1 but offered only export cipher suites by choosing TLS
-    ** 1.0 and selecting one of those export cipher suites. However, a secure
-    ** TLS 1.1 client should not have export cipher suites enabled at all,
-    ** and a TLS 1.1 client should definitely not be offering *only* export
-    ** cipher suites. Therefore, we refuse to negotiate export cipher suites
-    ** with any client that indicates support for TLS 1.1 or higher when we
-    ** (the server) have TLS 1.1 support enabled.
-    */
-    for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
-        ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
-        SSLVersionRange vrange = { ss->version, ss->version };
-        if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange, ss)) {
-            continue;
-        }
-        for (i = 0; i + 1 < suites.len; i += 2) {
-            PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
-            if (suite_i == suite->cipher_suite) {
-                ss->ssl3.hs.cipher_suite = suite->cipher_suite;
-                ss->ssl3.hs.suite_def =
-                    ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
-                ss->ssl3.hs.kea_def =
-                    &kea_defs[ss->ssl3.hs.suite_def->key_exchange_alg];
-                ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_cipher_suite;
-                goto suite_found;
-            }
-        }
-    }
-    errCode = SSL_ERROR_NO_CYPHER_OVERLAP;
-    goto alert_loser;
-
-suite_found:
-    if (canOfferSessionTicket)
-        canOfferSessionTicket = ssl3_KEAAllowsSessionTicket(
-            ss->ssl3.hs.suite_def->key_exchange_alg);
-
-    if (canOfferSessionTicket) {
-        ssl3_RegisterServerHelloExtensionSender(ss,
-                                                ssl_session_ticket_xtn, ssl3_SendSessionTicketXtn);
-    }
-
-    /* Select a compression algorithm. */
-    for (i = 0; i < comps.len; i++) {
-        if (!compressionEnabled(ss, comps.data[i]))
-            continue;
-        for (j = 0; j < compressionMethodsCount; j++) {
-            if (comps.data[i] == compressions[j]) {
-                ss->ssl3.hs.compression =
-                    (SSLCompressionMethod)compressions[j];
-                goto compression_found;
-            }
-        }
-    }
-    errCode = SSL_ERROR_NO_COMPRESSION_OVERLAP;
-    /* null compression must be supported */
-    goto alert_loser;
-
-compression_found:
-    suites.data = NULL;
-    comps.data = NULL;
-
-    ss->sec.send = ssl3_SendApplicationData;
-
-    /* If there are any failures while processing the old sid,
-     * we don't consider them to be errors.  Instead, We just behave
-     * as if the client had sent us no sid to begin with, and make a new one.
-     * The exception here is attempts to resume extended_master_secret
-     * sessions without the extension, which causes an alert.
-     */
-    if (sid != NULL)
-        do {
-            ssl3CipherSpec *pwSpec;
-            SECItem wrappedMS; /* wrapped key */
-
-            if (sid->version != ss->version ||
-                sid->u.ssl3.cipherSuite != ss->ssl3.hs.cipher_suite ||
-                sid->u.ssl3.compression != ss->ssl3.hs.compression) {
-                break; /* not an error */
-            }
-
-            /* [draft-ietf-tls-session-hash-06; Section 5.3]
-             * o  If the original session did not use the "extended_master_secret"
-             *    extension but the new ClientHello contains the extension, then the
-             *    server MUST NOT perform the abbreviated handshake.  Instead, it
-             *    SHOULD continue with a full handshake (as described in
-             *    Section 5.2) to negotiate a new session.
-             *
-             * o  If the original session used the "extended_master_secret"
-             *    extension but the new ClientHello does not contain the extension,
-             *    the server MUST abort the abbreviated handshake.
-             */
-            if (ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) {
-                if (!sid->u.ssl3.keys.extendedMasterSecretUsed) {
-                    break; /* not an error */
-                }
-            } else {
-                if (sid->u.ssl3.keys.extendedMasterSecretUsed) {
-                    /* Note: we do not destroy the session */
-                    desc = handshake_failure;
-                    errCode = SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET;
-                    goto alert_loser;
-                }
-            }
-
-            if (ss->sec.ci.sid) {
-                if (ss->sec.uncache)
-                    ss->sec.uncache(ss->sec.ci.sid);
-                PORT_Assert(ss->sec.ci.sid != sid); /* should be impossible, but ... */
-                if (ss->sec.ci.sid != sid) {
-                    ssl_FreeSID(ss->sec.ci.sid);
-                }
-                ss->sec.ci.sid = NULL;
-            }
-            /* we need to resurrect the master secret.... */
-
-            ssl_GetSpecWriteLock(ss);
-            haveSpecWriteLock = PR_TRUE;
-            pwSpec = ss->ssl3.pwSpec;
-            if (sid->u.ssl3.keys.msIsWrapped) {
-                PK11SymKey *wrapKey; /* wrapping key */
-                CK_FLAGS keyFlags = 0;
-#ifndef NO_PKCS11_BYPASS
-                if (ss->opt.bypassPKCS11) {
-                    /* we cannot restart a non-bypass session in a
-                    ** bypass socket.
-                    */
-                    break;
-                }
-#endif
-
-                wrapKey = getWrappingKey(ss, NULL, sid->u.ssl3.exchKeyType,
-                                         sid->u.ssl3.masterWrapMech,
-                                         ss->pkcs11PinArg);
-                if (!wrapKey) {
-                    /* we have a SID cache entry, but no wrapping key for it??? */
-                    break;
-                }
-
-                if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */
-                    keyFlags =
-                        CKF_SIGN | CKF_VERIFY;
-                }
-
-                wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
-                wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
-
-                /* unwrap the master secret. */
-                pwSpec->master_secret =
-                    PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech,
-                                               NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE,
-                                               CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags);
-                PK11_FreeSymKey(wrapKey);
-                if (pwSpec->master_secret == NULL) {
-                    break; /* not an error */
-                }
-#ifndef NO_PKCS11_BYPASS
-            } else if (ss->opt.bypassPKCS11) {
-                wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
-                wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
-                memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len);
-                pwSpec->msItem.data = pwSpec->raw_master_secret;
-                pwSpec->msItem.len = wrappedMS.len;
-#endif
-            } else {
-                /* We CAN restart a bypass session in a non-bypass socket. */
-                /* need to import the raw master secret to session object */
-                PK11SlotInfo *slot;
-                wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
-                wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
-                slot = PK11_GetInternalSlot();
-                pwSpec->master_secret =
-                    PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE,
-                                      PK11_OriginUnwrap, CKA_ENCRYPT, &wrappedMS,
-                                      NULL);
-                PK11_FreeSlot(slot);
-                if (pwSpec->master_secret == NULL) {
-                    break; /* not an error */
-                }
-            }
-            ss->sec.ci.sid = sid;
-            if (sid->peerCert != NULL) {
-                ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
-                ssl3_CopyPeerCertsFromSID(ss, sid);
-            }
-
-            /*
-             * Old SID passed all tests, so resume this old session.
-             *
-             * XXX make sure compression still matches
-             */
-            SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_hits);
-            if (ss->statelessResume)
-                SSL_AtomicIncrementLong(&ssl3stats.hch_sid_stateless_resumes);
-            ss->ssl3.hs.isResuming = PR_TRUE;
-
-            ss->sec.authAlgorithm = sid->authAlgorithm;
-            ss->sec.authKeyBits = sid->authKeyBits;
-            ss->sec.keaType = sid->keaType;
-            ss->sec.keaKeyBits = sid->keaKeyBits;
-
-            /* server sids don't remember the server cert we previously sent,
-            ** but they do remember the kea type we originally used, so we
-            ** can locate it again, provided that the current ssl socket
-            ** has had its server certs configured the same as the previous one.
-            */
-            ss->sec.localCert =
-                CERT_DupCertificate(ss->serverCerts[sid->keaType].serverCert);
-
-            /* Copy cached name in to pending spec */
-            if (sid != NULL &&
-                sid->version > SSL_LIBRARY_VERSION_3_0 &&
-                sid->u.ssl3.srvName.len && sid->u.ssl3.srvName.data) {
-                /* Set server name from sid */
-                SECItem *sidName = &sid->u.ssl3.srvName;
-                SECItem *pwsName = &ss->ssl3.pwSpec->srvVirtName;
-                if (pwsName->data) {
-                    SECITEM_FreeItem(pwsName, PR_FALSE);
-                }
-                rv = SECITEM_CopyItem(NULL, pwsName, sidName);
-                if (rv != SECSuccess) {
-                    errCode = PORT_GetError();
-                    desc = internal_error;
-                    goto alert_loser;
-                }
-            }
-
-            /* Clean up sni name array */
-            if (ssl3_ExtensionNegotiated(ss, ssl_server_name_xtn) &&
-                ss->xtnData.sniNameArr) {
-                PORT_Free(ss->xtnData.sniNameArr);
-                ss->xtnData.sniNameArr = NULL;
-                ss->xtnData.sniNameArrSize = 0;
-            }
-
-            ssl_GetXmitBufLock(ss);
-            haveXmitBufLock = PR_TRUE;
-
-            rv = ssl3_SendServerHello(ss);
-            if (rv != SECSuccess) {
-                errCode = PORT_GetError();
-                goto loser;
-            }
-
-            if (haveSpecWriteLock) {
-                ssl_ReleaseSpecWriteLock(ss);
-                haveSpecWriteLock = PR_FALSE;
-            }
-
-            /* NULL value for PMS because we are re-using the old MS */
-            rv = ssl3_InitPendingCipherSpec(ss, NULL);
-            if (rv != SECSuccess) {
-                errCode = PORT_GetError();
-                goto loser;
-            }
-
-            rv = ssl3_SendChangeCipherSpecs(ss);
-            if (rv != SECSuccess) {
-                errCode = PORT_GetError();
-                goto loser;
-            }
-            rv = ssl3_SendFinished(ss, 0);
-            ss->ssl3.hs.ws = wait_change_cipher;
-            if (rv != SECSuccess) {
-                errCode = PORT_GetError();
-                goto loser;
-            }
-
-            if (haveXmitBufLock) {
-                ssl_ReleaseXmitBufLock(ss);
-                haveXmitBufLock = PR_FALSE;
-            }
-
-            return SECSuccess;
-        } while (0);
-
-    if (haveSpecWriteLock) {
-        ssl_ReleaseSpecWriteLock(ss);
-        haveSpecWriteLock = PR_FALSE;
-    }
-
-    if (sid) { /* we had a sid, but it's no longer valid, free it */
-        SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_not_ok);
-        if (ss->sec.uncache)
-            ss->sec.uncache(sid);
-        ssl_FreeSID(sid);
-        sid = NULL;
-    }
-    SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_misses);
-
-    if (ssl3_ExtensionNegotiated(ss, ssl_server_name_xtn)) {
-        int ret = 0;
-        if (ss->sniSocketConfig)
-            do { /* not a loop */
-                PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
-                            ssl_preinfo_all);
-
-                ret = SSL_SNI_SEND_ALERT;
-                /* If extension is negotiated, the len of names should > 0. */
-                if (ss->xtnData.sniNameArrSize) {
-                    /* Calling client callback to reconfigure the socket. */
-                    ret = (SECStatus)(*ss->sniSocketConfig)(ss->fd,
-                                                            ss->xtnData.sniNameArr,
-                                                            ss->xtnData.sniNameArrSize,
-                                                            ss->sniSocketConfigArg);
-                }
-                if (ret <= SSL_SNI_SEND_ALERT) {
-                    /* Application does not know the name or was not able to
-                     * properly reconfigure the socket. */
-                    errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
-                    desc = unrecognized_name;
-                    break;
-                } else if (ret == SSL_SNI_CURRENT_CONFIG_IS_USED) {
-                    SECStatus rv = SECSuccess;
-                    SECItem *cwsName, *pwsName;
-
-                    ssl_GetSpecWriteLock(ss); /*******************************/
-                    pwsName = &ss->ssl3.pwSpec->srvVirtName;
-                    cwsName = &ss->ssl3.cwSpec->srvVirtName;
-#ifndef SSL_SNI_ALLOW_NAME_CHANGE_2HS
-                    /* not allow name change on the 2d HS */
-                    if (ss->firstHsDone) {
-                        if (ssl3_ServerNameCompare(pwsName, cwsName)) {
-                            ssl_ReleaseSpecWriteLock(ss); /******************/
-                            errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
-                            desc = handshake_failure;
-                            ret = SSL_SNI_SEND_ALERT;
-                            break;
-                        }
-                    }
-#endif
-                    if (pwsName->data) {
-                        SECITEM_FreeItem(pwsName, PR_FALSE);
-                    }
-                    if (cwsName->data) {
-                        rv = SECITEM_CopyItem(NULL, pwsName, cwsName);
-                    }
-                    ssl_ReleaseSpecWriteLock(ss); /**************************/
-                    if (rv != SECSuccess) {
-                        errCode = SSL_ERROR_INTERNAL_ERROR_ALERT;
-                        desc = internal_error;
-                        ret = SSL_SNI_SEND_ALERT;
-                        break;
-                    }
-                } else if ((unsigned int)ret < ss->xtnData.sniNameArrSize) {
-                    /* Application has configured new socket info. Lets check it
-                     * and save the name. */
-                    SECStatus rv;
-                    SECItem *name = &ss->xtnData.sniNameArr[ret];
-                    int configedCiphers;
-                    SECItem *pwsName;
-
-                    /* get rid of the old name and save the newly picked. */
-                    /* This code is protected by ssl3HandshakeLock. */
-                    ssl_GetSpecWriteLock(ss); /*******************************/
-#ifndef SSL_SNI_ALLOW_NAME_CHANGE_2HS
-                    /* not allow name change on the 2d HS */
-                    if (ss->firstHsDone) {
-                        SECItem *cwsName = &ss->ssl3.cwSpec->srvVirtName;
-                        if (ssl3_ServerNameCompare(name, cwsName)) {
-                            ssl_ReleaseSpecWriteLock(ss); /******************/
-                            errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
-                            desc = handshake_failure;
-                            ret = SSL_SNI_SEND_ALERT;
-                            break;
-                        }
-                    }
-#endif
-                    pwsName = &ss->ssl3.pwSpec->srvVirtName;
-                    if (pwsName->data) {
-                        SECITEM_FreeItem(pwsName, PR_FALSE);
-                    }
-                    rv = SECITEM_CopyItem(NULL, pwsName, name);
-                    ssl_ReleaseSpecWriteLock(ss); /***************************/
-                    if (rv != SECSuccess) {
-                        errCode = SSL_ERROR_INTERNAL_ERROR_ALERT;
-                        desc = internal_error;
-                        ret = SSL_SNI_SEND_ALERT;
-                        break;
-                    }
-                    configedCiphers = ssl3_config_match_init(ss);
-                    if (configedCiphers <= 0) {
-                        /* no ciphers are working/supported */
-                        errCode = PORT_GetError();
-                        desc = handshake_failure;
-                        ret = SSL_SNI_SEND_ALERT;
-                        break;
-                    }
-                    /* Need to tell the client that application has picked
-                     * the name from the offered list and reconfigured the socket.
-                     */
-                    ssl3_RegisterServerHelloExtensionSender(ss, ssl_server_name_xtn,
-                                                            ssl3_SendServerNameXtn);
-                } else {
-                    /* Callback returned index outside of the boundary. */
-                    PORT_Assert((unsigned int)ret < ss->xtnData.sniNameArrSize);
-                    errCode = SSL_ERROR_INTERNAL_ERROR_ALERT;
-                    desc = internal_error;
-                    ret = SSL_SNI_SEND_ALERT;
-                    break;
-                }
-            } while (0);
-        /* Free sniNameArr. The data that each SECItem in the array
-         * points into is the data from the input buffer "b". It will
-         * not be available outside the scope of this or it's child
-         * functions.*/
-        if (ss->xtnData.sniNameArr) {
-            PORT_Free(ss->xtnData.sniNameArr);
-            ss->xtnData.sniNameArr = NULL;
-            ss->xtnData.sniNameArrSize = 0;
-        }
-        if (ret <= SSL_SNI_SEND_ALERT) {
-            /* desc and errCode should be set. */
-            goto alert_loser;
-        }
-    }
-#ifndef SSL_SNI_ALLOW_NAME_CHANGE_2HS
-    else if (ss->firstHsDone) {
-        /* Check that we don't have the name is current spec
-         * if this extension was not negotiated on the 2d hs. */
-        PRBool passed = PR_TRUE;
-        ssl_GetSpecReadLock(ss); /*******************************/
-        if (ss->ssl3.cwSpec->srvVirtName.data) {
-            passed = PR_FALSE;
-        }
-        ssl_ReleaseSpecReadLock(ss); /***************************/
-        if (!passed) {
-            errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
-            desc = handshake_failure;
-            goto alert_loser;
-        }
-    }
-#endif
-
-    /* If this is TLS 1.3 we are expecting a ClientKeyShare
-     * extension. Missing/absent extension cause failure
-     * below. */
-    if (isTLS13) {
-        rv = tls13_HandleClientKeyShare(ss);
-        if (rv != SECSuccess) {
-            errCode = PORT_GetError();
-            goto alert_loser;
-        }
-    }
-
-    sid = ssl3_NewSessionID(ss, PR_TRUE);
-    if (sid == NULL) {
-        errCode = PORT_GetError();
-        goto loser; /* memory error is set. */
-    }
-    ss->sec.ci.sid = sid;
-
-    sid->u.ssl3.keys.extendedMasterSecretUsed =
-        ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn);
-    ss->ssl3.hs.isResuming = PR_FALSE;
-
-    ssl_GetXmitBufLock(ss);
-    if (isTLS13) {
-        rv = tls13_SendServerHelloSequence(ss);
-    } else {
-        rv = ssl3_SendServerHelloSequence(ss);
-    }
-    ssl_ReleaseXmitBufLock(ss);
-    if (rv != SECSuccess) {
-        errCode = PORT_GetError();
-        desc = handshake_failure;
-        goto alert_loser;
-    }
-
-    if (haveXmitBufLock) {
-        ssl_ReleaseXmitBufLock(ss);
-        haveXmitBufLock = PR_FALSE;
-    }
-
-    return SECSuccess;
-
-alert_loser:
-    if (haveSpecWriteLock) {
-        ssl_ReleaseSpecWriteLock(ss);
-        haveSpecWriteLock = PR_FALSE;
-    }
-    (void)SSL3_SendAlert(ss, level, desc);
-/* FALLTHRU */
-loser:
-    if (haveSpecWriteLock) {
-        ssl_ReleaseSpecWriteLock(ss);
-        haveSpecWriteLock = PR_FALSE;
-    }
-
-    if (haveXmitBufLock) {
-        ssl_ReleaseXmitBufLock(ss);
-        haveXmitBufLock = PR_FALSE;
-    }
-
-    PORT_SetError(errCode);
-    return SECFailure;
-}
-
-/*
- * ssl3_HandleV2ClientHello is used when a V2 formatted hello comes
- * in asking to use the V3 handshake.
- * Called from ssl2_HandleClientHelloMessage() in sslcon.c
- */
-SECStatus
-ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length)
-{
-    sslSessionID *sid = NULL;
-    unsigned char *suites;
-    unsigned char *random;
-    SSL3ProtocolVersion version;
-    SECStatus rv;
-    int i;
-    int j;
-    int sid_length;
-    int suite_length;
-    int rand_length;
-    int errCode = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO;
-    SSL3AlertDescription desc = handshake_failure;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: handle v2 client_hello", SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-
-    ssl_GetSSL3HandshakeLock(ss);
-
-    PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData));
-
-    rv = ssl3_InitState(ss);
-    if (rv != SECSuccess) {
-        ssl_ReleaseSSL3HandshakeLock(ss);
-        return rv; /* ssl3_InitState has set the error code. */
-    }
-    rv = ssl3_RestartHandshakeHashes(ss);
-    if (rv != SECSuccess) {
-        ssl_ReleaseSSL3HandshakeLock(ss);
-        return rv;
-    }
-
-    if (ss->ssl3.hs.ws != wait_client_hello) {
-        desc = unexpected_message;
-        errCode = SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO;
-        goto loser; /* alert_loser */
-    }
-
-    version = (buffer[1] << 8) | buffer[2];
-    suite_length = (buffer[3] << 8) | buffer[4];
-    sid_length = (buffer[5] << 8) | buffer[6];
-    rand_length = (buffer[7] << 8) | buffer[8];
-    ss->clientHelloVersion = version;
-
-    if (version >= SSL_LIBRARY_VERSION_TLS_1_3) {
-        /* [draft-ietf-tls-tls-11; C.3] forbids sending a TLS 1.3
-         * ClientHello using the backwards-compatible format. */
-        desc = illegal_parameter;
-        errCode = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO;
-        goto loser;
-    }
-
-    rv = ssl3_NegotiateVersion(ss, version, PR_TRUE);
-    if (rv != SECSuccess) {
-        /* send back which ever alert client will understand. */
-        desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version
-                                                   : handshake_failure;
-        errCode = SSL_ERROR_UNSUPPORTED_VERSION;
-        goto alert_loser;
-    }
-    ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_version;
-
-    rv = ssl3_InitHandshakeHashes(ss);
-    if (rv != SECSuccess) {
-        desc = internal_error;
-        errCode = PORT_GetError();
-        goto alert_loser;
-    }
-
-    /* if we get a non-zero SID, just ignore it. */
-    if (length !=
-        SSL_HL_CLIENT_HELLO_HBYTES + suite_length + sid_length + rand_length) {
-        SSL_DBG(("%d: SSL3[%d]: bad v2 client hello message, len=%d should=%d",
-                 SSL_GETPID(), ss->fd, length,
-                 SSL_HL_CLIENT_HELLO_HBYTES + suite_length + sid_length +
-                     rand_length));
-        goto loser; /* malformed */ /* alert_loser */
-    }
-
-    suites = buffer + SSL_HL_CLIENT_HELLO_HBYTES;
-    random = suites + suite_length + sid_length;
-
-    if (rand_length < SSL_MIN_CHALLENGE_BYTES ||
-        rand_length > SSL_MAX_CHALLENGE_BYTES) {
-        goto loser; /* malformed */ /* alert_loser */
-    }
-
-    PORT_Assert(SSL_MAX_CHALLENGE_BYTES == SSL3_RANDOM_LENGTH);
-
-    PORT_Memset(&ss->ssl3.hs.client_random, 0, SSL3_RANDOM_LENGTH);
-    PORT_Memcpy(
-        &ss->ssl3.hs.client_random.rand[SSL3_RANDOM_LENGTH - rand_length],
-        random, rand_length);
-
-    PRINT_BUF(60, (ss, "client random:", &ss->ssl3.hs.client_random.rand[0],
-                   SSL3_RANDOM_LENGTH));
-#ifndef NSS_DISABLE_ECC
-    /* Disable any ECC cipher suites for which we have no cert. */
-    ssl3_FilterECCipherSuitesByServerCerts(ss);
-#endif
-    i = ssl3_config_match_init(ss);
-    if (i <= 0) {
-        errCode = PORT_GetError(); /* error code is already set. */
-        goto alert_loser;
-    }
-
-    /* Select a cipher suite.
-    **
-    ** NOTE: This suite selection algorithm should be the same as the one in
-    ** ssl3_HandleClientHello().
-    **
-    ** See the comments about export cipher suites in ssl3_HandleClientHello().
-    */
-    for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
-        ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
-        SSLVersionRange vrange = { ss->version, ss->version };
-        if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange, ss)) {
-            continue;
-        }
-        for (i = 0; i + 2 < suite_length; i += 3) {
-            PRUint32 suite_i = (suites[i] << 16) | (suites[i + 1] << 8) | suites[i + 2];
-            if (suite_i == suite->cipher_suite) {
-                ss->ssl3.hs.cipher_suite = suite->cipher_suite;
-                ss->ssl3.hs.suite_def =
-                    ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
-                ss->ssl3.hs.kea_def =
-                    &kea_defs[ss->ssl3.hs.suite_def->key_exchange_alg];
-                ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_cipher_suite;
-                goto suite_found;
-            }
-        }
-    }
-    errCode = SSL_ERROR_NO_CYPHER_OVERLAP;
-    goto alert_loser;
-
-suite_found:
-
-    /* Look for the SCSV, and if found, treat it just like an empty RI
-     * extension by processing a local copy of an empty RI extension.
-     */
-    for (i = 0; i + 2 < suite_length; i += 3) {
-        PRUint32 suite_i = (suites[i] << 16) | (suites[i + 1] << 8) | suites[i + 2];
-        if (suite_i == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) {
-            SSL3Opaque *b2 = (SSL3Opaque *)emptyRIext;
-            PRUint32 L2 = sizeof emptyRIext;
-            (void)ssl3_HandleHelloExtensions(ss, &b2, &L2, client_hello);
-            break;
-        }
-    }
-
-    if (ss->opt.requireSafeNegotiation &&
-        !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
-        desc = handshake_failure;
-        errCode = SSL_ERROR_UNSAFE_NEGOTIATION;
-        goto alert_loser;
-    }
-
-    ss->ssl3.hs.compression = ssl_compression_null;
-    ss->sec.send = ssl3_SendApplicationData;
-
-    /* we don't even search for a cache hit here.  It's just a miss. */
-    SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_misses);
-    sid = ssl3_NewSessionID(ss, PR_TRUE);
-    if (sid == NULL) {
-        errCode = PORT_GetError();
-        goto loser; /* memory error is set. */
-    }
-    ss->sec.ci.sid = sid;
-    /* do not worry about memory leak of sid since it now belongs to ci */
-
-    /* We have to update the handshake hashes before we can send stuff */
-    rv = ssl3_UpdateHandshakeHashes(ss, buffer, length);
-    if (rv != SECSuccess) {
-        errCode = PORT_GetError();
-        goto loser;
-    }
-
-    ssl_GetXmitBufLock(ss);
-    rv = ssl3_SendServerHelloSequence(ss);
-    ssl_ReleaseXmitBufLock(ss);
-    if (rv != SECSuccess) {
-        errCode = PORT_GetError();
-        goto loser;
-    }
-
-    /* XXX_1    The call stack to here is:
-     * ssl_Do1stHandshake -> ssl2_HandleClientHelloMessage -> here.
-     * ssl2_HandleClientHelloMessage returns whatever we return here.
-     * ssl_Do1stHandshake will continue looping if it gets back either
-     *      SECSuccess or SECWouldBlock.
-     * SECSuccess is preferable here.  See XXX_1 in sslgathr.c.
-     */
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    return SECSuccess;
-
-alert_loser:
-    SSL3_SendAlert(ss, alert_fatal, desc);
-loser:
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    PORT_SetError(errCode);
-    return SECFailure;
-}
-
-/* The negotiated version number has been already placed in ss->version.
-**
-** Called from:  ssl3_HandleClientHello                     (resuming session),
-**  ssl3_SendServerHelloSequence <- ssl3_HandleClientHello   (new session),
-**  ssl3_SendServerHelloSequence <- ssl3_HandleV2ClientHello (new session)
-*/
-SECStatus
-ssl3_SendServerHello(sslSocket *ss)
-{
-    sslSessionID *sid;
-    SECStatus rv;
-    PRUint32 maxBytes = 65535;
-    PRUint32 length;
-    PRInt32 extensions_len = 0;
-    SSL3ProtocolVersion version;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: send server_hello handshake", SSL_GETPID(),
-                ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if (!IS_DTLS(ss)) {
-        PORT_Assert(MSB(ss->version) == MSB(SSL_LIBRARY_VERSION_3_0));
-
-        if (MSB(ss->version) != MSB(SSL_LIBRARY_VERSION_3_0)) {
-            PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
-            return SECFailure;
-        }
-    } else {
-        PORT_Assert(MSB(ss->version) == MSB(SSL_LIBRARY_VERSION_DTLS_1_0));
-
-        if (MSB(ss->version) != MSB(SSL_LIBRARY_VERSION_DTLS_1_0)) {
-            PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
-            return SECFailure;
-        }
-    }
-
-    sid = ss->sec.ci.sid;
-
-    extensions_len = ssl3_CallHelloExtensionSenders(
-        ss, PR_FALSE, maxBytes, &ss->xtnData.serverHelloSenders[0]);
-    if (extensions_len > 0)
-        extensions_len += 2; /* Add sizeof total extension length */
-
-    /* TLS 1.3 doesn't use the session_id or compression_method
-     * fields in the ServerHello. */
-    length = sizeof(SSL3ProtocolVersion) + SSL3_RANDOM_LENGTH;
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        length += 1 + ((sid == NULL) ? 0 : sid->u.ssl3.sessionIDLength);
-    }
-    length += sizeof(ssl3CipherSuite);
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        length += 1; /* Compression */
-    }
-    length += extensions_len;
-
-    rv = ssl3_AppendHandshakeHeader(ss, server_hello, length);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake. */
-    }
-
-    if (IS_DTLS(ss)) {
-        version = dtls_TLSVersionToDTLSVersion(ss->version);
-    } else {
-        version = ss->version;
-    }
-
-    rv = ssl3_AppendHandshakeNumber(ss, version, 2);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake. */
-    }
-    /* Random already generated in ssl3_HandleClientHello */
-    rv = ssl3_AppendHandshake(
-        ss, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake. */
-    }
-
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        if (sid) {
-            rv = ssl3_AppendHandshakeVariable(
-                ss, sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength, 1);
-        } else {
-            rv = ssl3_AppendHandshakeNumber(ss, 0, 1);
-        }
-        if (rv != SECSuccess) {
-            return rv; /* err set by AppendHandshake. */
-        }
-    }
-
-    rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.cipher_suite, 2);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake. */
-    }
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.compression, 1);
-        if (rv != SECSuccess) {
-            return rv; /* err set by AppendHandshake. */
-        }
-    }
-    if (extensions_len) {
-        PRInt32 sent_len;
-
-        extensions_len -= 2;
-        rv = ssl3_AppendHandshakeNumber(ss, extensions_len, 2);
-        if (rv != SECSuccess)
-            return rv; /* err set by ssl3_AppendHandshakeNumber */
-        sent_len = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, extensions_len,
-                                                  &ss->xtnData.serverHelloSenders[0]);
-        PORT_Assert(sent_len == extensions_len);
-        if (sent_len != extensions_len) {
-            if (sent_len >= 0)
-                PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            return SECFailure;
-        }
-    }
-    rv = ssl3_SetupPendingCipherSpec(ss);
-    if (rv != SECSuccess) {
-        return rv; /* err set by ssl3_SetupPendingCipherSpec */
-    }
-
-    return SECSuccess;
-}
-
-static SECStatus
-ssl3_PickSignatureHashAlgorithm(sslSocket *ss,
-                                SSLSignatureAndHashAlg *out);
-
-static SECStatus
-ssl3_SendDHServerKeyExchange(sslSocket *ss)
-{
-    const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
-    SECStatus rv = SECFailure;
-    int length;
-    PRBool isTLS;
-    SECItem signed_hash = { siBuffer, NULL, 0 };
-    SSL3Hashes hashes;
-    SSLSignatureAndHashAlg sigAndHash;
-    SECKEYDHParams dhParam;
-
-    ssl3KeyPair *keyPair = NULL;
-    SECKEYPublicKey *pubKey = NULL;   /* Ephemeral DH key */
-    SECKEYPrivateKey *privKey = NULL; /* Ephemeral DH key */
-    int certIndex = -1;
-
-    if (kea_def->kea != kea_dhe_dss && kea_def->kea != kea_dhe_rsa) {
-        /* TODO: Support DH_anon. It might be sufficient to drop the signature.
-                 See bug 1170510. */
-        PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-        return SECFailure;
-    }
-
-    dhParam.prime.data = ss->dheParams->prime.data;
-    dhParam.prime.len = ss->dheParams->prime.len;
-    dhParam.base.data = ss->dheParams->base.data;
-    dhParam.base.len = ss->dheParams->base.len;
-
-    PRINT_BUF(60, (NULL, "Server DH p", dhParam.prime.data,
-                   dhParam.prime.len));
-    PRINT_BUF(60, (NULL, "Server DH g", dhParam.base.data,
-                   dhParam.base.len));
-
-    /* Generate ephemeral DH keypair */
-    privKey = SECKEY_CreateDHPrivateKey(&dhParam, &pubKey, NULL);
-    if (!privKey || !pubKey) {
-        ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
-        rv = SECFailure;
-        goto loser;
-    }
-
-    keyPair = ssl3_NewKeyPair(privKey, pubKey);
-    if (!keyPair) {
-        ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
-        goto loser;
-    }
-
-    PRINT_BUF(50, (ss, "DH public value:",
-                   pubKey->u.dh.publicValue.data,
-                   pubKey->u.dh.publicValue.len));
-
-    if (ssl3_PickSignatureHashAlgorithm(ss, &sigAndHash) != SECSuccess) {
-        ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
-        goto loser;
-    }
-
-    rv = ssl3_ComputeDHKeyHash(sigAndHash.hashAlg,
-                               pubKey->u.dh.prime,
-                               pubKey->u.dh.base,
-                               pubKey->u.dh.publicValue,
-                               &ss->ssl3.hs.client_random,
-                               &ss->ssl3.hs.server_random,
-                               &hashes, ss->opt.bypassPKCS11);
-    if (rv != SECSuccess) {
-        ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-        goto loser;
-    }
-
-    /* It has been suggested to test kea_def->signKeyType instead, and to use
-     * ssl_auth_* instead. Investigate what to do. See bug 102794. */
-    if (kea_def->kea == kea_dhe_rsa)
-        certIndex = ssl_kea_rsa;
-    else
-        certIndex = ssl_kea_dh;
-
-    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
-    rv = ssl3_SignHashes(&hashes, ss->serverCerts[certIndex].SERVERKEY,
-                         &signed_hash, isTLS);
-    if (rv != SECSuccess) {
-        goto loser; /* ssl3_SignHashes has set err. */
-    }
-    if (signed_hash.data == NULL) {
-        PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-        goto loser;
-    }
-    length = 2 + pubKey->u.dh.prime.len +
-             2 + pubKey->u.dh.base.len +
-             2 + pubKey->u.dh.publicValue.len +
-             2 + signed_hash.len;
-
-    if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
-        length += 2;
-    }
-
-    rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
-    if (rv != SECSuccess) {
-        goto loser; /* err set by AppendHandshake. */
-    }
-
-    rv = ssl3_AppendHandshakeVariable(ss, pubKey->u.dh.prime.data,
-                                      pubKey->u.dh.prime.len, 2);
-    if (rv != SECSuccess) {
-        goto loser; /* err set by AppendHandshake. */
-    }
-
-    rv = ssl3_AppendHandshakeVariable(ss, pubKey->u.dh.base.data,
-                                      pubKey->u.dh.base.len, 2);
-    if (rv != SECSuccess) {
-        goto loser; /* err set by AppendHandshake. */
-    }
-
-    rv = ssl3_AppendHandshakeVariable(ss, pubKey->u.dh.publicValue.data,
-                                      pubKey->u.dh.publicValue.len, 2);
-    if (rv != SECSuccess) {
-        goto loser; /* err set by AppendHandshake. */
-    }
-
-    if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
-        rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash);
-        if (rv != SECSuccess) {
-            goto loser; /* err set by AppendHandshake. */
-        }
-    }
-
-    rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
-                                      signed_hash.len, 2);
-    if (rv != SECSuccess) {
-        goto loser; /* err set by AppendHandshake. */
-    }
-    PORT_Free(signed_hash.data);
-    ss->dheKeyPair = keyPair;
-    return SECSuccess;
-
-loser:
-    if (signed_hash.data)
-        PORT_Free(signed_hash.data);
-    if (privKey)
-        SECKEY_DestroyPrivateKey(privKey);
-    if (pubKey)
-        SECKEY_DestroyPublicKey(pubKey);
-    return SECFailure;
-}
-
-/* ssl3_PickSignatureHashAlgorithm selects a hash algorithm to use when signing
- * elements of the handshake. (The negotiated cipher suite determines the
- * signature algorithm.) Prior to TLS 1.2, the MD5/SHA1 combination is always
- * used. With TLS 1.2, a client may advertise its support for signature and
- * hash combinations. */
-static SECStatus
-ssl3_PickSignatureHashAlgorithm(sslSocket *ss,
-                                SSLSignatureAndHashAlg *out)
-{
-    PRUint32 policy;
-    unsigned int i, j;
-
-    out->sigAlg = ss->ssl3.hs.kea_def->signKeyType;
-
-    if (ss->version <= SSL_LIBRARY_VERSION_TLS_1_1) {
-        /* SEC_OID_UNKNOWN means the MD5/SHA1 combo hash used in TLS 1.1 and
-         * prior. */
-        out->hashAlg = ssl_hash_none;
-        return SECSuccess;
-    }
-
-    if (ss->ssl3.hs.numClientSigAndHash == 0) {
-        /* If the client didn't provide any signature_algorithms extension then
-         * we can assume that they support SHA-1:
-         * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
-        out->hashAlg = ssl_hash_sha1;
-        return SECSuccess;
-    }
-
-    /* Here we look for the first server preference that the client has
-     * indicated support for in their signature_algorithms extension. */
-    for (i = 0; i < ss->ssl3.signatureAlgorithmCount; ++i) {
-        const SSLSignatureAndHashAlg *serverPref =
-            &ss->ssl3.signatureAlgorithms[i];
-        SECOidTag hashOID;
-        if (serverPref->sigAlg != out->sigAlg) {
-            continue;
-        }
-        hashOID = ssl3_TLSHashAlgorithmToOID(serverPref->hashAlg);
-        if ((NSS_GetAlgorithmPolicy(hashOID, &policy) == SECSuccess) &&
-            !(policy & NSS_USE_ALG_IN_SSL_KX)) {
-            /* we ignore hashes we don't support */
-            continue;
-        }
-        for (j = 0; j < ss->ssl3.hs.numClientSigAndHash; j++) {
-            const SSLSignatureAndHashAlg *clientPref =
-                &ss->ssl3.hs.clientSigAndHash[j];
-            if (clientPref->hashAlg == serverPref->hashAlg &&
-                clientPref->sigAlg == out->sigAlg) {
-                out->hashAlg = serverPref->hashAlg;
-                return SECSuccess;
-            }
-        }
-    }
-
-    PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
-    return SECFailure;
-}
-
-static SECStatus
-ssl3_SendServerKeyExchange(sslSocket *ss)
-{
-    const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
-    SECStatus rv = SECFailure;
-    int length;
-    PRBool isTLS;
-    SECItem signed_hash = { siBuffer, NULL, 0 };
-    SSL3Hashes hashes;
-    SECKEYPublicKey *sdPub; /* public key for step-down */
-    SSLSignatureAndHashAlg sigAndHash;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: send server_key_exchange handshake",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if (ssl3_PickSignatureHashAlgorithm(ss, &sigAndHash) != SECSuccess) {
-        return SECFailure;
-    }
-
-    switch (kea_def->exchKeyType) {
-        case kt_rsa:
-            /* Perform SSL Step-Down here. */
-            sdPub = ss->stepDownKeyPair->pubKey;
-            PORT_Assert(sdPub != NULL);
-            if (!sdPub) {
-                PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-                return SECFailure;
-            }
-            rv = ssl3_ComputeExportRSAKeyHash(sigAndHash.hashAlg,
-                                              sdPub->u.rsa.modulus,
-                                              sdPub->u.rsa.publicExponent,
-                                              &ss->ssl3.hs.client_random,
-                                              &ss->ssl3.hs.server_random,
-                                              &hashes, ss->opt.bypassPKCS11);
-            if (rv != SECSuccess) {
-                ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-                return rv;
-            }
-
-            isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
-            rv = ssl3_SignHashes(&hashes, ss->serverCerts[kt_rsa].SERVERKEY,
-                                 &signed_hash, isTLS);
-            if (rv != SECSuccess) {
-                goto loser; /* ssl3_SignHashes has set err. */
-            }
-            if (signed_hash.data == NULL) {
-                /* how can this happen and rv == SECSuccess ?? */
-                PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-                goto loser;
-            }
-            length = 2 + sdPub->u.rsa.modulus.len +
-                     2 + sdPub->u.rsa.publicExponent.len +
-                     2 + signed_hash.len;
-
-            if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
-                length += 2;
-            }
-
-            rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
-            if (rv != SECSuccess) {
-                goto loser; /* err set by AppendHandshake. */
-            }
-
-            rv = ssl3_AppendHandshakeVariable(ss, sdPub->u.rsa.modulus.data,
-                                              sdPub->u.rsa.modulus.len, 2);
-            if (rv != SECSuccess) {
-                goto loser; /* err set by AppendHandshake. */
-            }
-
-            rv = ssl3_AppendHandshakeVariable(
-                ss, sdPub->u.rsa.publicExponent.data,
-                sdPub->u.rsa.publicExponent.len, 2);
-            if (rv != SECSuccess) {
-                goto loser; /* err set by AppendHandshake. */
-            }
-
-            if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
-                rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash);
-                if (rv != SECSuccess) {
-                    goto loser; /* err set by AppendHandshake. */
-                }
-            }
-
-            rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
-                                              signed_hash.len, 2);
-            if (rv != SECSuccess) {
-                goto loser; /* err set by AppendHandshake. */
-            }
-            PORT_Free(signed_hash.data);
-            return SECSuccess;
-
-        case ssl_kea_dh: {
-            rv = ssl3_SendDHServerKeyExchange(ss);
-            return rv;
-        }
-
-#ifndef NSS_DISABLE_ECC
-        case kt_ecdh: {
-            rv = ssl3_SendECDHServerKeyExchange(ss, &sigAndHash);
-            return rv;
-        }
-#endif /* NSS_DISABLE_ECC */
-
-        case kt_null:
-        default:
-            PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
-            break;
-    }
-loser:
-    if (signed_hash.data != NULL)
-        PORT_Free(signed_hash.data);
-    return SECFailure;
-}
-
-SECStatus
-ssl3_EncodeCertificateRequestSigAlgs(sslSocket *ss, PRUint8 *buf,
-                                     unsigned maxLen, PRUint32 *len)
-{
-    unsigned int i;
-
-    PORT_Assert(maxLen >= ss->ssl3.signatureAlgorithmCount * 2);
-    if (maxLen < ss->ssl3.signatureAlgorithmCount * 2) {
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        return SECFailure;
-    }
-
-    *len = 0;
-    for (i = 0; i < ss->ssl3.signatureAlgorithmCount; ++i) {
-        const SSLSignatureAndHashAlg *alg = &ss->ssl3.signatureAlgorithms[i];
-        /* Note that we don't support a handshake hash with anything other than
-         * SHA-256, so asking for a signature from clients for something else
-         * would be inviting disaster. */
-        if (alg->hashAlg == ssl_hash_sha256) {
-            buf[(*len)++] = (PRUint8)alg->hashAlg;
-            buf[(*len)++] = (PRUint8)alg->sigAlg;
-        }
-    }
-
-    if (*len == 0) {
-        PORT_SetError(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM);
-        return SECFailure;
-    }
-    return SECSuccess;
-}
-
-void
-ssl3_GetCertificateRequestCAs(sslSocket *ss, int *calen, SECItem **names,
-                              int *nnames)
-{
-    SECItem *name;
-    CERTDistNames *ca_list;
-    int i;
-
-    *calen = 0;
-    *names = NULL;
-    *nnames = 0;
-
-    /* ssl3.ca_list is initialized to NULL, and never changed. */
-    ca_list = ss->ssl3.ca_list;
-    if (!ca_list) {
-        ca_list = ssl3_server_ca_list;
-    }
-
-    if (ca_list != NULL) {
-        *names = ca_list->names;
-        *nnames = ca_list->nnames;
-    }
-
-    for (i = 0, name = *names; i < *nnames; i++, name++) {
-        *calen += 2 + name->len;
-    }
-}
-
-static SECStatus
-ssl3_SendCertificateRequest(sslSocket *ss)
-{
-    PRBool isTLS12;
-    const PRUint8 *certTypes;
-    SECStatus rv;
-    int length;
-    SECItem *names;
-    int calen;
-    int nnames;
-    SECItem *name;
-    int i;
-    int certTypesLength;
-    PRUint8 sigAlgs[MAX_SIGNATURE_ALGORITHMS * 2];
-    unsigned int sigAlgsLength = 0;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: send certificate_request handshake",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
-
-    ssl3_GetCertificateRequestCAs(ss, &calen, &names, &nnames);
-    certTypes = certificate_types;
-    certTypesLength = sizeof certificate_types;
-
-    length = 1 + certTypesLength + 2 + calen;
-    if (isTLS12) {
-        rv = ssl3_EncodeCertificateRequestSigAlgs(ss, sigAlgs, sizeof(sigAlgs),
-                                                  &sigAlgsLength);
-        if (rv != SECSuccess) {
-            return rv;
-        }
-        length += 2 + sigAlgsLength;
-    }
-
-    rv = ssl3_AppendHandshakeHeader(ss, certificate_request, length);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake. */
-    }
-    rv = ssl3_AppendHandshakeVariable(ss, certTypes, certTypesLength, 1);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake. */
-    }
-    if (isTLS12) {
-        rv = ssl3_AppendHandshakeVariable(ss, sigAlgs, sigAlgsLength, 2);
-        if (rv != SECSuccess) {
-            return rv; /* err set by AppendHandshake. */
-        }
-    }
-    rv = ssl3_AppendHandshakeNumber(ss, calen, 2);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake. */
-    }
-    for (i = 0, name = names; i < nnames; i++, name++) {
-        rv = ssl3_AppendHandshakeVariable(ss, name->data, name->len, 2);
-        if (rv != SECSuccess) {
-            return rv; /* err set by AppendHandshake. */
-        }
-    }
-
-    return SECSuccess;
-}
-
-static SECStatus
-ssl3_SendServerHelloDone(sslSocket *ss)
-{
-    SECStatus rv;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: send server_hello_done handshake",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    rv = ssl3_AppendHandshakeHeader(ss, server_hello_done, 0);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake. */
-    }
-    rv = ssl3_FlushHandshake(ss, 0);
-    if (rv != SECSuccess) {
-        return rv; /* error code set by ssl3_FlushHandshake */
-    }
-    return SECSuccess;
-}
-
-/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered
- * a complete ssl3 Certificate Verify message
- * Caller must hold Handshake and RecvBuf locks.
- */
-static SECStatus
-ssl3_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
-                             SSL3Hashes *hashes)
-{
-    SECItem signed_hash = { siBuffer, NULL, 0 };
-    SECStatus rv;
-    int errCode = SSL_ERROR_RX_MALFORMED_CERT_VERIFY;
-    SSL3AlertDescription desc = handshake_failure;
-    PRBool isTLS, isTLS12;
-    SSLSignatureAndHashAlg sigAndHash;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_verify handshake",
-                SSL_GETPID(), ss->fd));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
-    isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
-
-    if (ss->ssl3.hs.ws != wait_cert_verify) {
-        desc = unexpected_message;
-        errCode = SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY;
-        goto alert_loser;
-    }
-
-    if (!hashes) {
-        PORT_Assert(0);
-        desc = internal_error;
-        errCode = SEC_ERROR_LIBRARY_FAILURE;
-        goto alert_loser;
-    }
-
-    if (isTLS12) {
-        rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
-                                                   &sigAndHash);
-        if (rv != SECSuccess) {
-            goto loser; /* malformed or unsupported. */
-        }
-        rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
-            ss, &sigAndHash, ss->sec.peerCert);
-        if (rv != SECSuccess) {
-            errCode = PORT_GetError();
-            desc = decrypt_error;
-            goto alert_loser;
-        }
-
-        /* We only support CertificateVerify messages that use the handshake
-         * hash. */
-        if (sigAndHash.hashAlg != hashes->hashAlg) {
-            errCode = SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM;
-            desc = decrypt_error;
-            goto alert_loser;
-        }
-    }
-
-    rv = ssl3_ConsumeHandshakeVariable(ss, &signed_hash, 2, &b, &length);
-    if (rv != SECSuccess) {
-        goto loser; /* malformed. */
-    }
-
-    /* XXX verify that the key & kea match */
-    rv = ssl3_VerifySignedHashes(hashes, ss->sec.peerCert, &signed_hash,
-                                 isTLS, ss->pkcs11PinArg);
-    if (rv != SECSuccess) {
-        errCode = PORT_GetError();
-        desc = isTLS ? decrypt_error : handshake_failure;
-        goto alert_loser;
-    }
-
-    signed_hash.data = NULL;
-
-    if (length != 0) {
-        desc = isTLS ? decode_error : illegal_parameter;
-        goto alert_loser; /* malformed */
-    }
-    ss->ssl3.hs.ws = wait_change_cipher;
-    return SECSuccess;
-
-alert_loser:
-    SSL3_SendAlert(ss, alert_fatal, desc);
-loser:
-    PORT_SetError(errCode);
-    return SECFailure;
-}
-
-/* find a slot that is able to generate a PMS and wrap it with RSA.
- * Then generate and return the PMS.
- * If the serverKeySlot parameter is non-null, this function will use
- * that slot to do the job, otherwise it will find a slot.
- *
- * Called from  ssl3_DeriveConnectionKeysPKCS11()  (above)
- *      sendRSAClientKeyExchange()         (above)
- *      ssl3_HandleRSAClientKeyExchange()  (below)
- * Caller must hold the SpecWriteLock, the SSL3HandshakeLock
- */
-static PK11SymKey *
-ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec,
-                    PK11SlotInfo *serverKeySlot)
-{
-    PK11SymKey *pms = NULL;
-    PK11SlotInfo *slot = serverKeySlot;
-    void *pwArg = ss->pkcs11PinArg;
-    SECItem param;
-    CK_VERSION version;
-    CK_MECHANISM_TYPE mechanism_array[3];
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if (slot == NULL) {
-        SSLCipherAlgorithm calg;
-        /* The specReadLock would suffice here, but we cannot assert on
-        ** read locks.  Also, all the callers who call with a non-null
-        ** slot already hold the SpecWriteLock.
-        */
-        PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
-        PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
-
-        calg = spec->cipher_def->calg;
-
-        /* First get an appropriate slot.  */
-        mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN;
-        mechanism_array[1] = CKM_RSA_PKCS;
-        mechanism_array[2] = ssl3_Alg2Mech(calg);
-
-        slot = PK11_GetBestSlotMultiple(mechanism_array, 3, pwArg);
-        if (slot == NULL) {
-            /* can't find a slot with all three, find a slot with the minimum */
-            slot = PK11_GetBestSlotMultiple(mechanism_array, 2, pwArg);
-            if (slot == NULL) {
-                PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND);
-                return pms; /* which is NULL */
-            }
-        }
-    }
-
-    /* Generate the pre-master secret ...  */
-    if (IS_DTLS(ss)) {
-        SSL3ProtocolVersion temp;
-
-        temp = dtls_TLSVersionToDTLSVersion(ss->clientHelloVersion);
-        version.major = MSB(temp);
-        version.minor = LSB(temp);
-    } else {
-        version.major = MSB(ss->clientHelloVersion);
-        version.minor = LSB(ss->clientHelloVersion);
-    }
-
-    param.data = (unsigned char *)&version;
-    param.len = sizeof version;
-
-    pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, &param, 0, pwArg);
-    if (!serverKeySlot)
-        PK11_FreeSlot(slot);
-    if (pms == NULL) {
-        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
-    }
-    return pms;
-}
-
-/* Note: The Bleichenbacher attack on PKCS#1 necessitates that we NEVER
- * return any indication of failure of the Client Key Exchange message,
- * where that failure is caused by the content of the client's message.
- * This function must not return SECFailure for any reason that is directly
- * or indirectly caused by the content of the client's encrypted PMS.
- * We must not send an alert and also not drop the connection.
- * Instead, we generate a random PMS.  This will cause a failure
- * in the processing the finished message, which is exactly where
- * the failure must occur.
- *
- * Called from ssl3_HandleClientKeyExchange
- */
-static SECStatus
-ssl3_HandleRSAClientKeyExchange(sslSocket *ss,
-                                SSL3Opaque *b,
-                                PRUint32 length,
-                                SECKEYPrivateKey *serverKey)
-{
-#ifndef NO_PKCS11_BYPASS
-    unsigned char *cr = (unsigned char *)&ss->ssl3.hs.client_random;
-    unsigned char *sr = (unsigned char *)&ss->ssl3.hs.server_random;
-    ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
-    unsigned int outLen = 0;
-    PRBool isTLS = PR_FALSE;
-    SECItem pmsItem = { siBuffer, NULL, 0 };
-    unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH];
-#endif
-    SECStatus rv;
-    SECItem enc_pms;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
-
-    enc_pms.data = b;
-    enc_pms.len = length;
-#ifndef NO_PKCS11_BYPASS
-    pmsItem.data = rsaPmsBuf;
-    pmsItem.len = sizeof rsaPmsBuf;
-#endif
-
-    if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */
-        PRInt32 kLen;
-        kLen = ssl3_ConsumeHandshakeNumber(ss, 2, &enc_pms.data, &enc_pms.len);
-        if (kLen < 0) {
-            PORT_SetError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
-            return SECFailure;
-        }
-        if ((unsigned)kLen < enc_pms.len) {
-            enc_pms.len = kLen;
-        }
-#ifndef NO_PKCS11_BYPASS
-        isTLS = PR_TRUE;
-#endif
-    } else {
-#ifndef NO_PKCS11_BYPASS
-        isTLS = (PRBool)(ss->ssl3.hs.kea_def->tls_keygen != 0);
-#endif
-    }
-
-#ifndef NO_PKCS11_BYPASS
-    if (ss->opt.bypassPKCS11) {
-        /* We have not implemented a tls_ExtendedMasterKeyDeriveBypass
-         * and will not negotiate this extension in bypass mode. This
-         * assert just double-checks that.
-         */
-        PORT_Assert(
-            !ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn));
-
-        /* TRIPLE BYPASS, get PMS directly from RSA decryption.
-         * Use PK11_PrivDecryptPKCS1 to decrypt the PMS to a buffer,
-         * then, check for version rollback attack, then
-         * do the equivalent of ssl3_DeriveMasterSecret, placing the MS in
-         * pwSpec->msItem.  Finally call ssl3_InitPendingCipherSpec with
-         * ss and NULL, so that it will use the MS we've already derived here.
-         */
-
-        rv = PK11_PrivDecryptPKCS1(serverKey, rsaPmsBuf, &outLen,
-                                   sizeof rsaPmsBuf, enc_pms.data, enc_pms.len);
-        if (rv != SECSuccess) {
-            /* triple bypass failed.  Let's try for a double bypass. */
-            goto double_bypass;
-        } else if (ss->opt.detectRollBack) {
-            SSL3ProtocolVersion client_version =
-                (rsaPmsBuf[0] << 8) | rsaPmsBuf[1];
-
-            if (IS_DTLS(ss)) {
-                client_version = dtls_DTLSVersionToTLSVersion(client_version);
-            }
-
-            if (client_version != ss->clientHelloVersion) {
-                /* Version roll-back detected. ensure failure.  */
-                rv = PK11_GenerateRandom(rsaPmsBuf, sizeof rsaPmsBuf);
-            }
-        }
-        /* have PMS, build MS without PKCS11 */
-        rv = ssl3_MasterSecretDeriveBypass(pwSpec, cr, sr, &pmsItem, isTLS,
-                                           PR_TRUE);
-        if (rv != SECSuccess) {
-            pwSpec->msItem.data = pwSpec->raw_master_secret;
-            pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH;
-            PK11_GenerateRandom(pwSpec->msItem.data, pwSpec->msItem.len);
-        }
-        rv = ssl3_InitPendingCipherSpec(ss, NULL);
-    } else
-#endif
-    {
-        PK11SymKey *tmpPms[2] = { NULL, NULL };
-        PK11SlotInfo *slot;
-        int useFauxPms = 0;
-#define currentPms tmpPms[!useFauxPms]
-#define unusedPms tmpPms[useFauxPms]
-#define realPms tmpPms[1]
-#define fauxPms tmpPms[0]
-
-#ifndef NO_PKCS11_BYPASS
-    double_bypass:
-#endif
-
-        /*
-         * Get as close to algorithm 2 from RFC 5246; Section 7.4.7.1
-         * as we can within the constraints of the PKCS#11 interface.
-         *
-         * 1. Unconditionally generate a bogus PMS (what RFC 5246
-         *    calls R).
-         * 2. Attempt the RSA decryption to recover the PMS (what
-         *    RFC 5246 calls M).
-         * 3. Set PMS = (M == NULL) ? R : M
-         * 4. Use ssl3_ComputeMasterSecret(PMS) to attempt to derive
-         *    the MS from PMS. This includes performing the version
-         *    check and length check.
-         * 5. If either the initial RSA decryption failed or
-         *    ssl3_ComputeMasterSecret(PMS) failed, then discard
-         *    M and set PMS = R. Else, discard R and set PMS = M.
-         *
-         * We do two derivations here because we can't rely on having
-         * a function that only performs the PMS version and length
-         * check. The only redundant cost is that this runs the PRF,
-         * which isn't necessary here.
-         */
-
-        /* Generate the bogus PMS (R) */
-        slot = PK11_GetSlotFromPrivateKey(serverKey);
-        if (!slot) {
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            return SECFailure;
-        }
-
-        if (!PK11_DoesMechanism(slot, CKM_SSL3_MASTER_KEY_DERIVE)) {
-            PK11_FreeSlot(slot);
-            slot = PK11_GetBestSlot(CKM_SSL3_MASTER_KEY_DERIVE, NULL);
-            if (!slot) {
-                PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-                return SECFailure;
-            }
-        }
-
-        ssl_GetSpecWriteLock(ss);
-        fauxPms = ssl3_GenerateRSAPMS(ss, ss->ssl3.prSpec, slot);
-        ssl_ReleaseSpecWriteLock(ss);
-        PK11_FreeSlot(slot);
-
-        if (fauxPms == NULL) {
-            ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
-            return SECFailure;
-        }
-
-        /*
-         * unwrap pms out of the incoming buffer
-         * Note: CKM_SSL3_MASTER_KEY_DERIVE is NOT the mechanism used to do
-         *  the unwrap.  Rather, it is the mechanism with which the
-         *      unwrapped pms will be used.
-         */
-        realPms = PK11_PubUnwrapSymKey(serverKey, &enc_pms,
-                                       CKM_SSL3_MASTER_KEY_DERIVE, CKA_DERIVE, 0);
-        /* Temporarily use the PMS if unwrapping the real PMS fails. */
-        useFauxPms |= (realPms == NULL);
-
-        /* Attempt to derive the MS from the PMS. This is the only way to
-         * check the version field in the RSA PMS. If this fails, we
-         * then use the faux PMS in place of the PMS. Note that this
-         * operation should never fail if we are using the faux PMS
-         * since it is correctly formatted. */
-        rv = ssl3_ComputeMasterSecret(ss, currentPms, NULL);
-
-        /* If we succeeded, then select the true PMS and discard the
-         * FPMS. Else, select the FPMS and select the true PMS */
-        useFauxPms |= (rv != SECSuccess);
-
-        if (unusedPms) {
-            PK11_FreeSymKey(unusedPms);
-        }
-
-        /* This step will derive the MS from the PMS, among other things. */
-        rv = ssl3_InitPendingCipherSpec(ss, currentPms);
-        PK11_FreeSymKey(currentPms);
-    }
-
-    if (rv != SECSuccess) {
-        SEND_ALERT
-        return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */
-    }
-
-#undef currentPms
-#undef unusedPms
-#undef realPms
-#undef fauxPms
-
-    return SECSuccess;
-}
-
-static SECStatus
-ssl3_HandleDHClientKeyExchange(sslSocket *ss,
-                               SSL3Opaque *b,
-                               PRUint32 length,
-                               SECKEYPublicKey *srvrPubKey,
-                               SECKEYPrivateKey *serverKey)
-{
-    PK11SymKey *pms;
-    SECStatus rv;
-    SECKEYPublicKey clntPubKey;
-    CK_MECHANISM_TYPE target;
-    PRBool isTLS;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(srvrPubKey);
-
-    clntPubKey.keyType = dhKey;
-    clntPubKey.u.dh.prime.len = srvrPubKey->u.dh.prime.len;
-    clntPubKey.u.dh.prime.data = srvrPubKey->u.dh.prime.data;
-    clntPubKey.u.dh.base.len = srvrPubKey->u.dh.base.len;
-    clntPubKey.u.dh.base.data = srvrPubKey->u.dh.base.data;
-
-    rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.dh.publicValue,
-                                       2, &b, &length);
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-
-    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
-
-    if (isTLS)
-        target = CKM_TLS_MASTER_KEY_DERIVE_DH;
-    else
-        target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
-
-    /*  Determine the PMS */
-    pms = PK11_PubDerive(serverKey, &clntPubKey, PR_FALSE, NULL, NULL,
-                         CKM_DH_PKCS_DERIVE, target, CKA_DERIVE, 0, NULL);
-    if (pms == NULL) {
-        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
-        goto loser;
-    }
-
-    rv = ssl3_InitPendingCipherSpec(ss, pms);
-    PK11_FreeSymKey(pms);
-    pms = NULL;
-
-loser:
-    if (ss->dheKeyPair) {
-        ssl3_FreeKeyPair(ss->dheKeyPair);
-        ss->dheKeyPair = NULL;
-    }
-    return rv;
-}
-
-/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered
- * a complete ssl3 ClientKeyExchange message from the remote client
- * Caller must hold Handshake and RecvBuf locks.
- */
-static SECStatus
-ssl3_HandleClientKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    SECKEYPrivateKey *serverKey = NULL;
-    SECStatus rv;
-    const ssl3KEADef *kea_def;
-    ssl3KeyPair *serverKeyPair = NULL;
-    SECKEYPublicKey *serverPubKey = NULL;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: handle client_key_exchange handshake",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if (ss->ssl3.hs.ws != wait_client_key) {
-        SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-        PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH);
-        return SECFailure;
-    }
-
-    kea_def = ss->ssl3.hs.kea_def;
-
-    if (ss->ssl3.hs.usedStepDownKey) {
-        PORT_Assert(kea_def->is_limited /* XXX OR cert is signing only */
-                    &&
-                    kea_def->exchKeyType == kt_rsa &&
-                    ss->stepDownKeyPair != NULL);
-        if (!kea_def->is_limited ||
-            kea_def->exchKeyType != kt_rsa ||
-            ss->stepDownKeyPair == NULL) {
-            /* shouldn't happen, don't use step down if it does */
-            goto skip;
-        }
-        serverKeyPair = ss->stepDownKeyPair;
-        ss->sec.keaKeyBits = EXPORT_RSA_KEY_LENGTH * BPB;
-    } else
-    skip:
-    if (kea_def->kea == kea_dhe_dss ||
-        kea_def->kea == kea_dhe_rsa) {
-        if (ss->dheKeyPair) {
-            serverKeyPair = ss->dheKeyPair;
-            if (serverKeyPair->pubKey) {
-                ss->sec.keaKeyBits =
-                    SECKEY_PublicKeyStrengthInBits(serverKeyPair->pubKey);
-            }
-        }
-    } else
-#ifndef NSS_DISABLE_ECC
-        /* XXX Using SSLKEAType to index server certifiates
-         * does not work for (EC)DHE ciphers. Until we have
-         * an indexing mechanism general enough for all key
-         * exchange algorithms, we'll need to deal with each
-         * one seprately.
-         */
-        if ((kea_def->kea == kea_ecdhe_rsa) ||
-            (kea_def->kea == kea_ecdhe_ecdsa)) {
-        if (ss->ephemeralECDHKeyPair != NULL) {
-            serverKeyPair = ss->ephemeralECDHKeyPair;
-            if (serverKeyPair->pubKey) {
-                ss->sec.keaKeyBits =
-                    SECKEY_PublicKeyStrengthInBits(serverKeyPair->pubKey);
-            }
-        }
-    } else
-#endif
-    {
-        sslServerCerts *sc = ss->serverCerts + kea_def->exchKeyType;
-        serverKeyPair = sc->serverKeyPair;
-        ss->sec.keaKeyBits = sc->serverKeyBits;
-    }
-
-    if (serverKeyPair) {
-        serverKey = serverKeyPair->privKey;
-    }
-
-    if (serverKey == NULL) {
-        SEND_ALERT
-        PORT_SetError(SSL_ERROR_NO_SERVER_KEY_FOR_ALG);
-        return SECFailure;
-    }
-
-    ss->sec.keaType = kea_def->exchKeyType;
-
-    switch (kea_def->exchKeyType) {
-        case kt_rsa:
-            rv = ssl3_HandleRSAClientKeyExchange(ss, b, length, serverKey);
-            if (rv != SECSuccess) {
-                SEND_ALERT
-                return SECFailure; /* error code set */
-            }
-            break;
-
-        case ssl_kea_dh:
-            if (ss->dheKeyPair && ss->dheKeyPair->pubKey) {
-                serverPubKey = ss->dheKeyPair->pubKey;
-            }
-            if (!serverPubKey) {
-                PORT_SetError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
-                return SECFailure;
-            }
-            rv = ssl3_HandleDHClientKeyExchange(ss, b, length,
-                                                serverPubKey, serverKey);
-            if (rv != SECSuccess) {
-                SSL3_SendAlert(ss, alert_fatal, handshake_failure);
-                return SECFailure; /* error code set */
-            }
-            break;
-
-#ifndef NSS_DISABLE_ECC
-        case kt_ecdh:
-            /* XXX We really ought to be able to store multiple
-             * EC certs (a requirement if we wish to support both
-             * ECDH-RSA and ECDH-ECDSA key exchanges concurrently).
-             * When we make that change, we'll need an index other
-             * than kt_ecdh to pick the right EC certificate.
-             */
-            if (serverKeyPair) {
-                serverPubKey = serverKeyPair->pubKey;
-            }
-            if (serverPubKey == NULL) {
-                /* XXX Is this the right error code? */
-                PORT_SetError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
-                return SECFailure;
-            }
-            rv = ssl3_HandleECDHClientKeyExchange(ss, b, length,
-                                                  serverPubKey, serverKey);
-            if (ss->ephemeralECDHKeyPair) {
-                ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair);
-                ss->ephemeralECDHKeyPair = NULL;
-            }
-            if (rv != SECSuccess) {
-                return SECFailure; /* error code set */
-            }
-            break;
-#endif /* NSS_DISABLE_ECC */
-
-        default:
-            (void)ssl3_HandshakeFailure(ss);
-            PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
-            return SECFailure;
-    }
-    ss->ssl3.hs.ws = ss->sec.peerCert ? wait_cert_verify : wait_change_cipher;
-    return SECSuccess;
-}
-
-/* This is TLS's equivalent of sending a no_certificate alert. */
-SECStatus
-ssl3_SendEmptyCertificate(sslSocket *ss)
-{
-    SECStatus rv;
-    unsigned int len = 0;
-    PRBool isTLS13 = PR_FALSE;
-
-    if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
-        len = ss->ssl3.hs.certReqContextLen + 1;
-        isTLS13 = PR_TRUE;
-    }
-
-    rv = ssl3_AppendHandshakeHeader(ss, certificate, len + 3);
-    if (rv != SECSuccess) {
-        return rv;
-    }
-
-    if (isTLS13) {
-        rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.hs.certReqContext,
-                                          ss->ssl3.hs.certReqContextLen, 1);
-        if (rv != SECSuccess) {
-            return rv;
-        }
-    }
-
-    return ssl3_AppendHandshakeNumber(ss, 0, 3);
-}
-
-SECStatus
-ssl3_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    SECStatus rv;
-    SECItem ticketData;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: handle session_ticket handshake",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    PORT_Assert(!ss->ssl3.hs.newSessionTicket.ticket.data);
-    PORT_Assert(!ss->ssl3.hs.receivedNewSessionTicket);
-
-    if (ss->ssl3.hs.ws != wait_new_session_ticket) {
-        SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-        PORT_SetError(SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET);
-        return SECFailure;
-    }
-
-    /* RFC5077 Section 3.3: "The client MUST NOT treat the ticket as valid
-     * until it has verified the server's Finished message." See the comment in
-     * ssl3_FinishHandshake for more details.
-     */
-    ss->ssl3.hs.newSessionTicket.received_timestamp = ssl_Time();
-    if (length < 4) {
-        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
-        PORT_SetError(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET);
-        return SECFailure;
-    }
-    ss->ssl3.hs.newSessionTicket.ticket_lifetime_hint =
-        (PRUint32)ssl3_ConsumeHandshakeNumber(ss, 4, &b, &length);
-
-    rv = ssl3_ConsumeHandshakeVariable(ss, &ticketData, 2, &b, &length);
-    if (rv != SECSuccess || length != 0) {
-        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
-        PORT_SetError(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET);
-        return SECFailure; /* malformed */
-    }
-    /* If the server sent a zero-length ticket, ignore it and keep the
-     * existing ticket. */
-    if (ticketData.len != 0) {
-        rv = SECITEM_CopyItem(NULL, &ss->ssl3.hs.newSessionTicket.ticket,
-                              &ticketData);
-        if (rv != SECSuccess) {
-            return rv;
-        }
-        ss->ssl3.hs.receivedNewSessionTicket = PR_TRUE;
-    }
-
-    ss->ssl3.hs.ws = wait_change_cipher;
-    return SECSuccess;
-}
-
-#ifdef NISCC_TEST
-static PRInt32 connNum = 0;
-
-static SECStatus
-get_fake_cert(SECItem *pCertItem, int *pIndex)
-{
-    PRFileDesc *cf;
-    char *testdir;
-    char *startat;
-    char *stopat;
-    const char *extension;
-    int fileNum;
-    PRInt32 numBytes = 0;
-    PRStatus prStatus;
-    PRFileInfo info;
-    char cfn[100];
-
-    pCertItem->data = 0;
-    if ((testdir = PR_GetEnvSecure("NISCC_TEST")) == NULL) {
-        return SECSuccess;
-    }
-    *pIndex = (NULL != strstr(testdir, "root"));
-    extension = (strstr(testdir, "simple") ? "" : ".der");
-    fileNum = PR_ATOMIC_INCREMENT(&connNum) - 1;
-    if ((startat = PR_GetEnvSecure("START_AT")) != NULL) {
-        fileNum += atoi(startat);
-    }
-    if ((stopat = PR_GetEnvSecure("STOP_AT")) != NULL &&
-        fileNum >= atoi(stopat)) {
-        *pIndex = -1;
-        return SECSuccess;
-    }
-    sprintf(cfn, "%s/%08d%s", testdir, fileNum, extension);
-    cf = PR_Open(cfn, PR_RDONLY, 0);
-    if (!cf) {
-        goto loser;
-    }
-    prStatus = PR_GetOpenFileInfo(cf, &info);
-    if (prStatus != PR_SUCCESS) {
-        PR_Close(cf);
-        goto loser;
-    }
-    pCertItem = SECITEM_AllocItem(NULL, pCertItem, info.size);
-    if (pCertItem) {
-        numBytes = PR_Read(cf, pCertItem->data, info.size);
-    }
-    PR_Close(cf);
-    if (numBytes != info.size) {
-        SECITEM_FreeItem(pCertItem, PR_FALSE);
-        PORT_SetError(SEC_ERROR_IO);
-        goto loser;
-    }
-    fprintf(stderr, "using %s\n", cfn);
-    return SECSuccess;
-
-loser:
-    fprintf(stderr, "failed to use %s\n", cfn);
-    *pIndex = -1;
-    return SECFailure;
-}
-#endif
-
-/*
- * Used by both client and server.
- * Called from HandleServerHelloDone and from SendServerHelloSequence.
- */
-SECStatus
-ssl3_SendCertificate(sslSocket *ss)
-{
-    SECStatus rv;
-    CERTCertificateList *certChain;
-    int certChainLen = 0;
-    int i;
-    SSL3KEAType certIndex;
-#ifdef NISCC_TEST
-    SECItem fakeCert;
-    int ndex = -1;
-#endif
-    PRBool isTLS13 = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3;
-    unsigned int contextLen = 0;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: send certificate handshake",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if (ss->sec.localCert)
-        CERT_DestroyCertificate(ss->sec.localCert);
-    if (ss->sec.isServer) {
-        sslServerCerts *sc = NULL;
-
-        /* XXX SSLKEAType isn't really a good choice for
-         * indexing certificates (it breaks when we deal
-         * with (EC)DHE-* cipher suites. This hack ensures
-         * the RSA cert is picked for (EC)DHE-RSA.
-         * Revisit this when we add server side support
-         * for ECDHE-ECDSA or client-side authentication
-         * using EC certificates.
-         */
-        if ((ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) ||
-            (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) {
-            certIndex = kt_rsa;
-        } else {
-            certIndex = ss->ssl3.hs.kea_def->exchKeyType;
-        }
-        sc = ss->serverCerts + certIndex;
-        certChain = sc->serverCertChain;
-        ss->sec.authKeyBits = sc->serverKeyBits;
-        ss->sec.authAlgorithm = ss->ssl3.hs.kea_def->signKeyType;
-        ss->sec.localCert = CERT_DupCertificate(sc->serverCert);
-    } else {
-        certChain = ss->ssl3.clientCertChain;
-        ss->sec.localCert = CERT_DupCertificate(ss->ssl3.clientCertificate);
-    }
-
-#ifdef NISCC_TEST
-    rv = get_fake_cert(&fakeCert, &ndex);
-#endif
-
-    if (isTLS13) {
-        contextLen = 1; /* Length of the context */
-        if (!ss->sec.isServer) {
-            contextLen += ss->ssl3.hs.certReqContextLen;
-        }
-    }
-    if (certChain) {
-        for (i = 0; i < certChain->len; i++) {
-#ifdef NISCC_TEST
-            if (fakeCert.len > 0 && i == ndex) {
-                certChainLen += fakeCert.len + 3;
-            } else {
-                certChainLen += certChain->certs[i].len + 3;
-            }
-#else
-            certChainLen += certChain->certs[i].len + 3;
-#endif
-        }
-    }
-
-    rv = ssl3_AppendHandshakeHeader(ss, certificate,
-                                    contextLen + certChainLen + 3);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake. */
-    }
-
-    if (isTLS13) {
-        if (ss->sec.isServer) {
-            rv = ssl3_AppendHandshakeNumber(ss, 0, 1);
-        } else {
-            rv = ssl3_AppendHandshakeVariable(ss,
-                                              ss->ssl3.hs.certReqContext,
-                                              ss->ssl3.hs.certReqContextLen, 1);
-        }
-        if (rv != SECSuccess) {
-            return rv; /* err set by AppendHandshake. */
-        }
-    }
-
-    rv = ssl3_AppendHandshakeNumber(ss, certChainLen, 3);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake. */
-    }
-    if (certChain) {
-        for (i = 0; i < certChain->len; i++) {
-#ifdef NISCC_TEST
-            if (fakeCert.len > 0 && i == ndex) {
-                rv = ssl3_AppendHandshakeVariable(ss, fakeCert.data,
-                                                  fakeCert.len, 3);
-                SECITEM_FreeItem(&fakeCert, PR_FALSE);
-            } else {
-                rv = ssl3_AppendHandshakeVariable(ss, certChain->certs[i].data,
-                                                  certChain->certs[i].len, 3);
-            }
-#else
-            rv = ssl3_AppendHandshakeVariable(ss, certChain->certs[i].data,
-                                              certChain->certs[i].len, 3);
-#endif
-            if (rv != SECSuccess) {
-                return rv; /* err set by AppendHandshake. */
-            }
-        }
-    }
-
-    return SECSuccess;
-}
-
-/*
- * Used by server only.
- * single-stapling, send only a single cert status
- */
-SECStatus
-ssl3_SendCertificateStatus(sslSocket *ss)
-{
-    SECStatus rv;
-    int len = 0;
-    SECItemArray *statusToSend = NULL;
-    SSL3KEAType certIndex;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: send certificate status handshake",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->sec.isServer);
-
-    if (!ssl3_ExtensionNegotiated(ss, ssl_cert_status_xtn))
-        return SECSuccess;
-
-    /* Use certStatus based on the cert being used. */
-    if ((ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) ||
-        (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) {
-        certIndex = kt_rsa;
-    } else {
-        certIndex = ss->ssl3.hs.kea_def->exchKeyType;
-    }
-    if (ss->certStatusArray[certIndex] && ss->certStatusArray[certIndex]->len) {
-        statusToSend = ss->certStatusArray[certIndex];
-    }
-    if (!statusToSend)
-        return SECSuccess;
-
-    /* Use the array's first item only (single stapling) */
-    len = 1 + statusToSend->items[0].len + 3;
-
-    rv = ssl3_AppendHandshakeHeader(ss, certificate_status, len);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake. */
-    }
-    rv = ssl3_AppendHandshakeNumber(ss, 1 /*ocsp*/, 1);
-    if (rv != SECSuccess)
-        return rv; /* err set by AppendHandshake. */
-
-    rv = ssl3_AppendHandshakeVariable(ss,
-                                      statusToSend->items[0].data,
-                                      statusToSend->items[0].len,
-                                      3);
-    if (rv != SECSuccess)
-        return rv; /* err set by AppendHandshake. */
-
-    return SECSuccess;
-}
-
-/* This is used to delete the CA certificates in the peer certificate chain
- * from the cert database after they've been validated.
- */
-static void
-ssl3_CleanupPeerCerts(sslSocket *ss)
-{
-    PLArenaPool *arena = ss->ssl3.peerCertArena;
-    ssl3CertNode *certs = (ssl3CertNode *)ss->ssl3.peerCertChain;
-
-    for (; certs; certs = certs->next) {
-        CERT_DestroyCertificate(certs->cert);
-    }
-    if (arena)
-        PORT_FreeArena(arena, PR_FALSE);
-    ss->ssl3.peerCertArena = NULL;
-    ss->ssl3.peerCertChain = NULL;
-}
-
-/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered
- * a complete ssl3 CertificateStatus message.
- * Caller must hold Handshake and RecvBuf locks.
- */
-static SECStatus
-ssl3_HandleCertificateStatus(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    if (ss->ssl3.hs.ws != wait_certificate_status) {
-        (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-        PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERT_STATUS);
-        return SECFailure;
-    }
-
-    return ssl3_CompleteHandleCertificateStatus(ss, b, length);
-}
-
-/* Called from:
- *      ssl3_HandleCertificateStatus
- *      tls13_HandleCertificateStatus
- */
-SECStatus
-ssl3_CompleteHandleCertificateStatus(sslSocket *ss, SSL3Opaque *b,
-                                     PRUint32 length)
-{
-    PRInt32 status, len;
-
-    PORT_Assert(!ss->sec.isServer);
-
-    /* Consume the CertificateStatusType enum */
-    status = ssl3_ConsumeHandshakeNumber(ss, 1, &b, &length);
-    if (status != 1 /* ocsp */) {
-        goto format_loser;
-    }
-
-    len = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length);
-    if (len != length) {
-        goto format_loser;
-    }
-
-#define MAX_CERTSTATUS_LEN 0x1ffff /* 128k - 1 */
-    if (length > MAX_CERTSTATUS_LEN)
-        goto format_loser;
-#undef MAX_CERTSTATUS_LEN
-
-    /* Array size 1, because we currently implement single-stapling only */
-    SECITEM_AllocArray(NULL, &ss->sec.ci.sid->peerCertStatus, 1);
-    if (!ss->sec.ci.sid->peerCertStatus.items)
-        return SECFailure;
-
-    ss->sec.ci.sid->peerCertStatus.items[0].data = PORT_Alloc(length);
-
-    if (!ss->sec.ci.sid->peerCertStatus.items[0].data) {
-        SECITEM_FreeArray(&ss->sec.ci.sid->peerCertStatus, PR_FALSE);
-        return SECFailure;
-    }
-
-    PORT_Memcpy(ss->sec.ci.sid->peerCertStatus.items[0].data, b, length);
-    ss->sec.ci.sid->peerCertStatus.items[0].len = length;
-    ss->sec.ci.sid->peerCertStatus.items[0].type = siBuffer;
-
-    return ssl3_AuthCertificate(ss);
-
-format_loser:
-    return ssl3_DecodeError(ss);
-}
-
-/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered
- * a complete ssl3 Certificate message.
- * Caller must hold Handshake and RecvBuf locks.
- */
-static SECStatus
-ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    SSL_TRC(3, ("%d: SSL3[%d]: handle certificate handshake",
-                SSL_GETPID(), ss->fd));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if ((ss->sec.isServer && ss->ssl3.hs.ws != wait_client_cert) ||
-        (!ss->sec.isServer && ss->ssl3.hs.ws != wait_server_cert)) {
-        (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-        PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERTIFICATE);
-        return SECFailure;
-    }
-
-    return ssl3_CompleteHandleCertificate(ss, b, length);
-}
-
-/* Called from ssl3_HandleCertificate
- */
-SECStatus
-ssl3_CompleteHandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    ssl3CertNode *c;
-    ssl3CertNode *lastCert = NULL;
-    PRInt32 remaining = 0;
-    PRInt32 size;
-    SECStatus rv;
-    PRBool isServer = (PRBool)(!!ss->sec.isServer);
-    PRBool isTLS;
-    SSL3AlertDescription desc;
-    int errCode = SSL_ERROR_RX_MALFORMED_CERTIFICATE;
-    SECItem certItem;
-
-    if (ss->sec.peerCert != NULL) {
-        if (ss->sec.peerKey) {
-            SECKEY_DestroyPublicKey(ss->sec.peerKey);
-            ss->sec.peerKey = NULL;
-        }
-        CERT_DestroyCertificate(ss->sec.peerCert);
-        ss->sec.peerCert = NULL;
-    }
-
-    ssl3_CleanupPeerCerts(ss);
-    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
-
-    /* It is reported that some TLS client sends a Certificate message
-    ** with a zero-length message body.  We'll treat that case like a
-    ** normal no_certificates message to maximize interoperability.
-    */
-    if (length) {
-        remaining = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length);
-        if (remaining < 0)
-            goto loser; /* fatal alert already sent by ConsumeHandshake. */
-        if ((PRUint32)remaining > length)
-            goto decode_loser;
-    }
-
-    if (!remaining) {
-        if (!(isTLS && isServer)) {
-            desc = bad_certificate;
-            goto alert_loser;
-        }
-        /* This is TLS's version of a no_certificate alert. */
-        /* I'm a server. I've requested a client cert. He hasn't got one. */
-        rv = ssl3_HandleNoCertificate(ss);
-        if (rv != SECSuccess) {
-            errCode = PORT_GetError();
-            goto loser;
-        }
-
-        if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-            ss->ssl3.hs.ws = wait_client_key;
-        } else {
-            TLS13_SET_HS_STATE(ss, wait_finished);
-        }
-        return SECSuccess;
-    }
-
-    ss->ssl3.peerCertArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-    if (ss->ssl3.peerCertArena == NULL) {
-        goto loser; /* don't send alerts on memory errors */
-    }
-
-    /* First get the peer cert. */
-    remaining -= 3;
-    if (remaining < 0)
-        goto decode_loser;
-
-    size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length);
-    if (size <= 0)
-        goto loser; /* fatal alert already sent by ConsumeHandshake. */
-
-    if (remaining < size)
-        goto decode_loser;
-
-    certItem.data = b;
-    certItem.len = size;
-    b += size;
-    length -= size;
-    remaining -= size;
-
-    ss->sec.peerCert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL,
-                                               PR_FALSE, PR_TRUE);
-    if (ss->sec.peerCert == NULL) {
-        /* We should report an alert if the cert was bad, but not if the
-         * problem was just some local problem, like memory error.
-         */
-        goto ambiguous_err;
-    }
-
-    /* Now get all of the CA certs. */
-    while (remaining > 0) {
-        remaining -= 3;
-        if (remaining < 0)
-            goto decode_loser;
-
-        size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length);
-        if (size <= 0)
-            goto loser; /* fatal alert already sent by ConsumeHandshake. */
-
-        if (remaining < size)
-            goto decode_loser;
-
-        certItem.data = b;
-        certItem.len = size;
-        b += size;
-        length -= size;
-        remaining -= size;
-
-        c = PORT_ArenaNew(ss->ssl3.peerCertArena, ssl3CertNode);
-        if (c == NULL) {
-            goto loser; /* don't send alerts on memory errors */
-        }
-
-        c->cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL,
-                                          PR_FALSE, PR_TRUE);
-        if (c->cert == NULL) {
-            goto ambiguous_err;
-        }
-
-        c->next = NULL;
-        if (lastCert) {
-            lastCert->next = c;
-        } else {
-            ss->ssl3.peerCertChain = c;
-        }
-        lastCert = c;
-    }
-
-    if (remaining != 0)
-        goto decode_loser;
-
-    SECKEY_UpdateCertPQG(ss->sec.peerCert);
-
-    if (!isServer && ssl3_ExtensionNegotiated(ss, ssl_cert_status_xtn)) {
-        ss->ssl3.hs.ws = wait_certificate_status;
-        rv = SECSuccess;
-    } else {
-        rv = ssl3_AuthCertificate(ss); /* sets ss->ssl3.hs.ws */
-    }
-
-    return rv;
-
-ambiguous_err:
-    errCode = PORT_GetError();
-    switch (errCode) {
-        case PR_OUT_OF_MEMORY_ERROR:
-        case SEC_ERROR_BAD_DATABASE:
-        case SEC_ERROR_NO_MEMORY:
-            if (isTLS) {
-                desc = internal_error;
-                goto alert_loser;
-            }
-            goto loser;
-    }
-    ssl3_SendAlertForCertError(ss, errCode);
-    goto loser;
-
-decode_loser:
-    desc = isTLS ? decode_error : bad_certificate;
-
-alert_loser:
-    (void)SSL3_SendAlert(ss, alert_fatal, desc);
-
-loser:
-    (void)ssl_MapLowLevelError(errCode);
-    return SECFailure;
-}
-
-static SECStatus
-ssl3_AuthCertificate(sslSocket *ss)
-{
-    SECStatus rv;
-    PRBool isServer = (PRBool)(!!ss->sec.isServer);
-    int errCode;
-
-    ss->ssl3.hs.authCertificatePending = PR_FALSE;
-
-    PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
-                ssl_preinfo_all);
-    /*
-     * Ask caller-supplied callback function to validate cert chain.
-     */
-    rv = (SECStatus)(*ss->authCertificate)(ss->authCertificateArg, ss->fd,
-                                           PR_TRUE, isServer);
-    if (rv != SECSuccess) {
-        errCode = PORT_GetError();
-        if (rv != SECWouldBlock) {
-            if (ss->handleBadCert) {
-                rv = (*ss->handleBadCert)(ss->badCertArg, ss->fd);
-            }
-        }
-
-        if (rv == SECWouldBlock) {
-            if (ss->sec.isServer) {
-                errCode = SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS;
-                rv = SECFailure;
-                goto loser;
-            }
-            /* TODO(ekr@rtfm.com): Reenable for TLS 1.3 */
-            if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
-                errCode = SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION;
-                rv = SECFailure;
-                goto loser;
-            }
-
-            ss->ssl3.hs.authCertificatePending = PR_TRUE;
-            rv = SECSuccess;
-        }
-
-        if (rv != SECSuccess) {
-            ssl3_SendAlertForCertError(ss, errCode);
-            goto loser;
-        }
-    }
-
-    ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
-    ssl3_CopyPeerCertsToSID(ss->ssl3.peerCertChain, ss->sec.ci.sid);
-
-    if (!ss->sec.isServer) {
-        CERTCertificate *cert = ss->sec.peerCert;
-
-        /* set the server authentication type and size from the value
-        ** in the cert. */
-        SECKEYPublicKey *pubKey = CERT_ExtractPublicKey(cert);
-        ss->sec.authAlgorithm = ss->ssl3.hs.kea_def->signKeyType;
-        ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
-        if (pubKey) {
-            KeyType pubKeyType;
-            PRInt32 minKey;
-            /* This partly fixes Bug 124230 and may cause problems for
-             * callers which depend on the old (wrong) behavior. */
-            ss->sec.authKeyBits = SECKEY_PublicKeyStrengthInBits(pubKey);
-            pubKeyType = SECKEY_GetPublicKeyType(pubKey);
-            minKey = ss->sec.authKeyBits;
-            switch (pubKeyType) {
-                case rsaKey:
-                case rsaPssKey:
-                case rsaOaepKey:
-                    rv =
-                        NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &minKey);
-                    if (rv !=
-                        SECSuccess) {
-                        minKey =
-                            SSL_RSA_MIN_MODULUS_BITS;
-                    }
-                    break;
-                case dsaKey:
-                    rv =
-                        NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &minKey);
-                    if (rv !=
-                        SECSuccess) {
-                        minKey =
-                            SSL_DSA_MIN_P_BITS;
-                    }
-                    break;
-                case dhKey:
-                    rv =
-                        NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &minKey);
-                    if (rv !=
-                        SECSuccess) {
-                        minKey =
-                            SSL_DH_MIN_P_BITS;
-                    }
-                    break;
-                default:
-                    break;
-            }
-
-            /* Too small: not good enough. Send a fatal alert. */
-            /* We aren't checking EC here on the understanding that we only
-             * support curves we like, a decision that might need revisiting. */
-            if (ss->sec.authKeyBits < minKey) {
-                PORT_SetError(SSL_ERROR_WEAK_SERVER_CERT_KEY);
-                (void)SSL3_SendAlert(ss, alert_fatal,
-                                     ss->version >= SSL_LIBRARY_VERSION_TLS_1_0
-                                         ? insufficient_security
-                                         : illegal_parameter);
-                SECKEY_DestroyPublicKey(pubKey);
-                return SECFailure;
-            }
-            SECKEY_DestroyPublicKey(pubKey);
-            pubKey = NULL;
-        }
-
-        if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
-            TLS13_SET_HS_STATE(ss, wait_cert_verify);
-        } else {
-            /* Ephemeral suites require ServerKeyExchange. Export cipher suites
-             * with RSA key exchange also require ServerKeyExchange if the
-             * authentication key exceeds the key size limit. */
-            if (ss->ssl3.hs.kea_def->ephemeral ||
-                (ss->ssl3.hs.kea_def->is_limited &&
-                 ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_rsa &&
-                 ss->sec.authKeyBits > ss->ssl3.hs.kea_def->key_size_limit)) {
-                /* require server_key_exchange */
-                ss->ssl3.hs.ws = wait_server_key;
-            } else {
-                /* disallow server_key_exchange */
-                ss->ssl3.hs.ws = wait_cert_request;
-                /* This is static RSA key exchange so set the key bits to
-                 * auth bits. */
-                ss->sec.keaKeyBits = ss->sec.authKeyBits;
-            }
-        }
-    } else {
-        /* Server */
-        if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-            ss->ssl3.hs.ws = wait_client_key;
-        } else {
-            TLS13_SET_HS_STATE(ss, wait_cert_verify);
-        }
-    }
-
-    PORT_Assert(rv == SECSuccess);
-    if (rv != SECSuccess) {
-        errCode = SEC_ERROR_LIBRARY_FAILURE;
-        rv = SECFailure;
-        goto loser;
-    }
-
-    return rv;
-
-loser:
-    (void)ssl_MapLowLevelError(errCode);
-    return SECFailure;
-}
-
-static SECStatus ssl3_FinishHandshake(sslSocket *ss);
-
-static SECStatus
-ssl3_AlwaysFail(sslSocket *ss)
-{
-    PORT_SetError(PR_INVALID_STATE_ERROR);
-    return SECFailure;
-}
-
-/* Caller must hold 1stHandshakeLock.
-*/
-SECStatus
-ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error)
-{
-    SECStatus rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    if (ss->sec.isServer) {
-        PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS);
-        return SECFailure;
-    }
-
-    ssl_GetRecvBufLock(ss);
-    ssl_GetSSL3HandshakeLock(ss);
-
-    if (!ss->ssl3.hs.authCertificatePending) {
-        PORT_SetError(PR_INVALID_STATE_ERROR);
-        rv = SECFailure;
-        goto done;
-    }
-
-    ss->ssl3.hs.authCertificatePending = PR_FALSE;
-
-    if (error != 0) {
-        ss->ssl3.hs.restartTarget = ssl3_AlwaysFail;
-        ssl3_SendAlertForCertError(ss, error);
-        rv = SECSuccess;
-    } else if (ss->ssl3.hs.restartTarget != NULL) {
-        sslRestartTarget target = ss->ssl3.hs.restartTarget;
-        ss->ssl3.hs.restartTarget = NULL;
-
-        if (target == ssl3_FinishHandshake) {
-            SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication lost the race"
-                        " with peer's finished message",
-                        SSL_GETPID(), ss->fd));
-        }
-
-        rv = target(ss);
-        /* Even if we blocked here, we have accomplished enough to claim
-         * success. Any remaining work will be taken care of by subsequent
-         * calls to SSL_ForceHandshake/PR_Send/PR_Read/etc.
-         */
-        if (rv == SECWouldBlock) {
-            rv = SECSuccess;
-        }
-    } else {
-        SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication won the race with"
-                    " peer's finished message",
-                    SSL_GETPID(), ss->fd));
-
-        PORT_Assert(!ss->ssl3.hs.isResuming);
-        PORT_Assert(ss->ssl3.hs.ws != idle_handshake);
-
-        if (ss->opt.enableFalseStart &&
-            !ss->firstHsDone &&
-            !ss->ssl3.hs.isResuming &&
-            ssl3_WaitingForServerSecondRound(ss)) {
-            /* ssl3_SendClientSecondRound deferred the false start check because
-             * certificate authentication was pending, so we do it now if we still
-             * haven't received all of the server's second round yet.
-             */
-            rv = ssl3_CheckFalseStart(ss);
-        } else {
-            rv = SECSuccess;
-        }
-    }
-
-done:
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    ssl_ReleaseRecvBufLock(ss);
-
-    return rv;
-}
-
-static SECStatus
-ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
-                        PRBool isServer,
-                        const SSL3Hashes *hashes,
-                        TLSFinished *tlsFinished)
-{
-    SECStatus rv;
-    CK_TLS_MAC_PARAMS tls_mac_params;
-    SECItem param = { siBuffer, NULL, 0 };
-    PK11Context *prf_context;
-    unsigned int retLen;
-
-    if (!spec->master_secret || spec->bypassCiphers) {
-        const char *label = isServer ? "server finished" : "client finished";
-        unsigned int len = 15;
-
-        return ssl3_TLSPRFWithMasterSecret(spec, label, len, hashes->u.raw,
-                                           hashes->len, tlsFinished->verify_data,
-                                           sizeof tlsFinished->verify_data);
-    }
-
-    if (spec->version < SSL_LIBRARY_VERSION_TLS_1_2) {
-        tls_mac_params.prfMechanism = CKM_TLS_PRF;
-    } else {
-        tls_mac_params.prfMechanism = CKM_SHA256;
-    }
-    tls_mac_params.ulMacLength = 12;
-    tls_mac_params.ulServerOrClient = isServer ? 1 : 2;
-    param.data = (unsigned char *)&tls_mac_params;
-    param.len = sizeof(tls_mac_params);
-    prf_context = PK11_CreateContextBySymKey(CKM_TLS_MAC, CKA_SIGN,
-                                             spec->master_secret, &param);
-    if (!prf_context)
-        return SECFailure;
-
-    rv = PK11_DigestBegin(prf_context);
-    rv |= PK11_DigestOp(prf_context, hashes->u.raw, hashes->len);
-    rv |= PK11_DigestFinal(prf_context, tlsFinished->verify_data, &retLen,
-                           sizeof tlsFinished->verify_data);
-    PORT_Assert(rv != SECSuccess || retLen == sizeof tlsFinished->verify_data);
-
-    PK11_DestroyContext(prf_context, PR_TRUE);
-
-    return rv;
-}
-
-/* The calling function must acquire and release the appropriate
- * lock (e.g., ssl_GetSpecReadLock / ssl_ReleaseSpecReadLock for
- * ss->ssl3.crSpec).
- */
-SECStatus
-ssl3_TLSPRFWithMasterSecret(ssl3CipherSpec *spec, const char *label,
-                            unsigned int labelLen, const unsigned char *val, unsigned int valLen,
-                            unsigned char *out, unsigned int outLen)
-{
-    SECStatus rv = SECSuccess;
-
-    if (spec->master_secret && !spec->bypassCiphers) {
-        SECItem param = { siBuffer, NULL, 0 };
-        CK_MECHANISM_TYPE mech = CKM_TLS_PRF_GENERAL;
-        PK11Context *prf_context;
-        unsigned int retLen;
-
-        if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
-            mech = CKM_NSS_TLS_PRF_GENERAL_SHA256;
-        }
-        prf_context = PK11_CreateContextBySymKey(mech, CKA_SIGN,
-                                                 spec->master_secret, &param);
-        if (!prf_context)
-            return SECFailure;
-
-        rv = PK11_DigestBegin(prf_context);
-        rv |= PK11_DigestOp(prf_context, (unsigned char *)label, labelLen);
-        rv |= PK11_DigestOp(prf_context, val, valLen);
-        rv |= PK11_DigestFinal(prf_context, out, &retLen, outLen);
-        PORT_Assert(rv != SECSuccess || retLen == outLen);
-
-        PK11_DestroyContext(prf_context, PR_TRUE);
-    } else {
-/* bypass PKCS11 */
-#ifdef NO_PKCS11_BYPASS
-        PORT_Assert(spec->master_secret);
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        rv = SECFailure;
-#else
-        SECItem inData = { siBuffer };
-        SECItem outData = { siBuffer };
-        PRBool isFIPS = PR_FALSE;
-
-        inData.data = (unsigned char *)val;
-        inData.len = valLen;
-        outData.data = out;
-        outData.len = outLen;
-        if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
-            rv = TLS_P_hash(HASH_AlgSHA256, &spec->msItem, label, &inData,
-                            &outData, isFIPS);
-        } else {
-            rv = TLS_PRF(&spec->msItem, label, &inData, &outData, isFIPS);
-        }
-        PORT_Assert(rv != SECSuccess || outData.len == outLen);
-#endif
-    }
-    return rv;
-}
-
-/* called from ssl3_SendClientSecondRound
- *             ssl3_HandleFinished
- */
-static SECStatus
-ssl3_SendNextProto(sslSocket *ss)
-{
-    SECStatus rv;
-    int padding_len;
-    static const unsigned char padding[32] = { 0 };
-
-    if (ss->ssl3.nextProto.len == 0 ||
-        ss->ssl3.nextProtoState == SSL_NEXT_PROTO_SELECTED) {
-        return SECSuccess;
-    }
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    padding_len = 32 - ((ss->ssl3.nextProto.len + 2) % 32);
-
-    rv = ssl3_AppendHandshakeHeader(ss, next_proto, ss->ssl3.nextProto.len +
-                                                        2 +
-                                                        padding_len);
-    if (rv != SECSuccess) {
-        return rv; /* error code set by AppendHandshakeHeader */
-    }
-    rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.nextProto.data,
-                                      ss->ssl3.nextProto.len, 1);
-    if (rv != SECSuccess) {
-        return rv; /* error code set by AppendHandshake */
-    }
-    rv = ssl3_AppendHandshakeVariable(ss, padding, padding_len, 1);
-    if (rv != SECSuccess) {
-        return rv; /* error code set by AppendHandshake */
-    }
-    return rv;
-}
-
-/* called from ssl3_SendFinished
- *
- * This function is simply a debugging aid and therefore does not return a
- * SECStatus. */
-static void
-ssl3_RecordKeyLog(sslSocket *ss)
-{
-    SECStatus rv;
-    SECItem *keyData;
-    char buf[14 /* "CLIENT_RANDOM " */ +
-             SSL3_RANDOM_LENGTH * 2 /* client_random */ +
-             1 /* " " */ +
-             48 * 2 /* master secret */ +
-             1 /* new line */];
-    unsigned int j;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if (!ssl_keylog_iob)
-        return;
-
-    rv = PK11_ExtractKeyValue(ss->ssl3.cwSpec->master_secret);
-    if (rv != SECSuccess)
-        return;
-
-    ssl_GetSpecReadLock(ss);
-
-    /* keyData does not need to be freed. */
-    keyData = PK11_GetKeyData(ss->ssl3.cwSpec->master_secret);
-    if (!keyData || !keyData->data || keyData->len != 48) {
-        ssl_ReleaseSpecReadLock(ss);
-        return;
-    }
-
-    /* https://developer.mozilla.org/en/NSS_Key_Log_Format */
-
-    /* There could be multiple, concurrent writers to the
-     * keylog, so we have to do everything in a single call to
-     * fwrite. */
-
-    memcpy(buf, "CLIENT_RANDOM ", 14);
-    j = 14;
-    hexEncode(buf + j, ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH);
-    j += SSL3_RANDOM_LENGTH * 2;
-    buf[j++] = ' ';
-    hexEncode(buf + j, keyData->data, 48);
-    j += 48 * 2;
-    buf[j++] = '\n';
-
-    PORT_Assert(j == sizeof(buf));
-
-    ssl_ReleaseSpecReadLock(ss);
-
-    if (fwrite(buf, sizeof(buf), 1, ssl_keylog_iob) != 1)
-        return;
-    fflush(ssl_keylog_iob);
-    return;
-}
-
-/* called from ssl3_SendClientSecondRound
- *	     ssl3_HandleFinished
- */
-static SECStatus
-ssl3_SendChannelIDEncryptedExtensions(sslSocket *ss)
-{
-    static const char CHANNEL_ID_MAGIC[] = "TLS Channel ID signature";
-    static const char CHANNEL_ID_RESUMPTION_MAGIC[] = "Resumption";
-    /* This is the ASN.1 prefix for a P-256 public key. Specifically it's:
-     * SEQUENCE
-     *   SEQUENCE
-     *     OID id-ecPublicKey
-     *     OID prime256v1
-     *   BIT STRING, length 66, 0 trailing bits: 0x04
-     *
-     * The 0x04 in the BIT STRING is the prefix for an uncompressed, X9.62
-     * public key. Following that are the two field elements as 32-byte,
-     * big-endian numbers, as required by the Channel ID. */
-    static const unsigned char P256_SPKI_PREFIX[] = {
-        0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
-        0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
-        0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
-        0x42, 0x00, 0x04
-    };
-    /* ChannelIDs are always 128 bytes long: 64 bytes of P-256 public key and 64
-     * bytes of ECDSA signature. */
-    static const int CHANNEL_ID_PUBLIC_KEY_LENGTH = 64;
-    static const int CHANNEL_ID_LENGTH = 128;
-
-    SECStatus rv = SECFailure;
-    SECItem *spki = NULL;
-    SSL3Hashes hashes;
-    const unsigned char *pub_bytes;
-    unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) +
-                              sizeof(CHANNEL_ID_RESUMPTION_MAGIC) +
-                              sizeof(SSL3Hashes) * 2];
-    size_t signed_data_len;
-    unsigned char digest[SHA256_LENGTH];
-    SECItem digest_item;
-    unsigned char signature[64];
-    SECItem signature_item;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if (ss->ssl3.channelID == NULL)
-        return SECSuccess;
-
-    PORT_Assert(ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn));
-
-    if (SECKEY_GetPrivateKeyType(ss->ssl3.channelID) != ecKey ||
-        PK11_SignatureLen(ss->ssl3.channelID) != sizeof(signature)) {
-        PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY);
-        rv = SECFailure;
-        goto loser;
-    }
-
-    ssl_GetSpecReadLock(ss);
-    rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.cwSpec, &hashes, 0);
-    ssl_ReleaseSpecReadLock(ss);
-
-    if (rv != SECSuccess)
-        goto loser;
-
-    rv = ssl3_AppendHandshakeHeader(ss, channelid_encrypted_extensions,
-                                    2 + 2 + CHANNEL_ID_LENGTH);
-    if (rv != SECSuccess)
-        goto loser; /* error code set by AppendHandshakeHeader */
-    rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2);
-    if (rv != SECSuccess)
-        goto loser; /* error code set by AppendHandshake */
-    rv = ssl3_AppendHandshakeNumber(ss, CHANNEL_ID_LENGTH, 2);
-    if (rv != SECSuccess)
-        goto loser; /* error code set by AppendHandshake */
-
-    spki = SECKEY_EncodeDERSubjectPublicKeyInfo(ss->ssl3.channelIDPub);
-
-    if (spki->len != sizeof(P256_SPKI_PREFIX) + CHANNEL_ID_PUBLIC_KEY_LENGTH ||
-        memcmp(spki->data, P256_SPKI_PREFIX, sizeof(P256_SPKI_PREFIX)) != 0) {
-        PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY);
-        rv = SECFailure;
-        goto loser;
-    }
-
-    pub_bytes = spki->data + sizeof(P256_SPKI_PREFIX);
-
-    signed_data_len = 0;
-    memcpy(signed_data + signed_data_len, CHANNEL_ID_MAGIC,
-           sizeof(CHANNEL_ID_MAGIC));
-    signed_data_len += sizeof(CHANNEL_ID_MAGIC);
-    if (ss->ssl3.hs.isResuming) {
-        SECItem *originalHandshakeHash =
-            &ss->sec.ci.sid->u.ssl3.originalHandshakeHash;
-        PORT_Assert(originalHandshakeHash->len > 0);
-
-        memcpy(signed_data + signed_data_len, CHANNEL_ID_RESUMPTION_MAGIC,
-               sizeof(CHANNEL_ID_RESUMPTION_MAGIC));
-        signed_data_len += sizeof(CHANNEL_ID_RESUMPTION_MAGIC);
-        memcpy(signed_data + signed_data_len, originalHandshakeHash->data,
-               originalHandshakeHash->len);
-        signed_data_len += originalHandshakeHash->len;
-    }
-    memcpy(signed_data + signed_data_len, hashes.u.raw, hashes.len);
-    signed_data_len += hashes.len;
-
-    rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data, signed_data_len);
-    if (rv != SECSuccess)
-        goto loser;
-
-    digest_item.data = digest;
-    digest_item.len = sizeof(digest);
-
-    signature_item.data = signature;
-    signature_item.len = sizeof(signature);
-
-    rv = PK11_Sign(ss->ssl3.channelID, &signature_item, &digest_item);
-    if (rv != SECSuccess)
-        goto loser;
-
-    rv = ssl3_AppendHandshake(ss, pub_bytes, CHANNEL_ID_PUBLIC_KEY_LENGTH);
-    if (rv != SECSuccess)
-        goto loser;
-    rv = ssl3_AppendHandshake(ss, signature, sizeof(signature));
-
-loser:
-    if (spki)
-        SECITEM_FreeItem(spki, PR_TRUE);
-    if (ss->ssl3.channelID) {
-        SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
-        ss->ssl3.channelID = NULL;
-    }
-    if (ss->ssl3.channelIDPub) {
-        SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
-        ss->ssl3.channelIDPub = NULL;
-    }
-
-    return rv;
-}
-
-/* ssl3_RestartHandshakeAfterChannelIDReq is called to restart a handshake
- * after a ChannelID callback returned SECWouldBlock. At this point we have
- * processed the server's ServerHello but not yet any further messages. We will
- * always get a message from the server after a ServerHello so either they are
- * waiting in the buffer or we'll get network I/O. */
-SECStatus
-ssl3_RestartHandshakeAfterChannelIDReq(sslSocket *ss,
-                                       SECKEYPublicKey *channelIDPub,
-                                       SECKEYPrivateKey *channelID)
-{
-    if (ss->handshake == 0) {
-        SECKEY_DestroyPublicKey(channelIDPub);
-        SECKEY_DestroyPrivateKey(channelID);
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        return SECFailure;
-    }
-
-    if (channelIDPub == NULL ||
-        channelID == NULL) {
-        if (channelIDPub)
-            SECKEY_DestroyPublicKey(channelIDPub);
-        if (channelID)
-            SECKEY_DestroyPrivateKey(channelID);
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return SECFailure;
-    }
-
-    if (ss->ssl3.channelID)
-        SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
-    if (ss->ssl3.channelIDPub)
-        SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
-
-    ss->handshake = ssl_GatherRecord1stHandshake;
-    ss->ssl3.channelID = channelID;
-    ss->ssl3.channelIDPub = channelIDPub;
-
-    return SECSuccess;
-}
-
-/* called from ssl3_SendClientSecondRound
- *             ssl3_HandleClientHello
- *             ssl3_HandleFinished
- */
-static SECStatus
-ssl3_SendFinished(sslSocket *ss, PRInt32 flags)
-{
-    ssl3CipherSpec *cwSpec;
-    PRBool isTLS;
-    PRBool isServer = ss->sec.isServer;
-    SECStatus rv;
-    SSL3Sender sender = isServer ? sender_server : sender_client;
-    SSL3Hashes hashes;
-    TLSFinished tlsFinished;
-
-    SSL_TRC(3, ("%d: SSL3[%d]: send finished handshake", SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    ssl_GetSpecReadLock(ss);
-    cwSpec = ss->ssl3.cwSpec;
-    isTLS = (PRBool)(cwSpec->version > SSL_LIBRARY_VERSION_3_0);
-    rv = ssl3_ComputeHandshakeHashes(ss, cwSpec, &hashes, sender);
-    if (isTLS && rv == SECSuccess) {
-        rv = ssl3_ComputeTLSFinished(cwSpec, isServer, &hashes, &tlsFinished);
-    }
-    ssl_ReleaseSpecReadLock(ss);
-    if (rv != SECSuccess) {
-        goto fail; /* err code was set by ssl3_ComputeHandshakeHashes */
-    }
-
-    if (isTLS) {
-        if (isServer)
-            ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished;
-        else
-            ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished;
-        ss->ssl3.hs.finishedBytes = sizeof tlsFinished;
-        rv = ssl3_AppendHandshakeHeader(ss, finished, sizeof tlsFinished);
-        if (rv != SECSuccess)
-            goto fail; /* err set by AppendHandshake. */
-        rv = ssl3_AppendHandshake(ss, &tlsFinished, sizeof tlsFinished);
-        if (rv != SECSuccess)
-            goto fail; /* err set by AppendHandshake. */
-    } else {
-        if (isServer)
-            ss->ssl3.hs.finishedMsgs.sFinished[1] = hashes.u.s;
-        else
-            ss->ssl3.hs.finishedMsgs.sFinished[0] = hashes.u.s;
-        PORT_Assert(hashes.len == sizeof hashes.u.s);
-        ss->ssl3.hs.finishedBytes = sizeof hashes.u.s;
-        rv = ssl3_AppendHandshakeHeader(ss, finished, sizeof hashes.u.s);
-        if (rv != SECSuccess)
-            goto fail; /* err set by AppendHandshake. */
-        rv = ssl3_AppendHandshake(ss, &hashes.u.s, sizeof hashes.u.s);
-        if (rv != SECSuccess)
-            goto fail; /* err set by AppendHandshake. */
-    }
-    rv = ssl3_FlushHandshake(ss, flags);
-    if (rv != SECSuccess) {
-        goto fail; /* error code set by ssl3_FlushHandshake */
-    }
-
-    ssl3_RecordKeyLog(ss);
-
-    return SECSuccess;
-
-fail:
-    return rv;
-}
-
-/* wrap the master secret, and put it into the SID.
- * Caller holds the Spec read lock.
- */
-SECStatus
-ssl3_CacheWrappedMasterSecret(sslSocket *ss, sslSessionID *sid,
-                              ssl3CipherSpec *spec, SSL3KEAType effectiveExchKeyType)
-{
-    PK11SymKey *wrappingKey = NULL;
-    PK11SlotInfo *symKeySlot;
-    void *pwArg = ss->pkcs11PinArg;
-    SECStatus rv = SECFailure;
-    PRBool isServer = ss->sec.isServer;
-    CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
-    symKeySlot = PK11_GetSlotFromKey(spec->master_secret);
-    if (!isServer) {
-        int wrapKeyIndex;
-        int incarnation;
-
-        /* these next few functions are mere accessors and don't fail. */
-        sid->u.ssl3.masterWrapIndex = wrapKeyIndex =
-            PK11_GetCurrentWrapIndex(symKeySlot);
-        PORT_Assert(wrapKeyIndex == 0); /* array has only one entry! */
-
-        sid->u.ssl3.masterWrapSeries = incarnation =
-            PK11_GetSlotSeries(symKeySlot);
-        sid->u.ssl3.masterSlotID = PK11_GetSlotID(symKeySlot);
-        sid->u.ssl3.masterModuleID = PK11_GetModuleID(symKeySlot);
-        sid->u.ssl3.masterValid = PR_TRUE;
-        /* Get the default wrapping key, for wrapping the master secret before
-         * placing it in the SID cache entry. */
-        wrappingKey = PK11_GetWrapKey(symKeySlot, wrapKeyIndex,
-                                      CKM_INVALID_MECHANISM, incarnation,
-                                      pwArg);
-        if (wrappingKey) {
-            mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */
-        } else {
-            int keyLength;
-            /* if the wrappingKey doesn't exist, attempt to create it.
-             * Note: we intentionally ignore errors here.  If we cannot
-             * generate a wrapping key, it is not fatal to this SSL connection,
-             * but we will not be able to restart this session.
-             */
-            mechanism = PK11_GetBestWrapMechanism(symKeySlot);
-            keyLength = PK11_GetBestKeyLength(symKeySlot, mechanism);
-            /* Zero length means fixed key length algorithm, or error.
-             * It's ambiguous.
-             */
-            wrappingKey = PK11_KeyGen(symKeySlot, mechanism, NULL,
-                                      keyLength, pwArg);
-            if (wrappingKey) {
-                PK11_SetWrapKey(symKeySlot, wrapKeyIndex, wrappingKey);
-            }
-        }
-    } else {
-        /* server socket using session cache. */
-        mechanism = PK11_GetBestWrapMechanism(symKeySlot);
-        if (mechanism != CKM_INVALID_MECHANISM) {
-            wrappingKey =
-                getWrappingKey(ss, symKeySlot, effectiveExchKeyType,
-                               mechanism, pwArg);
-            if (wrappingKey) {
-                mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */
-            }
-        }
-    }
-
-    sid->u.ssl3.masterWrapMech = mechanism;
-    PK11_FreeSlot(symKeySlot);
-
-    if (wrappingKey) {
-        SECItem wmsItem;
-
-        wmsItem.data = sid->u.ssl3.keys.wrapped_master_secret;
-        wmsItem.len = sizeof sid->u.ssl3.keys.wrapped_master_secret;
-        rv = PK11_WrapSymKey(mechanism, NULL, wrappingKey,
-                             spec->master_secret, &wmsItem);
-        /* rv is examined below. */
-        sid->u.ssl3.keys.wrapped_master_secret_len = wmsItem.len;
-        PK11_FreeSymKey(wrappingKey);
-    }
-    return rv;
-}
-
-/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered
- * a complete ssl3 Finished message from the peer.
- * Caller must hold Handshake and RecvBuf locks.
- */
-static SECStatus
-ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
-                    const SSL3Hashes *hashes)
-{
-    sslSessionID *sid = ss->sec.ci.sid;
-    SECStatus rv = SECSuccess;
-    PRBool isServer = ss->sec.isServer;
-    PRBool isTLS;
-    SSL3KEAType effectiveExchKeyType;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    SSL_TRC(3, ("%d: SSL3[%d]: handle finished handshake",
-                SSL_GETPID(), ss->fd));
-
-    if (ss->ssl3.hs.ws != wait_finished) {
-        SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-        PORT_SetError(SSL_ERROR_RX_UNEXPECTED_FINISHED);
-        return SECFailure;
-    }
-
-    if (!hashes) {
-        PORT_Assert(0);
-        SSL3_SendAlert(ss, alert_fatal, internal_error);
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        return SECFailure;
-    }
-
-    isTLS = (PRBool)(ss->ssl3.crSpec->version > SSL_LIBRARY_VERSION_3_0);
-    if (isTLS) {
-        TLSFinished tlsFinished;
-
-        if (length != sizeof tlsFinished) {
-            (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
-            PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED);
-            return SECFailure;
-        }
-        rv = ssl3_ComputeTLSFinished(ss->ssl3.crSpec, !isServer,
-                                     hashes, &tlsFinished);
-        if (!isServer)
-            ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished;
-        else
-            ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished;
-        ss->ssl3.hs.finishedBytes = sizeof tlsFinished;
-        if (rv != SECSuccess ||
-            0 != NSS_SecureMemcmp(&tlsFinished, b, length)) {
-            (void)SSL3_SendAlert(ss, alert_fatal, decrypt_error);
-            PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
-            return SECFailure;
-        }
-    } else {
-        if (length != sizeof(SSL3Finished)) {
-            (void)ssl3_IllegalParameter(ss);
-            PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED);
-            return SECFailure;
-        }
-
-        if (!isServer)
-            ss->ssl3.hs.finishedMsgs.sFinished[1] = hashes->u.s;
-        else
-            ss->ssl3.hs.finishedMsgs.sFinished[0] = hashes->u.s;
-        PORT_Assert(hashes->len == sizeof hashes->u.s);
-        ss->ssl3.hs.finishedBytes = sizeof hashes->u.s;
-        if (0 != NSS_SecureMemcmp(&hashes->u.s, b, length)) {
-            (void)ssl3_HandshakeFailure(ss);
-            PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
-            return SECFailure;
-        }
-    }
-
-    ssl_GetXmitBufLock(ss); /*************************************/
-
-    if ((isServer && !ss->ssl3.hs.isResuming) ||
-        (!isServer && ss->ssl3.hs.isResuming)) {
-        PRInt32 flags = 0;
-
-        /* Send a NewSessionTicket message if the client sent us
-         * either an empty session ticket, or one that did not verify.
-         * (Note that if either of these conditions was met, then the
-         * server has sent a SessionTicket extension in the
-         * ServerHello message.)
-         */
-        if (isServer && !ss->ssl3.hs.isResuming &&
-            ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) &&
-            ssl3_KEAAllowsSessionTicket(ss->ssl3.hs.suite_def->key_exchange_alg)) {
-            /* RFC 5077 Section 3.3: "In the case of a full handshake, the
-             * server MUST verify the client's Finished message before sending
-             * the ticket." Presumably, this also means that the client's
-             * certificate, if any, must be verified beforehand too.
-             */
-            rv = ssl3_SendNewSessionTicket(ss);
-            if (rv != SECSuccess) {
-                goto xmit_loser;
-            }
-        }
-
-        rv = ssl3_SendChangeCipherSpecs(ss);
-        if (rv != SECSuccess) {
-            goto xmit_loser; /* err is set. */
-        }
-        /* If this thread is in SSL_SecureSend (trying to write some data)
-        ** then set the ssl_SEND_FLAG_FORCE_INTO_BUFFER flag, so that the
-        ** last two handshake messages (change cipher spec and finished)
-        ** will be sent in the same send/write call as the application data.
-        */
-        if (ss->writerThread == PR_GetCurrentThread()) {
-            flags = ssl_SEND_FLAG_FORCE_INTO_BUFFER;
-        }
-
-        if (!isServer) {
-            if (!ss->firstHsDone) {
-                rv = ssl3_SendNextProto(ss);
-                if (rv != SECSuccess) {
-                    goto xmit_loser; /* err code was set. */
-                }
-            }
-            rv = ssl3_SendChannelIDEncryptedExtensions(ss);
-            if (rv != SECSuccess)
-                goto xmit_loser; /* err code was set. */
-        }
-
-        if (IS_DTLS(ss)) {
-            flags |= ssl_SEND_FLAG_NO_RETRANSMIT;
-        }
-
-        rv = ssl3_SendFinished(ss, flags);
-        if (rv != SECSuccess) {
-            goto xmit_loser; /* err is set. */
-        }
-    }
-
-xmit_loser:
-    ssl_ReleaseXmitBufLock(ss); /*************************************/
-    if (rv != SECSuccess) {
-        return rv;
-    }
-
-    if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa ||
-        ss->ssl3.hs.kea_def->kea == kea_dhe_rsa) {
-        effectiveExchKeyType = kt_rsa;
-    } else {
-        effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType;
-    }
-
-    if (sid->cached == never_cached && !ss->opt.noCache && ss->sec.cache) {
-        /* fill in the sid */
-        sid->u.ssl3.cipherSuite = ss->ssl3.hs.cipher_suite;
-        sid->u.ssl3.compression = ss->ssl3.hs.compression;
-        sid->u.ssl3.policy = ss->ssl3.policy;
-#ifndef NSS_DISABLE_ECC
-        sid->u.ssl3.negotiatedECCurves = ss->ssl3.hs.negotiatedECCurves;
-#endif
-        sid->u.ssl3.exchKeyType = effectiveExchKeyType;
-        sid->version = ss->version;
-        sid->authAlgorithm = ss->sec.authAlgorithm;
-        sid->authKeyBits = ss->sec.authKeyBits;
-        sid->keaType = ss->sec.keaType;
-        sid->keaKeyBits = ss->sec.keaKeyBits;
-        sid->lastAccessTime = sid->creationTime = ssl_Time();
-        sid->expirationTime = sid->creationTime + ssl3_sid_timeout;
-        sid->localCert = CERT_DupCertificate(ss->sec.localCert);
-
-        ssl_GetSpecReadLock(ss); /*************************************/
-
-        /* Copy the master secret (wrapped or unwrapped) into the sid */
-        if (ss->ssl3.crSpec->msItem.len && ss->ssl3.crSpec->msItem.data) {
-            sid->u.ssl3.keys.wrapped_master_secret_len =
-                ss->ssl3.crSpec->msItem.len;
-            memcpy(sid->u.ssl3.keys.wrapped_master_secret,
-                   ss->ssl3.crSpec->msItem.data, ss->ssl3.crSpec->msItem.len);
-            sid->u.ssl3.masterValid = PR_TRUE;
-            sid->u.ssl3.keys.msIsWrapped = PR_FALSE;
-            rv = SECSuccess;
-        } else {
-            rv = ssl3_CacheWrappedMasterSecret(ss, ss->sec.ci.sid,
-                                               ss->ssl3.crSpec,
-                                               effectiveExchKeyType);
-            sid->u.ssl3.keys.msIsWrapped = PR_TRUE;
-        }
-        ssl_ReleaseSpecReadLock(ss); /*************************************/
-
-        /* If the wrap failed, we don't cache the sid.
-         * The connection continues normally however.
-         */
-        ss->ssl3.hs.cacheSID = rv == SECSuccess;
-    }
-
-    if (ss->ssl3.hs.authCertificatePending) {
-        if (ss->ssl3.hs.restartTarget) {
-            PR_NOT_REACHED("ssl3_HandleFinished: unexpected restartTarget");
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            return SECFailure;
-        }
-
-        ss->ssl3.hs.restartTarget = ssl3_FinishHandshake;
-        return SECWouldBlock;
-    }
-
-    rv = ssl3_FinishHandshake(ss);
-    return rv;
-}
-
-/* The return type is SECStatus instead of void because this function needs
- * to have type sslRestartTarget.
- */
-SECStatus
-ssl3_FinishHandshake(sslSocket *ss)
-{
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->ssl3.hs.restartTarget == NULL);
-
-    /* The first handshake is now completed. */
-    ss->handshake = NULL;
-
-    /* RFC 5077 Section 3.3: "The client MUST NOT treat the ticket as valid
-     * until it has verified the server's Finished message." When the server
-     * sends a NewSessionTicket in a resumption handshake, we must wait until
-     * the handshake is finished (we have verified the server's Finished
-     * AND the server's certificate) before we update the ticket in the sid.
-     *
-     * This must be done before we call (*ss->sec.cache)(ss->sec.ci.sid)
-     * because CacheSID requires the session ticket to already be set, and also
-     * because of the lazy lock creation scheme used by CacheSID and
-     * ssl3_SetSIDSessionTicket.
-     */
-    if (ss->ssl3.hs.receivedNewSessionTicket) {
-        PORT_Assert(!ss->sec.isServer);
-        ssl3_SetSIDSessionTicket(ss->sec.ci.sid, &ss->ssl3.hs.newSessionTicket);
-        /* The sid took over the ticket data */
-        PORT_Assert(!ss->ssl3.hs.newSessionTicket.ticket.data);
-        ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE;
-    }
-
-    if (ss->ssl3.hs.cacheSID && ss->sec.isServer) {
-        PORT_Assert(ss->sec.ci.sid->cached == never_cached);
-        (*ss->sec.cache)(ss->sec.ci.sid);
-        ss->ssl3.hs.cacheSID = PR_FALSE;
-    }
-
-    ss->ssl3.hs.canFalseStart = PR_FALSE; /* False Start phase is complete */
-    ss->ssl3.hs.ws = idle_handshake;
-
-    ssl_FinishHandshake(ss);
-
-    return SECSuccess;
-}
-
-/* Called from ssl3_HandleHandshake() when it has gathered a complete ssl3
- * hanshake message.
- * Caller must hold Handshake and RecvBuf locks.
- */
-SECStatus
-ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    SECStatus rv = SECSuccess;
-    SSL3HandshakeType type = ss->ssl3.hs.msg_type;
-    SSL3Hashes hashes;            /* computed hashes are put here. */
-    SSL3Hashes *hashesPtr = NULL; /* Set when hashes are computed */
-    PRUint8 hdr[4];
-    PRUint8 dtlsData[8];
-    PRBool computeHashes = PR_FALSE;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    /*
-     * We have to compute the hashes before we update them with the
-     * current message.
-     */
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        if (((type == finished) && (ss->ssl3.hs.ws == wait_finished)) ||
-            ((type == certificate_verify) &&
-             (ss->ssl3.hs.ws == wait_cert_verify))) {
-            computeHashes = PR_TRUE;
-        }
-    } else {
-        if (type == certificate_verify) {
-            computeHashes =
-                TLS13_IN_HS_STATE(ss, wait_cert_verify);
-        } else if (type == finished) {
-            computeHashes =
-                TLS13_IN_HS_STATE(ss, wait_cert_request, wait_finished);
-        }
-    }
-
-    ssl_GetSpecReadLock(ss); /************************************/
-    if (computeHashes) {
-        SSL3Sender sender = (SSL3Sender)0;
-        ssl3CipherSpec *rSpec = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 ? ss->ssl3.crSpec
-                                                                           : ss->ssl3.prSpec;
-
-        if (type == finished) {
-            sender = ss->sec.isServer ? sender_client : sender_server;
-            rSpec = ss->ssl3.crSpec;
-        }
-        rv = ssl3_ComputeHandshakeHashes(ss, rSpec, &hashes, sender);
-        if (rv == SECSuccess) {
-            hashesPtr = &hashes;
-        }
-    }
-    ssl_ReleaseSpecReadLock(ss); /************************************/
-    if (rv != SECSuccess) {
-        return rv; /* error code was set by ssl3_ComputeHandshakeHashes*/
-    }
-    SSL_TRC(30, ("%d: SSL3[%d]: handle handshake message: %s", SSL_GETPID(),
-                 ss->fd, ssl3_DecodeHandshakeType(ss->ssl3.hs.msg_type)));
-
-    hdr[0] = (PRUint8)ss->ssl3.hs.msg_type;
-    hdr[1] = (PRUint8)(length >> 16);
-    hdr[2] = (PRUint8)(length >> 8);
-    hdr[3] = (PRUint8)(length);
-
-    /* Start new handshake hashes when we start a new handshake */
-    if (ss->ssl3.hs.msg_type == client_hello) {
-        rv = ssl3_RestartHandshakeHashes(ss);
-        if (rv != SECSuccess) {
-            return rv;
-        }
-    }
-    /* We should not include hello_request and hello_verify_request messages
-     * in the handshake hashes */
-    if ((ss->ssl3.hs.msg_type != hello_request) &&
-        (ss->ssl3.hs.msg_type != hello_verify_request)) {
-        rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char *)hdr, 4);
-        if (rv != SECSuccess)
-            return rv; /* err code already set. */
-
-        /* Extra data to simulate a complete DTLS handshake fragment */
-        if (IS_DTLS(ss)) {
-            /* Sequence number */
-            dtlsData[0] = MSB(ss->ssl3.hs.recvMessageSeq);
-            dtlsData[1] = LSB(ss->ssl3.hs.recvMessageSeq);
-
-            /* Fragment offset */
-            dtlsData[2] = 0;
-            dtlsData[3] = 0;
-            dtlsData[4] = 0;
-
-            /* Fragment length */
-            dtlsData[5] = (PRUint8)(length >> 16);
-            dtlsData[6] = (PRUint8)(length >> 8);
-            dtlsData[7] = (PRUint8)(length);
-
-            rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char *)dtlsData,
-                                            sizeof(dtlsData));
-            if (rv != SECSuccess)
-                return rv; /* err code already set. */
-        }
-
-        /* The message body */
-        rv = ssl3_UpdateHandshakeHashes(ss, b, length);
-        if (rv != SECSuccess)
-            return rv; /* err code already set. */
-    }
-
-    PORT_SetError(0); /* each message starts with no error. */
-
-    if (ss->ssl3.hs.ws == wait_certificate_status &&
-        ss->ssl3.hs.msg_type != certificate_status) {
-        /* If we negotiated the certificate_status extension then we deferred
-         * certificate validation until we get the CertificateStatus messsage.
-         * But the CertificateStatus message is optional. If the server did
-         * not send it then we need to validate the certificate now. If the
-         * server does send the CertificateStatus message then we will
-         * authenticate the certificate in ssl3_HandleCertificateStatus.
-         */
-        rv = ssl3_AuthCertificate(ss); /* sets ss->ssl3.hs.ws */
-        PORT_Assert(rv != SECWouldBlock);
-        if (rv != SECSuccess) {
-            return rv;
-        }
-    }
-
-    switch (ss->ssl3.hs.msg_type) {
-        case client_hello:
-            if (!ss->sec.isServer) {
-                (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-                PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO);
-                return SECFailure;
-            }
-            rv = ssl3_HandleClientHello(ss, b, length);
-            break;
-        case server_hello:
-            if (ss->sec.isServer) {
-                (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-                PORT_SetError(SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO);
-                return SECFailure;
-            }
-            rv = ssl3_HandleServerHello(ss, b, length);
-            break;
-        default:
-            if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-                rv = ssl3_HandlePostHelloHandshakeMessage(ss, b, length, hashesPtr);
-            } else {
-                rv = tls13_HandlePostHelloHandshakeMessage(ss, b, length,
-                                                           hashesPtr);
-            }
-            break;
-    }
-
-    if (IS_DTLS(ss) && (rv != SECFailure)) {
-        /* Increment the expected sequence number */
-        ss->ssl3.hs.recvMessageSeq++;
-    }
-    return rv;
-}
-
-static SECStatus
-ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss, SSL3Opaque *b,
-                                     PRUint32 length, SSL3Hashes *hashesPtr)
-{
-    SECStatus rv;
-    PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3);
-
-    switch (ss->ssl3.hs.msg_type) {
-        case hello_request:
-            if (length != 0) {
-                (void)ssl3_DecodeError(ss);
-                PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_REQUEST);
-                return SECFailure;
-            }
-            if (ss->sec.isServer) {
-                (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-                PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST);
-                return SECFailure;
-            }
-            rv = ssl3_HandleHelloRequest(ss);
-            break;
-        case hello_verify_request:
-            if (!IS_DTLS(ss) || ss->sec.isServer) {
-                (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-                PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST);
-                return SECFailure;
-            }
-            rv = dtls_HandleHelloVerifyRequest(ss, b, length);
-            break;
-        case certificate:
-            rv = ssl3_HandleCertificate(ss, b, length);
-            break;
-        case certificate_status:
-            rv = ssl3_HandleCertificateStatus(ss, b, length);
-            break;
-        case server_key_exchange:
-            if (ss->sec.isServer) {
-                (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-                PORT_SetError(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH);
-                return SECFailure;
-            }
-            rv = ssl3_HandleServerKeyExchange(ss, b, length);
-            break;
-        case certificate_request:
-            if (ss->sec.isServer) {
-                (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-                PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST);
-                return SECFailure;
-            }
-            rv = ssl3_HandleCertificateRequest(ss, b, length);
-            break;
-        case server_hello_done:
-            if (length != 0) {
-                (void)ssl3_DecodeError(ss);
-                PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_DONE);
-                return SECFailure;
-            }
-            if (ss->sec.isServer) {
-                (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-                PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE);
-                return SECFailure;
-            }
-            rv = ssl3_HandleServerHelloDone(ss);
-            break;
-        case certificate_verify:
-            if (!ss->sec.isServer) {
-                (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-                PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY);
-                return SECFailure;
-            }
-            rv = ssl3_HandleCertificateVerify(ss, b, length, hashesPtr);
-            break;
-        case client_key_exchange:
-            if (!ss->sec.isServer) {
-                (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-                PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH);
-                return SECFailure;
-            }
-            rv = ssl3_HandleClientKeyExchange(ss, b, length);
-            break;
-        case new_session_ticket:
-            if (ss->sec.isServer) {
-                (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-                PORT_SetError(SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET);
-                return SECFailure;
-            }
-            rv = ssl3_HandleNewSessionTicket(ss, b, length);
-            break;
-        case finished:
-            rv = ssl3_HandleFinished(ss, b, length, hashesPtr);
-            break;
-        default:
-            (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-            PORT_SetError(SSL_ERROR_RX_UNKNOWN_HANDSHAKE);
-            rv = SECFailure;
-    }
-
-    return rv;
-}
-
-/* Called only from ssl3_HandleRecord, for each (deciphered) ssl3 record.
- * origBuf is the decrypted ssl record content.
- * Caller must hold the handshake and RecvBuf locks.
- */
-static SECStatus
-ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
-{
-    /*
-     * There may be a partial handshake message already in the handshake
-     * state. The incoming buffer may contain another portion, or a
-     * complete message or several messages followed by another portion.
-     *
-     * Each message is made contiguous before being passed to the actual
-     * message parser.
-     */
-    sslBuffer *buf = &ss->ssl3.hs.msgState; /* do not lose the original buffer pointer */
-    SECStatus rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if (buf->buf == NULL) {
-        *buf = *origBuf;
-    }
-    while (buf->len > 0) {
-        if (ss->ssl3.hs.header_bytes < 4) {
-            PRUint8 t;
-            t = *(buf->buf++);
-            buf->len--;
-            if (ss->ssl3.hs.header_bytes++ == 0)
-                ss->ssl3.hs.msg_type = (SSL3HandshakeType)t;
-            else
-                ss->ssl3.hs.msg_len = (ss->ssl3.hs.msg_len << 8) + t;
-            if (ss->ssl3.hs.header_bytes < 4)
-                continue;
-
-#define MAX_HANDSHAKE_MSG_LEN 0x1ffff /* 128k - 1 */
-            if (ss->ssl3.hs.msg_len > MAX_HANDSHAKE_MSG_LEN) {
-                (void)ssl3_DecodeError(ss);
-                PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
-                return SECFailure;
-            }
-#undef MAX_HANDSHAKE_MSG_LEN
-
-            /* If msg_len is zero, be sure we fall through,
-            ** even if buf->len is zero.
-            */
-            if (ss->ssl3.hs.msg_len > 0)
-                continue;
-        }
-
-        /*
-         * Header has been gathered and there is at least one byte of new
-         * data available for this message. If it can be done right out
-         * of the original buffer, then use it from there.
-         */
-        if (ss->ssl3.hs.msg_body.len == 0 && buf->len >= ss->ssl3.hs.msg_len) {
-            /* handle it from input buffer */
-            rv = ssl3_HandleHandshakeMessage(ss, buf->buf, ss->ssl3.hs.msg_len);
-            if (rv == SECFailure) {
-                /* This test wants to fall through on either
-                 * SECSuccess or SECWouldBlock.
-                 * ssl3_HandleHandshakeMessage MUST set the error code.
-                 */
-                return rv;
-            }
-            buf->buf += ss->ssl3.hs.msg_len;
-            buf->len -= ss->ssl3.hs.msg_len;
-            ss->ssl3.hs.msg_len = 0;
-            ss->ssl3.hs.header_bytes = 0;
-            if (rv != SECSuccess) { /* return if SECWouldBlock. */
-                return rv;
-            }
-        } else {
-            /* must be copied to msg_body and dealt with from there */
-            unsigned int bytes;
-
-            PORT_Assert(ss->ssl3.hs.msg_body.len < ss->ssl3.hs.msg_len);
-            bytes = PR_MIN(buf->len, ss->ssl3.hs.msg_len - ss->ssl3.hs.msg_body.len);
-
-            /* Grow the buffer if needed */
-            rv = sslBuffer_Grow(&ss->ssl3.hs.msg_body, ss->ssl3.hs.msg_len);
-            if (rv != SECSuccess) {
-                /* sslBuffer_Grow has set a memory error code. */
-                return SECFailure;
-            }
-
-            PORT_Memcpy(ss->ssl3.hs.msg_body.buf + ss->ssl3.hs.msg_body.len,
-                        buf->buf, bytes);
-            ss->ssl3.hs.msg_body.len += bytes;
-            buf->buf += bytes;
-            buf->len -= bytes;
-
-            PORT_Assert(ss->ssl3.hs.msg_body.len <= ss->ssl3.hs.msg_len);
-
-            /* if we have a whole message, do it */
-            if (ss->ssl3.hs.msg_body.len == ss->ssl3.hs.msg_len) {
-                rv = ssl3_HandleHandshakeMessage(
-                    ss, ss->ssl3.hs.msg_body.buf, ss->ssl3.hs.msg_len);
-                if (rv == SECFailure) {
-                    /* This test wants to fall through on either
-                     * SECSuccess or SECWouldBlock.
-                     * ssl3_HandleHandshakeMessage MUST set error code.
-                     */
-                    return rv;
-                }
-                ss->ssl3.hs.msg_body.len = 0;
-                ss->ssl3.hs.msg_len = 0;
-                ss->ssl3.hs.header_bytes = 0;
-                if (rv != SECSuccess) { /* return if SECWouldBlock. */
-                    return rv;
-                }
-            } else {
-                PORT_Assert(buf->len == 0);
-                break;
-            }
-        }
-    } /* end loop */
-
-    origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */
-    buf->buf = NULL;  /* not a leak. */
-    return SECSuccess;
-}
-
-/* These macros return the given value with the MSB copied to all the other
- * bits. They use the fact that arithmetic shift shifts-in the sign bit.
- * However, this is not ensured by the C standard so you may need to replace
- * them with something else for odd compilers. */
-#define DUPLICATE_MSB_TO_ALL(x) ((unsigned)((int)(x) >> (sizeof(int) * 8 - 1)))
-#define DUPLICATE_MSB_TO_ALL_8(x) ((unsigned char)(DUPLICATE_MSB_TO_ALL(x)))
-
-/* SECStatusToMask returns, in constant time, a mask value of all ones if
- * rv == SECSuccess.  Otherwise it returns zero. */
-static unsigned int
-SECStatusToMask(SECStatus rv)
-{
-    unsigned int good;
-    /* rv ^ SECSuccess is zero iff rv == SECSuccess. Subtracting one results
-     * in the MSB being set to one iff it was zero before. */
-    good = rv ^ SECSuccess;
-    good--;
-    return DUPLICATE_MSB_TO_ALL(good);
-}
-
-/* ssl_ConstantTimeGE returns 0xff if a>=b and 0x00 otherwise. */
-static unsigned char
-ssl_ConstantTimeGE(unsigned int a, unsigned int b)
-{
-    a -= b;
-    return DUPLICATE_MSB_TO_ALL(~a);
-}
-
-/* ssl_ConstantTimeEQ8 returns 0xff if a==b and 0x00 otherwise. */
-static unsigned char
-ssl_ConstantTimeEQ8(unsigned char a, unsigned char b)
-{
-    unsigned int c = a ^ b;
-    c--;
-    return DUPLICATE_MSB_TO_ALL_8(c);
-}
-
-static SECStatus
-ssl_RemoveSSLv3CBCPadding(sslBuffer *plaintext,
-                          unsigned int blockSize,
-                          unsigned int macSize)
-{
-    unsigned int paddingLength, good, t;
-    const unsigned int overhead = 1 /* padding length byte */ + macSize;
-
-    /* These lengths are all public so we can test them in non-constant
-     * time. */
-    if (overhead > plaintext->len) {
-        return SECFailure;
-    }
-
-    paddingLength = plaintext->buf[plaintext->len - 1];
-    /* SSLv3 padding bytes are random and cannot be checked. */
-    t = plaintext->len;
-    t -= paddingLength + overhead;
-    /* If len >= paddingLength+overhead then the MSB of t is zero. */
-    good = DUPLICATE_MSB_TO_ALL(~t);
-    /* SSLv3 requires that the padding is minimal. */
-    t = blockSize - (paddingLength + 1);
-    good &= DUPLICATE_MSB_TO_ALL(~t);
-    plaintext->len -= good & (paddingLength + 1);
-    return (good & SECSuccess) | (~good & SECFailure);
-}
-
-static SECStatus
-ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, unsigned int macSize)
-{
-    unsigned int paddingLength, good, t, toCheck, i;
-    const unsigned int overhead = 1 /* padding length byte */ + macSize;
-
-    /* These lengths are all public so we can test them in non-constant
-     * time. */
-    if (overhead > plaintext->len) {
-        return SECFailure;
-    }
-
-    paddingLength = plaintext->buf[plaintext->len - 1];
-    t = plaintext->len;
-    t -= paddingLength + overhead;
-    /* If len >= paddingLength+overhead then the MSB of t is zero. */
-    good = DUPLICATE_MSB_TO_ALL(~t);
-
-    /* The padding consists of a length byte at the end of the record and then
-     * that many bytes of padding, all with the same value as the length byte.
-     * Thus, with the length byte included, there are paddingLength+1 bytes of
-     * padding.
-     *
-     * We can't check just |paddingLength+1| bytes because that leaks
-     * decrypted information. Therefore we always have to check the maximum
-     * amount of padding possible. (Again, the length of the record is
-     * public information so we can use it.) */
-    toCheck = 255; /* maximum amount of padding. */
-    if (toCheck > plaintext->len - 1) {
-        toCheck = plaintext->len - 1;
-    }
-
-    for (i = 0; i < toCheck; i++) {
-        unsigned int t = paddingLength - i;
-        /* If i <= paddingLength then the MSB of t is zero and mask is
-         * 0xff.  Otherwise, mask is 0. */
-        unsigned char mask = DUPLICATE_MSB_TO_ALL(~t);
-        unsigned char b = plaintext->buf[plaintext->len - 1 - i];
-        /* The final |paddingLength+1| bytes should all have the value
-         * |paddingLength|. Therefore the XOR should be zero. */
-        good &= ~(mask & (paddingLength ^ b));
-    }
-
-    /* If any of the final |paddingLength+1| bytes had the wrong value,
-     * one or more of the lower eight bits of |good| will be cleared. We
-     * AND the bottom 8 bits together and duplicate the result to all the
-     * bits. */
-    good &= good >> 4;
-    good &= good >> 2;
-    good &= good >> 1;
-    good <<= sizeof(good) * 8 - 1;
-    good = DUPLICATE_MSB_TO_ALL(good);
-
-    plaintext->len -= good & (paddingLength + 1);
-    return (good & SECSuccess) | (~good & SECFailure);
-}
-
-/* On entry:
- *   originalLength >= macSize
- *   macSize <= MAX_MAC_LENGTH
- *   plaintext->len >= macSize
- */
-static void
-ssl_CBCExtractMAC(sslBuffer *plaintext,
-                  unsigned int originalLength,
-                  SSL3Opaque *out,
-                  unsigned int macSize)
-{
-    unsigned char rotatedMac[MAX_MAC_LENGTH];
-    /* macEnd is the index of |plaintext->buf| just after the end of the
-     * MAC. */
-    unsigned macEnd = plaintext->len;
-    unsigned macStart = macEnd - macSize;
-    /* scanStart contains the number of bytes that we can ignore because
-     * the MAC's position can only vary by 255 bytes. */
-    unsigned scanStart = 0;
-    unsigned i, j, divSpoiler;
-    unsigned char rotateOffset;
-
-    if (originalLength > macSize + 255 + 1)
-        scanStart = originalLength - (macSize + 255 + 1);
-
-    /* divSpoiler contains a multiple of macSize that is used to cause the
-     * modulo operation to be constant time. Without this, the time varies
-     * based on the amount of padding when running on Intel chips at least.
-     *
-     * The aim of right-shifting macSize is so that the compiler doesn't
-     * figure out that it can remove divSpoiler as that would require it
-     * to prove that macSize is always even, which I hope is beyond it. */
-    divSpoiler = macSize >> 1;
-    divSpoiler <<= (sizeof(divSpoiler) - 1) * 8;
-    rotateOffset = (divSpoiler + macStart - scanStart) % macSize;
-
-    memset(rotatedMac, 0, macSize);
-    for (i = scanStart; i < originalLength;) {
-        for (j = 0; j < macSize && i < originalLength; i++, j++) {
-            unsigned char macStarted = ssl_ConstantTimeGE(i, macStart);
-            unsigned char macEnded = ssl_ConstantTimeGE(i, macEnd);
-            unsigned char b = 0;
-            b = plaintext->buf[i];
-            rotatedMac[j] |= b & macStarted & ~macEnded;
-        }
-    }
-
-    /* Now rotate the MAC. If we knew that the MAC fit into a CPU cache line
-     * we could line-align |rotatedMac| and rotate in place. */
-    memset(out, 0, macSize);
-    for (i = 0; i < macSize; i++) {
-        unsigned char offset =
-            (divSpoiler + macSize - rotateOffset + i) % macSize;
-        for (j = 0; j < macSize; j++) {
-            out[j] |= rotatedMac[i] & ssl_ConstantTimeEQ8(j, offset);
-        }
-    }
-}
-
-/* Unprotect an SSL3 record and leave the result in plaintext.
- *
- * If SECFailure is returned, we:
- * 1. Set |*alert| to the alert to be sent.
- * 2. Call PORT_SetError() with an appropriate code.
- *
- * Called by ssl3_HandleRecord. Caller must hold the spec read lock.
- * Therefore, we MUST not call SSL3_SendAlert().
- *
- */
-static SECStatus
-ssl3_UnprotectRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *plaintext,
-                     SSL3AlertDescription *alert)
-{
-    ssl3CipherSpec *crSpec = ss->ssl3.crSpec;
-    const ssl3BulkCipherDef *cipher_def = crSpec->cipher_def;
-    PRBool isTLS;
-    unsigned int good;
-    unsigned int ivLen = 0;
-    SSL3ContentType rType;
-    unsigned int minLength;
-    unsigned int originalLen = 0;
-    unsigned char header[13];
-    unsigned int headerLen;
-    SSL3Opaque hash[MAX_MAC_LENGTH];
-    SSL3Opaque givenHashBuf[MAX_MAC_LENGTH];
-    SSL3Opaque *givenHash;
-    unsigned int hashBytes = MAX_MAC_LENGTH + 1;
-    SECStatus rv;
-
-    good = ~0U;
-    minLength = crSpec->mac_size;
-    if (cipher_def->type == type_block) {
-        /* CBC records have a padding length byte at the end. */
-        minLength++;
-        if (crSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
-            /* With >= TLS 1.1, CBC records have an explicit IV. */
-            minLength += cipher_def->iv_size;
-        }
-    } else if (cipher_def->type == type_aead) {
-        minLength = cipher_def->explicit_nonce_size + cipher_def->tag_size;
-    }
-
-    /* We can perform this test in variable time because the record's total
-     * length and the ciphersuite are both public knowledge. */
-    if (cText->buf->len < minLength) {
-        goto decrypt_loser;
-    }
-
-    if (cipher_def->type == type_block &&
-        crSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
-        /* Consume the per-record explicit IV. RFC 4346 Section 6.2.3.2 states
-         * "The receiver decrypts the entire GenericBlockCipher structure and
-         * then discards the first cipher block corresponding to the IV
-         * component." Instead, we decrypt the first cipher block and then
-         * discard it before decrypting the rest.
-         */
-        SSL3Opaque iv[MAX_IV_LENGTH];
-        int decoded;
-
-        ivLen = cipher_def->iv_size;
-        if (ivLen < 8 || ivLen > sizeof(iv)) {
-            *alert = internal_error;
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            return SECFailure;
-        }
-
-        PRINT_BUF(80, (ss, "IV (ciphertext):", cText->buf->buf, ivLen));
-
-        /* The decryption result is garbage, but since we just throw away
-         * the block it doesn't matter.  The decryption of the next block
-         * depends only on the ciphertext of the IV block.
-         */
-        rv = crSpec->decode(crSpec->decodeContext, iv, &decoded,
-                            sizeof(iv), cText->buf->buf, ivLen);
-
-        good &= SECStatusToMask(rv);
-    }
-
-    PRINT_BUF(80, (ss, "ciphertext:", cText->buf->buf + ivLen,
-                   cText->buf->len - ivLen));
-
-    isTLS = (PRBool)(crSpec->version > SSL_LIBRARY_VERSION_3_0);
-
-    if (isTLS && cText->buf->len - ivLen > (MAX_FRAGMENT_LENGTH + 2048)) {
-        *alert = record_overflow;
-        PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
-        return SECFailure;
-    }
-
-    rType = cText->type;
-    if (cipher_def->type == type_aead) {
-        /* XXX For many AEAD ciphers, the plaintext is shorter than the
-         * ciphertext by a fixed byte count, but it is not true in general.
-         * Each AEAD cipher should provide a function that returns the
-         * plaintext length for a given ciphertext. */
-        unsigned int decryptedLen =
-            cText->buf->len - cipher_def->explicit_nonce_size -
-            cipher_def->tag_size;
-        headerLen = ssl3_BuildRecordPseudoHeader(
-            header, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num,
-            rType, isTLS, cText->version, IS_DTLS(ss), decryptedLen);
-        PORT_Assert(headerLen <= sizeof(header));
-        rv = crSpec->aead(
-            ss->sec.isServer ? &crSpec->client : &crSpec->server,
-            PR_TRUE,                /* do decrypt */
-            plaintext->buf,         /* out */
-            (int *)&plaintext->len, /* outlen */
-            plaintext->space,       /* maxout */
-            cText->buf->buf,        /* in */
-            cText->buf->len,        /* inlen */
-            header, headerLen);
-        if (rv != SECSuccess) {
-            good = 0;
-        }
-    } else {
-        if (cipher_def->type == type_block &&
-            ((cText->buf->len - ivLen) % cipher_def->block_size) != 0) {
-            goto decrypt_loser;
-        }
-
-        /* decrypt from cText buf to plaintext. */
-        rv = crSpec->decode(
-            crSpec->decodeContext, plaintext->buf, (int *)&plaintext->len,
-            plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen);
-        if (rv != SECSuccess) {
-            goto decrypt_loser;
-        }
-
-        PRINT_BUF(80, (ss, "cleartext:", plaintext->buf, plaintext->len));
-
-        originalLen = plaintext->len;
-
-        /* If it's a block cipher, check and strip the padding. */
-        if (cipher_def->type == type_block) {
-            const unsigned int blockSize = cipher_def->block_size;
-            const unsigned int macSize = crSpec->mac_size;
-
-            if (!isTLS) {
-                good &= SECStatusToMask(ssl_RemoveSSLv3CBCPadding(
-                    plaintext, blockSize, macSize));
-            } else {
-                good &= SECStatusToMask(ssl_RemoveTLSCBCPadding(
-                    plaintext, macSize));
-            }
-        }
-
-        /* compute the MAC */
-        headerLen = ssl3_BuildRecordPseudoHeader(
-            header, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num,
-            rType, isTLS, cText->version, IS_DTLS(ss),
-            plaintext->len - crSpec->mac_size);
-        PORT_Assert(headerLen <= sizeof(header));
-        if (cipher_def->type == type_block) {
-            rv = ssl3_ComputeRecordMACConstantTime(
-                crSpec, (PRBool)(!ss->sec.isServer), header, headerLen,
-                plaintext->buf, plaintext->len, originalLen,
-                hash, &hashBytes);
-
-            ssl_CBCExtractMAC(plaintext, originalLen, givenHashBuf,
-                              crSpec->mac_size);
-            givenHash = givenHashBuf;
-
-            /* plaintext->len will always have enough space to remove the MAC
-             * because in ssl_Remove{SSLv3|TLS}CBCPadding we only adjust
-             * plaintext->len if the result has enough space for the MAC and we
-             * tested the unadjusted size against minLength, above. */
-            plaintext->len -= crSpec->mac_size;
-        } else {
-            /* This is safe because we checked the minLength above. */
-            plaintext->len -= crSpec->mac_size;
-
-            rv = ssl3_ComputeRecordMAC(
-                crSpec, (PRBool)(!ss->sec.isServer), header, headerLen,
-                plaintext->buf, plaintext->len, hash, &hashBytes);
-
-            /* We can read the MAC directly from the record because its location
-             * is public when a stream cipher is used. */
-            givenHash = plaintext->buf + plaintext->len;
-        }
-
-        good &= SECStatusToMask(rv);
-
-        if (hashBytes != (unsigned)crSpec->mac_size ||
-            NSS_SecureMemcmp(givenHash, hash, crSpec->mac_size) != 0) {
-            /* We're allowed to leak whether or not the MAC check was correct */
-            good = 0;
-        }
-    }
-
-    if (good == 0) {
-    decrypt_loser:
-        /* always log mac error, in case attacker can read server logs. */
-        PORT_SetError(SSL_ERROR_BAD_MAC_READ);
-        *alert = bad_record_mac;
-        return SECFailure;
-    }
-    return SECSuccess;
-}
-
-/* if cText is non-null, then decipher, check MAC, and decompress the
- * SSL record from cText->buf (typically gs->inbuf)
- * into databuf (typically gs->buf), and any previous contents of databuf
- * is lost.  Then handle databuf according to its SSL record type,
- * unless it's an application record.
- *
- * If cText is NULL, then the ciphertext has previously been deciphered and
- * checked, and is already sitting in databuf.  It is processed as an SSL
- * Handshake message.
- *
- * DOES NOT process the decrypted/decompressed application data.
- * On return, databuf contains the decrypted/decompressed record.
- *
- * Called from ssl3_GatherCompleteHandshake
- *             ssl3_RestartHandshakeAfterCertReq
- *
- * Caller must hold the RecvBufLock.
- *
- * This function aquires and releases the SSL3Handshake Lock, holding the
- * lock around any calls to functions that handle records other than
- * Application Data records.
- */
-SECStatus
-ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
-{
-    SECStatus rv;
-    PRBool isTLS;
-    PRUint64 dtls_seq_num = 0;
-    ssl3CipherSpec *crSpec;
-    SSL3ContentType rType;
-    sslBuffer *plaintext;
-    sslBuffer temp_buf;
-    SSL3AlertDescription alert;
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-
-    if (!ss->ssl3.initialized) {
-        ssl_GetSSL3HandshakeLock(ss);
-        rv = ssl3_InitState(ss);
-        ssl_ReleaseSSL3HandshakeLock(ss);
-        if (rv != SECSuccess) {
-            return rv; /* ssl3_InitState has set the error code. */
-        }
-    }
-
-    /* check for Token Presence */
-    if (!ssl3_ClientAuthTokenPresent(ss->sec.ci.sid)) {
-        PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
-        return SECFailure;
-    }
-
-    /* cText is NULL when we're called from ssl3_RestartHandshakeAfterXXX().
-     * This implies that databuf holds a previously deciphered SSL Handshake
-     * message.
-     */
-    if (cText == NULL) {
-        SSL_DBG(("%d: SSL3[%d]: HandleRecord, resuming handshake",
-                 SSL_GETPID(), ss->fd));
-        rType = content_handshake;
-        goto process_it;
-    }
-
-    ssl_GetSpecReadLock(ss); /******************************************/
-    crSpec = ss->ssl3.crSpec;
-    isTLS = (PRBool)(crSpec->version > SSL_LIBRARY_VERSION_3_0);
-
-    if (IS_DTLS(ss)) {
-        if (!dtls_IsRelevant(ss, crSpec, cText, &dtls_seq_num)) {
-            ssl_ReleaseSpecReadLock(ss);
-            /* Silently drop the packet */
-            databuf->len = 0; /* Needed to ensure data not left around */
-            return SECSuccess;
-        }
-    }
-
-    /* If we will be decompressing the buffer we need to decrypt somewhere
-     * other than into databuf */
-    if (crSpec->decompressor) {
-        temp_buf.buf = NULL;
-        temp_buf.space = 0;
-        plaintext = &temp_buf;
-    } else {
-        plaintext = databuf;
-    }
-
-    plaintext->len = 0; /* filled in by Unprotect call below. */
-    if (plaintext->space < MAX_FRAGMENT_LENGTH) {
-        rv = sslBuffer_Grow(plaintext, MAX_FRAGMENT_LENGTH + 2048);
-        if (rv != SECSuccess) {
-            ssl_ReleaseSpecReadLock(ss);
-            SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes",
-                     SSL_GETPID(), ss->fd, MAX_FRAGMENT_LENGTH + 2048));
-            /* sslBuffer_Grow has set a memory error code. */
-            /* Perhaps we should send an alert. (but we have no memory!) */
-            return SECFailure;
-        }
-    }
-
-    /* IMPORTANT: Unprotect functions MUST NOT send alerts
-     * because we still hold the spec read lock. Instead, if they
-     * return SECFailure, they set *alert to the alert to be sent. */
-    if (crSpec->version < SSL_LIBRARY_VERSION_TLS_1_3 ||
-        crSpec->cipher_def->calg == ssl_calg_null) {
-        /* Unencrypted TLS 1.3 records use the pre-TLS 1.3 format. */
-        rv = ssl3_UnprotectRecord(ss, cText, plaintext, &alert);
-    } else {
-        rv = tls13_UnprotectRecord(ss, cText, plaintext, &alert);
-    }
-
-    if (rv != SECSuccess) {
-        ssl_ReleaseSpecReadLock(ss);
-
-        SSL_DBG(("%d: SSL3[%d]: decryption failed", SSL_GETPID(), ss->fd));
-
-        if (!IS_DTLS(ss)) {
-            int errCode = PORT_GetError();
-            SSL3_SendAlert(ss, alert_fatal, alert);
-            /* Reset the error code in case SSL3_SendAlert called
-             * PORT_SetError(). */
-            PORT_SetError(errCode);
-            return SECFailure;
-        } else {
-            /* Silently drop the packet */
-            databuf->len = 0; /* Needed to ensure data not left around */
-            return SECSuccess;
-        }
-    }
-
-    /* SECSuccess */
-    if (!IS_DTLS(ss)) {
-        ssl3_BumpSequenceNumber(&crSpec->read_seq_num);
-    } else {
-        dtls_RecordSetRecvd(&crSpec->recvdRecords, dtls_seq_num);
-    }
-
-    ssl_ReleaseSpecReadLock(ss); /*****************************************/
-
-    /*
-     * The decrypted data is now in plaintext.
-     */
-    rType = cText->type; /* This must go after decryption because TLS 1.3
-                          * has encrypted content types. */
-
-    /* possibly decompress the record. If we aren't using compression then
-     * plaintext == databuf and so the uncompressed data is already in
-     * databuf. */
-    if (crSpec->decompressor) {
-        if (databuf->space < plaintext->len + SSL3_COMPRESSION_MAX_EXPANSION) {
-            rv = sslBuffer_Grow(
-                databuf, plaintext->len + SSL3_COMPRESSION_MAX_EXPANSION);
-            if (rv != SECSuccess) {
-                SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes",
-                         SSL_GETPID(), ss->fd,
-                         plaintext->len +
-                             SSL3_COMPRESSION_MAX_EXPANSION));
-                /* sslBuffer_Grow has set a memory error code. */
-                /* Perhaps we should send an alert. (but we have no memory!) */
-                PORT_Free(plaintext->buf);
-                return SECFailure;
-            }
-        }
-
-        rv = crSpec->decompressor(crSpec->decompressContext,
-                                  databuf->buf,
-                                  (int *)&databuf->len,
-                                  databuf->space,
-                                  plaintext->buf,
-                                  plaintext->len);
-
-        if (rv != SECSuccess) {
-            int err = ssl_MapLowLevelError(SSL_ERROR_DECOMPRESSION_FAILURE);
-            SSL3_SendAlert(ss, alert_fatal,
-                           isTLS ? decompression_failure
-                                 : bad_record_mac);
-
-            /* There appears to be a bug with (at least) Apache + OpenSSL where
-             * resumed SSLv3 connections don't actually use compression. See
-             * comments 93-95 of
-             * https://bugzilla.mozilla.org/show_bug.cgi?id=275744
-             *
-             * So, if we get a decompression error, and the record appears to
-             * be already uncompressed, then we return a more specific error
-             * code to hopefully save somebody some debugging time in the
-             * future.
-             */
-            if (plaintext->len >= 4) {
-                unsigned int len = ((unsigned int)plaintext->buf[1] << 16) |
-                                   ((unsigned int)plaintext->buf[2] << 8) |
-                                   (unsigned int)plaintext->buf[3];
-                if (len == plaintext->len - 4) {
-                    /* This appears to be uncompressed already */
-                    err = SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD;
-                }
-            }
-
-            PORT_Free(plaintext->buf);
-            PORT_SetError(err);
-            return SECFailure;
-        }
-
-        PORT_Free(plaintext->buf);
-    }
-
-    /*
-    ** Having completed the decompression, check the length again.
-    */
-    if (isTLS && databuf->len > (MAX_FRAGMENT_LENGTH + 1024)) {
-        SSL3_SendAlert(ss, alert_fatal, record_overflow);
-        PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
-        return SECFailure;
-    }
-
-    /* Application data records are processed by the caller of this
-    ** function, not by this function.
-    */
-    if (rType == content_application_data) {
-        if (ss->firstHsDone)
-            return SECSuccess;
-        (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-        PORT_SetError(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA);
-        return SECFailure;
-    }
-
-    /* It's a record that must be handled by ssl itself, not the application.
-    */
-process_it:
-    /* XXX  Get the xmit lock here.  Odds are very high that we'll be xmiting
-     * data ang getting the xmit lock here prevents deadlocks.
-     */
-    ssl_GetSSL3HandshakeLock(ss);
-
-    /* All the functions called in this switch MUST set error code if
-    ** they return SECFailure or SECWouldBlock.
-    */
-    switch (rType) {
-        case content_change_cipher_spec:
-            rv = ssl3_HandleChangeCipherSpecs(ss, databuf);
-            break;
-        case content_alert:
-            rv = ssl3_HandleAlert(ss, databuf);
-            break;
-        case content_handshake:
-            if (!IS_DTLS(ss)) {
-                rv = ssl3_HandleHandshake(ss, databuf);
-            } else {
-                rv = dtls_HandleHandshake(ss, databuf);
-            }
-            break;
-        /*
-        case content_application_data is handled before this switch
-        */
-        default:
-            SSL_DBG(("%d: SSL3[%d]: bogus content type=%d",
-                     SSL_GETPID(), ss->fd, cText->type));
-            /* XXX Send an alert ???  */
-            PORT_SetError(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE);
-            rv = SECFailure;
-            break;
-    }
-
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    return rv;
-}
-
-/*
- * Initialization functions
- */
-
-/* Called from ssl3_InitState, immediately below. */
-/* Caller must hold the SpecWriteLock. */
-static void
-ssl3_InitCipherSpec(sslSocket *ss, ssl3CipherSpec *spec)
-{
-    spec->cipher_def = &bulk_cipher_defs[cipher_null];
-    PORT_Assert(spec->cipher_def->cipher == cipher_null);
-    spec->mac_def = &mac_defs[mac_null];
-    PORT_Assert(spec->mac_def->mac == mac_null);
-    spec->encode = Null_Cipher;
-    spec->decode = Null_Cipher;
-    spec->destroy = NULL;
-    spec->compressor = NULL;
-    spec->decompressor = NULL;
-    spec->destroyCompressContext = NULL;
-    spec->destroyDecompressContext = NULL;
-    spec->mac_size = 0;
-    spec->master_secret = NULL;
-    spec->bypassCiphers = PR_FALSE;
-
-    spec->msItem.data = NULL;
-    spec->msItem.len = 0;
-
-    spec->client.write_key = NULL;
-    spec->client.write_mac_key = NULL;
-    spec->client.write_mac_context = NULL;
-
-    spec->server.write_key = NULL;
-    spec->server.write_mac_key = NULL;
-    spec->server.write_mac_context = NULL;
-
-    spec->write_seq_num.high = 0;
-    spec->write_seq_num.low = 0;
-
-    spec->read_seq_num.high = 0;
-    spec->read_seq_num.low = 0;
-
-    spec->epoch = 0;
-    dtls_InitRecvdRecords(&spec->recvdRecords);
-
-    spec->version = ss->vrange.max;
-}
-
-/* Called from: ssl3_SendRecord
-**      ssl3_StartHandshakeHash() <- ssl2_BeginClientHandshake()
-**      ssl3_SendClientHello()
-**      ssl3_HandleV2ClientHello()
-**      ssl3_HandleRecord()
-**
-** This function should perhaps acquire and release the SpecWriteLock.
-**
-**
-*/
-static SECStatus
-ssl3_InitState(sslSocket *ss)
-{
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if (ss->ssl3.initialized)
-        return SECSuccess; /* Function should be idempotent */
-
-    ss->ssl3.policy = SSL_ALLOWED;
-
-    ssl_GetSpecWriteLock(ss);
-    ss->ssl3.crSpec = ss->ssl3.cwSpec = &ss->ssl3.specs[0];
-    ss->ssl3.prSpec = ss->ssl3.pwSpec = &ss->ssl3.specs[1];
-    ss->ssl3.hs.sendingSCSV = PR_FALSE;
-    ssl3_InitCipherSpec(ss, ss->ssl3.crSpec);
-    ssl3_InitCipherSpec(ss, ss->ssl3.prSpec);
-    ss->ssl3.hs.preliminaryInfo = 0;
-
-    ss->ssl3.hs.ws = (ss->sec.isServer) ? wait_client_hello : wait_server_hello;
-#ifndef NSS_DISABLE_ECC
-    ss->ssl3.hs.negotiatedECCurves = ssl3_GetSupportedECCurveMask(ss);
-#endif
-    ssl_ReleaseSpecWriteLock(ss);
-
-    PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData));
-
-    if (IS_DTLS(ss)) {
-        ss->ssl3.hs.sendMessageSeq = 0;
-        ss->ssl3.hs.recvMessageSeq = 0;
-        ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
-        ss->ssl3.hs.rtRetries = 0;
-        ss->ssl3.hs.recvdHighWater = -1;
-        PR_INIT_CLIST(&ss->ssl3.hs.lastMessageFlight);
-        dtls_SetMTU(ss, 0); /* Set the MTU to the highest plateau */
-    }
-
-    PR_INIT_CLIST(&ss->ssl3.hs.remoteKeyShares);
-    ss->ssl3.hs.xSS = NULL;
-    ss->ssl3.hs.xES = NULL;
-    ss->ssl3.hs.trafficSecret = NULL;
-    ss->ssl3.hs.clientFinishedSecret = NULL;
-    ss->ssl3.hs.serverFinishedSecret = NULL;
-    ss->ssl3.hs.certReqContextLen = 0;
-
-    PORT_Assert(!ss->ssl3.hs.messages.buf && !ss->ssl3.hs.messages.space);
-    ss->ssl3.hs.messages.buf = NULL;
-    ss->ssl3.hs.messages.space = 0;
-
-    ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE;
-    PORT_Memset(&ss->ssl3.hs.newSessionTicket, 0,
-                sizeof(ss->ssl3.hs.newSessionTicket));
-
-    ss->ssl3.initialized = PR_TRUE;
-    return SECSuccess;
-}
-
-/* Returns a reference counted object that contains a key pair.
- * Or NULL on failure.  Initial ref count is 1.
- * Uses the keys in the pair as input.
- */
-ssl3KeyPair *
-ssl3_NewKeyPair(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey)
-{
-    ssl3KeyPair *pair;
-
-    if (!privKey || !pubKey) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return NULL;
-    }
-    pair = PORT_ZNew(ssl3KeyPair);
-    if (!pair)
-        return NULL; /* error code is set. */
-    pair->refCount = 1;
-    pair->privKey = privKey;
-    pair->pubKey = pubKey;
-    return pair; /* success */
-}
-
-ssl3KeyPair *
-ssl3_GetKeyPairRef(ssl3KeyPair *keyPair)
-{
-    PR_ATOMIC_INCREMENT(&keyPair->refCount);
-    return keyPair;
-}
-
-void
-ssl3_FreeKeyPair(ssl3KeyPair *keyPair)
-{
-    PRInt32 newCount = PR_ATOMIC_DECREMENT(&keyPair->refCount);
-    if (!newCount) {
-        if (keyPair->privKey)
-            SECKEY_DestroyPrivateKey(keyPair->privKey);
-        if (keyPair->pubKey)
-            SECKEY_DestroyPublicKey(keyPair->pubKey);
-        PORT_Free(keyPair);
-    }
-}
-
-/*
- * Creates the public and private RSA keys for SSL Step down.
- * Called from SSL_ConfigSecureServer in sslsecur.c
- */
-SECStatus
-ssl3_CreateRSAStepDownKeys(sslSocket *ss)
-{
-    SECStatus rv = SECSuccess;
-    SECKEYPrivateKey *privKey; /* RSA step down key */
-    SECKEYPublicKey *pubKey;   /* RSA step down key */
-
-    if (ss->stepDownKeyPair)
-        ssl3_FreeKeyPair(ss->stepDownKeyPair);
-    ss->stepDownKeyPair = NULL;
-#ifndef HACKED_EXPORT_SERVER
-    /* Sigh, should have a get key strength call for private keys */
-    if (PK11_GetPrivateModulusLen(ss->serverCerts[kt_rsa].SERVERKEY) >
-        EXPORT_RSA_KEY_LENGTH) {
-        /* need to ask for the key size in bits */
-        privKey = SECKEY_CreateRSAPrivateKey(EXPORT_RSA_KEY_LENGTH * BPB,
-                                             &pubKey, NULL);
-        if (!privKey || !pubKey ||
-            !(ss->stepDownKeyPair = ssl3_NewKeyPair(privKey, pubKey))) {
-            ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
-            rv = SECFailure;
-        }
-    }
-#endif
-    return rv;
-}
-
-/* record the export policy for this cipher suite */
-SECStatus
-ssl3_SetPolicy(ssl3CipherSuite which, int policy)
-{
-    ssl3CipherSuiteCfg *suite;
-
-    suite = ssl_LookupCipherSuiteCfg(which, cipherSuites);
-    if (suite == NULL) {
-        return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */
-    }
-    suite->policy = policy;
-
-    return SECSuccess;
-}
-
-SECStatus
-ssl3_GetPolicy(ssl3CipherSuite which, PRInt32 *oPolicy)
-{
-    ssl3CipherSuiteCfg *suite;
-    PRInt32 policy;
-    SECStatus rv;
-
-    suite = ssl_LookupCipherSuiteCfg(which, cipherSuites);
-    if (suite) {
-        policy = suite->policy;
-        rv = SECSuccess;
-    } else {
-        policy = SSL_NOT_ALLOWED;
-        rv = SECFailure; /* err code was set by Lookup. */
-    }
-    *oPolicy = policy;
-    return rv;
-}
-
-/* record the user preference for this suite */
-SECStatus
-ssl3_CipherPrefSetDefault(ssl3CipherSuite which, PRBool enabled)
-{
-    ssl3CipherSuiteCfg *suite;
-
-    suite = ssl_LookupCipherSuiteCfg(which, cipherSuites);
-    if (suite == NULL) {
-        return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */
-    }
-    suite->enabled = enabled;
-    return SECSuccess;
-}
-
-/* return the user preference for this suite */
-SECStatus
-ssl3_CipherPrefGetDefault(ssl3CipherSuite which, PRBool *enabled)
-{
-    ssl3CipherSuiteCfg *suite;
-    PRBool pref;
-    SECStatus rv;
-
-    suite = ssl_LookupCipherSuiteCfg(which, cipherSuites);
-    if (suite) {
-        pref = suite->enabled;
-        rv = SECSuccess;
-    } else {
-        pref = SSL_NOT_ALLOWED;
-        rv = SECFailure; /* err code was set by Lookup. */
-    }
-    *enabled = pref;
-    return rv;
-}
-
-SECStatus
-ssl3_CipherPrefSet(sslSocket *ss, ssl3CipherSuite which, PRBool enabled)
-{
-    ssl3CipherSuiteCfg *suite;
-
-    suite = ssl_LookupCipherSuiteCfg(which, ss->cipherSuites);
-    if (suite == NULL) {
-        return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */
-    }
-    suite->enabled = enabled;
-    return SECSuccess;
-}
-
-SECStatus
-ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *enabled)
-{
-    ssl3CipherSuiteCfg *suite;
-    PRBool pref;
-    SECStatus rv;
-
-    suite = ssl_LookupCipherSuiteCfg(which, ss->cipherSuites);
-    if (suite) {
-        pref = suite->enabled;
-        rv = SECSuccess;
-    } else {
-        pref = SSL_NOT_ALLOWED;
-        rv = SECFailure; /* err code was set by Lookup. */
-    }
-    *enabled = pref;
-    return rv;
-}
-
-SECStatus
-SSL_SignaturePrefSet(PRFileDesc *fd, const SSLSignatureAndHashAlg *algorithms,
-                     unsigned int count)
-{
-    sslSocket *ss;
-    unsigned int i;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SignaturePrefSet",
-                 SSL_GETPID(), fd));
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    if (!count || count > MAX_SIGNATURE_ALGORITHMS) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    ss->ssl3.signatureAlgorithmCount = 0;
-    for (i = 0; i < count; ++i) {
-        if (!ssl3_IsSupportedSignatureAlgorithm(&algorithms[i])) {
-            SSL_DBG(("%d: SSL[%d]: invalid signature algorithm set %d/%d",
-                     SSL_GETPID(), fd, algorithms[i].sigAlg,
-                     algorithms[i].hashAlg));
-            continue;
-        }
-
-        ss->ssl3.signatureAlgorithms[ss->ssl3.signatureAlgorithmCount++] =
-            algorithms[i];
-    }
-
-    if (ss->ssl3.signatureAlgorithmCount == 0) {
-        PORT_SetError(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM);
-        return SECFailure;
-    }
-    return SECSuccess;
-}
-
-SECStatus
-SSL_SignaturePrefGet(PRFileDesc *fd, SSLSignatureAndHashAlg *algorithms,
-                     unsigned int *count, unsigned int maxCount)
-{
-    sslSocket *ss;
-    unsigned int requiredSpace;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SignaturePrefGet",
-                 SSL_GETPID(), fd));
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    if (!algorithms || !count ||
-        maxCount < ss->ssl3.signatureAlgorithmCount) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    requiredSpace =
-        ss->ssl3.signatureAlgorithmCount * sizeof(SSLSignatureAndHashAlg);
-    PORT_Memcpy(algorithms, ss->ssl3.signatureAlgorithms, requiredSpace);
-    *count = ss->ssl3.signatureAlgorithmCount;
-    return SECSuccess;
-}
-
-unsigned int
-SSL_SignatureMaxCount()
-{
-    return MAX_SIGNATURE_ALGORITHMS;
-}
-
-SECStatus
-ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *ciphers, unsigned int len)
-{
-    /* |i| iterates over |ciphers| while |done| and |j| iterate over
-     * |ss->cipherSuites|. */
-    unsigned int i, done;
-
-    for (i = done = 0; i < len; i++) {
-        PRUint16 id = ciphers[i];
-        unsigned int existingIndex, j;
-        PRBool found = PR_FALSE;
-
-        for (j = done; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
-            if (ss->cipherSuites[j].cipher_suite == id) {
-                existingIndex = j;
-                found = PR_TRUE;
-                break;
-            }
-        }
-
-        if (!found) {
-            continue;
-        }
-
-        if (existingIndex != done) {
-            const ssl3CipherSuiteCfg temp = ss->cipherSuites[done];
-            ss->cipherSuites[done] = ss->cipherSuites[existingIndex];
-            ss->cipherSuites[existingIndex] = temp;
-        }
-        done++;
-    }
-
-    /* Disable all cipher suites that weren't included. */
-    for (; done < ssl_V3_SUITES_IMPLEMENTED; done++) {
-        ss->cipherSuites[done].enabled = 0;
-    }
-
-    return SECSuccess;
-}
-
-/* copy global default policy into socket. */
-void
-ssl3_InitSocketPolicy(sslSocket *ss)
-{
-    PORT_Memcpy(ss->cipherSuites, cipherSuites, sizeof cipherSuites);
-    PORT_Memcpy(ss->ssl3.signatureAlgorithms, defaultSignatureAlgorithms,
-                sizeof(defaultSignatureAlgorithms));
-    ss->ssl3.signatureAlgorithmCount = PR_ARRAY_SIZE(defaultSignatureAlgorithms);
-}
-
-SECStatus
-ssl3_GetTLSUniqueChannelBinding(sslSocket *ss,
-                                unsigned char *out,
-                                unsigned int *outLen,
-                                unsigned int outLenMax)
-{
-    PRBool isTLS;
-    int index = 0;
-    unsigned int len;
-    SECStatus rv = SECFailure;
-
-    *outLen = 0;
-
-    ssl_GetSSL3HandshakeLock(ss);
-
-    ssl_GetSpecReadLock(ss);
-    isTLS = (PRBool)(ss->ssl3.cwSpec->version > SSL_LIBRARY_VERSION_3_0);
-    ssl_ReleaseSpecReadLock(ss);
-
-    /* The tls-unique channel binding is the first Finished structure in the
-     * handshake. In the case of a resumption, that's the server's Finished.
-     * Otherwise, it's the client's Finished. */
-    len = ss->ssl3.hs.finishedBytes;
-
-    /* Sending or receiving a Finished message will set finishedBytes to a
-     * non-zero value. */
-    if (len == 0) {
-        PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
-        goto loser;
-    }
-
-    /* If we are in the middle of a renegotiation then the channel binding
-     * value is poorly defined and depends on the direction that it will be
-     * used on. Therefore we simply return an error in this case. */
-    if (ss->firstHsDone && ss->ssl3.hs.ws != idle_handshake) {
-        PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
-        goto loser;
-    }
-
-    /* If resuming, then we want the second Finished value in the array, which
-     * is the server's */
-    if (ss->ssl3.hs.isResuming)
-        index = 1;
-
-    *outLen = len;
-    if (outLenMax < len) {
-        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
-        goto loser;
-    }
-
-    if (isTLS) {
-        memcpy(out, &ss->ssl3.hs.finishedMsgs.tFinished[index], len);
-    } else {
-        memcpy(out, &ss->ssl3.hs.finishedMsgs.sFinished[index], len);
-    }
-
-    rv = SECSuccess;
-
-loser:
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    return rv;
-}
-
-/* ssl3_config_match_init must have already been called by
- * the caller of this function.
- */
-SECStatus
-ssl3_ConstructV2CipherSpecsHack(sslSocket *ss, unsigned char *cs, int *size)
-{
-    int i, count = 0;
-
-    PORT_Assert(ss != 0);
-    if (!ss) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return SECFailure;
-    }
-    if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
-        *size = 0;
-        return SECSuccess;
-    }
-    if (cs == NULL) {
-        *size = count_cipher_suites(ss, SSL_ALLOWED, PR_TRUE);
-        return SECSuccess;
-    }
-
-    /* ssl3_config_match_init was called by the caller of this function. */
-    for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
-        ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
-        if (config_match(suite, SSL_ALLOWED, PR_TRUE, &ss->vrange, ss)) {
-            if (cs != NULL) {
-                *cs++ = 0x00;
-                *cs++ = (suite->cipher_suite >> 8) & 0xFF;
-                *cs++ = suite->cipher_suite & 0xFF;
-            }
-            count++;
-        }
-    }
-    *size = count;
-    return SECSuccess;
-}
-
-/*
-** If ssl3 socket has completed the first handshake, and is in idle state,
-** then start a new handshake.
-** If flushCache is true, the SID cache will be flushed first, forcing a
-** "Full" handshake (not a session restart handshake), to be done.
-**
-** called from SSL_RedoHandshake(), which already holds the handshake locks.
-*/
-SECStatus
-ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache)
-{
-    sslSessionID *sid = ss->sec.ci.sid;
-    SECStatus rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if (!ss->firstHsDone ||
-        ((ss->version >= SSL_LIBRARY_VERSION_3_0) &&
-         ss->ssl3.initialized &&
-         (ss->ssl3.hs.ws != idle_handshake))) {
-        PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
-        return SECFailure;
-    }
-
-    if (IS_DTLS(ss)) {
-        dtls_RehandshakeCleanup(ss);
-    }
-
-    if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) {
-        PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
-        return SECFailure;
-    }
-    if (sid && flushCache) {
-        if (ss->sec.uncache)
-            ss->sec.uncache(sid); /* remove it from whichever cache it's in. */
-        ssl_FreeSID(sid);         /* dec ref count and free if zero. */
-        ss->sec.ci.sid = NULL;
-    }
-
-    ssl_GetXmitBufLock(ss); /**************************************/
-
-    /* start off a new handshake. */
-    rv = (ss->sec.isServer) ? ssl3_SendHelloRequest(ss)
-                            : ssl3_SendClientHello(ss, PR_FALSE);
-
-    ssl_ReleaseXmitBufLock(ss); /**************************************/
-    return rv;
-}
-
-/* Called from ssl_DestroySocketContents() in sslsock.c */
-void
-ssl3_DestroySSL3Info(sslSocket *ss)
-{
-
-    if (ss->ssl3.clientCertificate != NULL)
-        CERT_DestroyCertificate(ss->ssl3.clientCertificate);
-
-    if (ss->ssl3.clientPrivateKey != NULL)
-        SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
-
-    if (ss->ssl3.channelID)
-        SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
-    if (ss->ssl3.channelIDPub)
-        SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
-
-    if (ss->ssl3.peerCertArena != NULL)
-        ssl3_CleanupPeerCerts(ss);
-
-    if (ss->ssl3.clientCertChain != NULL) {
-        CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
-        ss->ssl3.clientCertChain = NULL;
-    }
-
-/* clean up handshake */
-#ifndef NO_PKCS11_BYPASS
-    if (ss->opt.bypassPKCS11) {
-        if (ss->ssl3.hs.hashType == handshake_hash_combo) {
-            SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE);
-            MD5_DestroyContext((MD5Context *)ss->ssl3.hs.md5_cx, PR_FALSE);
-        } else if (ss->ssl3.hs.hashType == handshake_hash_single) {
-            ss->ssl3.hs.sha_obj->destroy(ss->ssl3.hs.sha_cx, PR_FALSE);
-        }
-    }
-#endif
-    if (ss->ssl3.hs.md5) {
-        PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
-    }
-    if (ss->ssl3.hs.sha) {
-        PK11_DestroyContext(ss->ssl3.hs.sha, PR_TRUE);
-    }
-    if (ss->ssl3.hs.clientSigAndHash) {
-        PORT_Free(ss->ssl3.hs.clientSigAndHash);
-    }
-    if (ss->ssl3.hs.messages.buf) {
-        PORT_Free(ss->ssl3.hs.messages.buf);
-        ss->ssl3.hs.messages.buf = NULL;
-        ss->ssl3.hs.messages.len = 0;
-        ss->ssl3.hs.messages.space = 0;
-    }
-
-    /* free the SSL3Buffer (msg_body) */
-    PORT_Free(ss->ssl3.hs.msg_body.buf);
-
-    SECITEM_FreeItem(&ss->ssl3.hs.newSessionTicket.ticket, PR_FALSE);
-
-    /* free up the CipherSpecs */
-    ssl3_DestroyCipherSpec(&ss->ssl3.specs[0], PR_TRUE /*freeSrvName*/);
-    ssl3_DestroyCipherSpec(&ss->ssl3.specs[1], PR_TRUE /*freeSrvName*/);
-
-    /* Destroy the DTLS data */
-    if (IS_DTLS(ss)) {
-        dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
-        if (ss->ssl3.hs.recvdFragments.buf) {
-            PORT_Free(ss->ssl3.hs.recvdFragments.buf);
-        }
-    }
-
-    /* Destroy TLS 1.3 handshake shares */
-    tls13_DestroyKeyShares(&ss->ssl3.hs.remoteKeyShares);
-
-    /* Destroy TLS 1.3 keys */
-    if (ss->ssl3.hs.xSS)
-        PK11_FreeSymKey(ss->ssl3.hs.xSS);
-    if (ss->ssl3.hs.xES)
-        PK11_FreeSymKey(ss->ssl3.hs.xES);
-    if (ss->ssl3.hs.trafficSecret)
-        PK11_FreeSymKey(ss->ssl3.hs.trafficSecret);
-    if (ss->ssl3.hs.clientFinishedSecret)
-        PK11_FreeSymKey(ss->ssl3.hs.clientFinishedSecret);
-    if (ss->ssl3.hs.serverFinishedSecret)
-        PK11_FreeSymKey(ss->ssl3.hs.serverFinishedSecret);
-
-    if (ss->ssl3.dheGroups) {
-        PORT_Free(ss->ssl3.dheGroups);
-    }
-
-    ss->ssl3.initialized = PR_FALSE;
-
-    SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
-}
-
-#define MAP_NULL(x) (((x) != 0) ? (x) : SEC_OID_NULL_CIPHER)
-
-SECStatus
-ssl3_ApplyNSSPolicy(void)
-{
-    unsigned i;
-    SECStatus rv;
-    PRUint32 policy = 0;
-
-    rv = NSS_GetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, &policy);
-    if (rv != SECSuccess || !(policy & NSS_USE_POLICY_IN_SSL)) {
-        return SECSuccess; /* do nothing */
-    }
-
-    /* disable every ciphersuite */
-    for (i = 1; i < PR_ARRAY_SIZE(cipher_suite_defs); ++i) {
-        const ssl3CipherSuiteDef *suite = &cipher_suite_defs[i];
-        SECOidTag policyOid;
-
-        policyOid = MAP_NULL(kea_defs[suite->key_exchange_alg].oid);
-        rv = NSS_GetAlgorithmPolicy(policyOid, &policy);
-        if (rv == SECSuccess && !(policy & NSS_USE_ALG_IN_SSL_KX)) {
-            ssl_CipherPrefSetDefault(suite->cipher_suite, PR_FALSE);
-            ssl_CipherPolicySet(suite->cipher_suite, SSL_NOT_ALLOWED);
-            continue;
-        }
-
-        policyOid = MAP_NULL(bulk_cipher_defs[suite->bulk_cipher_alg].oid);
-        rv = NSS_GetAlgorithmPolicy(policyOid, &policy);
-        if (rv == SECSuccess && !(policy & NSS_USE_ALG_IN_SSL)) {
-            ssl_CipherPrefSetDefault(suite->cipher_suite, PR_FALSE);
-            ssl_CipherPolicySet(suite->cipher_suite, SSL_NOT_ALLOWED);
-            continue;
-        }
-
-        if (bulk_cipher_defs[suite->bulk_cipher_alg].type != type_aead) {
-            policyOid = MAP_NULL(mac_defs[suite->mac_alg].oid);
-            rv = NSS_GetAlgorithmPolicy(policyOid, &policy);
-            if (rv == SECSuccess && !(policy & NSS_USE_ALG_IN_SSL)) {
-                ssl_CipherPrefSetDefault(suite->cipher_suite, PR_FALSE);
-                ssl_CipherPolicySet(suite->cipher_suite,
-                                    SSL_NOT_ALLOWED);
-                continue;
-            }
-        }
-    }
-
-    rv = ssl3_ConstrainRangeByPolicy();
-
-    return rv;
-}
-
-/* End of ssl3con.c */
diff --git a/net/third_party/nss/ssl/ssl3ecc.c b/net/third_party/nss/ssl/ssl3ecc.c
deleted file mode 100644
index c8e9d06b..0000000
--- a/net/third_party/nss/ssl/ssl3ecc.c
+++ /dev/null
@@ -1,1481 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * SSL3 Protocol
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* ECC code moved here from ssl3con.c */
-
-#include "nss.h"
-#include "cert.h"
-#include "ssl.h"
-#include "cryptohi.h" /* for DSAU_ stuff */
-#include "keyhi.h"
-#include "secder.h"
-#include "secitem.h"
-
-#include "sslimpl.h"
-#include "sslproto.h"
-#include "sslerr.h"
-#include "prtime.h"
-#include "prinrval.h"
-#include "prerror.h"
-#include "pratom.h"
-#include "prthread.h"
-#include "prinit.h"
-
-#include "pk11func.h"
-#include "secmod.h"
-
-#include <stdio.h>
-
-#ifndef NSS_DISABLE_ECC
-
-#ifndef PK11_SETATTRS
-#define PK11_SETATTRS(x, id, v, l) \
-    (x)->type = (id);              \
-    (x)->pValue = (v);             \
-    (x)->ulValueLen = (l);
-#endif
-
-#define SSL_GET_SERVER_PUBLIC_KEY(sock, type)                                          \
-    (ss->serverCerts[type].serverKeyPair ? ss->serverCerts[type].serverKeyPair->pubKey \
-                                         : NULL)
-
-#define SSL_IS_CURVE_NEGOTIATED(curvemsk, curveName) \
-    ((curveName > ec_noName) &&                      \
-     (curveName < ec_pastLastName) &&                \
-     ((1UL << curveName) & curvemsk) != 0)
-
-static SECStatus ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve);
-
-#define supportedCurve(x) (((x) > ec_noName) && ((x) < ec_pastLastName))
-
-/* Table containing OID tags for elliptic curves named in the
- * ECC-TLS IETF draft.
- */
-static const SECOidTag ecName2OIDTag[] = {
-    0,
-    SEC_OID_SECG_EC_SECT163K1, /*  1 */
-    SEC_OID_SECG_EC_SECT163R1, /*  2 */
-    SEC_OID_SECG_EC_SECT163R2, /*  3 */
-    SEC_OID_SECG_EC_SECT193R1, /*  4 */
-    SEC_OID_SECG_EC_SECT193R2, /*  5 */
-    SEC_OID_SECG_EC_SECT233K1, /*  6 */
-    SEC_OID_SECG_EC_SECT233R1, /*  7 */
-    SEC_OID_SECG_EC_SECT239K1, /*  8 */
-    SEC_OID_SECG_EC_SECT283K1, /*  9 */
-    SEC_OID_SECG_EC_SECT283R1, /* 10 */
-    SEC_OID_SECG_EC_SECT409K1, /* 11 */
-    SEC_OID_SECG_EC_SECT409R1, /* 12 */
-    SEC_OID_SECG_EC_SECT571K1, /* 13 */
-    SEC_OID_SECG_EC_SECT571R1, /* 14 */
-    SEC_OID_SECG_EC_SECP160K1, /* 15 */
-    SEC_OID_SECG_EC_SECP160R1, /* 16 */
-    SEC_OID_SECG_EC_SECP160R2, /* 17 */
-    SEC_OID_SECG_EC_SECP192K1, /* 18 */
-    SEC_OID_SECG_EC_SECP192R1, /* 19 */
-    SEC_OID_SECG_EC_SECP224K1, /* 20 */
-    SEC_OID_SECG_EC_SECP224R1, /* 21 */
-    SEC_OID_SECG_EC_SECP256K1, /* 22 */
-    SEC_OID_SECG_EC_SECP256R1, /* 23 */
-    SEC_OID_SECG_EC_SECP384R1, /* 24 */
-    SEC_OID_SECG_EC_SECP521R1, /* 25 */
-};
-
-static const PRUint16 curve2bits[] = {
-    0,    /*  ec_noName     = 0,   */
-    163,  /*  ec_sect163k1  = 1,   */
-    163,  /*  ec_sect163r1  = 2,   */
-    163,  /*  ec_sect163r2  = 3,   */
-    193,  /*  ec_sect193r1  = 4,   */
-    193,  /*  ec_sect193r2  = 5,   */
-    233,  /*  ec_sect233k1  = 6,   */
-    233,  /*  ec_sect233r1  = 7,   */
-    239,  /*  ec_sect239k1  = 8,   */
-    283,  /*  ec_sect283k1  = 9,   */
-    283,  /*  ec_sect283r1  = 10,  */
-    409,  /*  ec_sect409k1  = 11,  */
-    409,  /*  ec_sect409r1  = 12,  */
-    571,  /*  ec_sect571k1  = 13,  */
-    571,  /*  ec_sect571r1  = 14,  */
-    160,  /*  ec_secp160k1  = 15,  */
-    160,  /*  ec_secp160r1  = 16,  */
-    160,  /*  ec_secp160r2  = 17,  */
-    192,  /*  ec_secp192k1  = 18,  */
-    192,  /*  ec_secp192r1  = 19,  */
-    224,  /*  ec_secp224k1  = 20,  */
-    224,  /*  ec_secp224r1  = 21,  */
-    256,  /*  ec_secp256k1  = 22,  */
-    256,  /*  ec_secp256r1  = 23,  */
-    384,  /*  ec_secp384r1  = 24,  */
-    521,  /*  ec_secp521r1  = 25,  */
-    65535 /*  ec_pastLastName      */
-};
-
-typedef struct Bits2CurveStr {
-    PRUint16 bits;
-    ECName curve;
-} Bits2Curve;
-
-static const Bits2Curve bits2curve[] = {
-    { 192, ec_secp192r1 /*  = 19,  fast */ },
-    { 160, ec_secp160r2 /*  = 17,  fast */ },
-    { 160, ec_secp160k1 /*  = 15,  */ },
-    { 160, ec_secp160r1 /*  = 16,  */ },
-    { 163, ec_sect163k1 /*  = 1,   */ },
-    { 163, ec_sect163r1 /*  = 2,   */ },
-    { 163, ec_sect163r2 /*  = 3,   */ },
-    { 192, ec_secp192k1 /*  = 18,  */ },
-    { 193, ec_sect193r1 /*  = 4,   */ },
-    { 193, ec_sect193r2 /*  = 5,   */ },
-    { 224, ec_secp224r1 /*  = 21,  fast */ },
-    { 224, ec_secp224k1 /*  = 20,  */ },
-    { 233, ec_sect233k1 /*  = 6,   */ },
-    { 233, ec_sect233r1 /*  = 7,   */ },
-    { 239, ec_sect239k1 /*  = 8,   */ },
-    { 256, ec_secp256r1 /*  = 23,  fast */ },
-    { 256, ec_secp256k1 /*  = 22,  */ },
-    { 283, ec_sect283k1 /*  = 9,   */ },
-    { 283, ec_sect283r1 /*  = 10,  */ },
-    { 384, ec_secp384r1 /*  = 24,  fast */ },
-    { 409, ec_sect409k1 /*  = 11,  */ },
-    { 409, ec_sect409r1 /*  = 12,  */ },
-    { 521, ec_secp521r1 /*  = 25,  fast */ },
-    { 571, ec_sect571k1 /*  = 13,  */ },
-    { 571, ec_sect571r1 /*  = 14,  */ },
-    { 65535, ec_noName }
-};
-
-typedef struct ECDHEKeyPairStr {
-    ssl3KeyPair *pair;
-    int error; /* error code of the call-once function */
-    PRCallOnceType once;
-} ECDHEKeyPair;
-
-/* arrays of ECDHE KeyPairs */
-static ECDHEKeyPair gECDHEKeyPairs[ec_pastLastName];
-
-SECStatus
-ssl3_ECName2Params(PLArenaPool *arena, ECName curve, SECKEYECParams *params)
-{
-    SECOidData *oidData = NULL;
-    PRUint32 policyFlags = 0;
-
-    if ((curve <= ec_noName) || (curve >= ec_pastLastName) ||
-        ((oidData = SECOID_FindOIDByTag(ecName2OIDTag[curve])) == NULL)) {
-        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
-        return SECFailure;
-    }
-
-    if ((NSS_GetAlgorithmPolicy(ecName2OIDTag[curve], &policyFlags) ==
-         SECSuccess) &&
-        !(policyFlags & NSS_USE_ALG_IN_SSL_KX)) {
-        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
-        return SECFailure;
-    }
-
-    SECITEM_AllocItem(arena, params, (2 + oidData->oid.len));
-    /*
-     * params->data needs to contain the ASN encoding of an object ID (OID)
-     * representing the named curve. The actual OID is in
-     * oidData->oid.data so we simply prepend 0x06 and OID length
-     */
-    params->data[0] = SEC_ASN1_OBJECT_ID;
-    params->data[1] = oidData->oid.len;
-    memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
-
-    return SECSuccess;
-}
-
-ECName
-ssl3_PubKey2ECName(SECKEYPublicKey *pubKey)
-{
-    SECItem oid = { siBuffer, NULL, 0 };
-    SECOidData *oidData = NULL;
-    PRUint32 policyFlags = 0;
-    ECName i;
-    SECKEYECParams *params;
-
-    if (pubKey->keyType != ecKey) {
-        PORT_Assert(0);
-        return ec_noName;
-    }
-
-    params = &pubKey->u.ec.DEREncodedParams;
-
-    /*
-     * params->data needs to contain the ASN encoding of an object ID (OID)
-     * representing a named curve. Here, we strip away everything
-     * before the actual OID and use the OID to look up a named curve.
-     */
-    if (params->data[0] != SEC_ASN1_OBJECT_ID)
-        return ec_noName;
-    oid.len = params->len - 2;
-    oid.data = params->data + 2;
-    if ((oidData = SECOID_FindOID(&oid)) == NULL)
-        return ec_noName;
-    if ((NSS_GetAlgorithmPolicy(oidData->offset, &policyFlags) ==
-         SECSuccess) &&
-        !(policyFlags & NSS_USE_ALG_IN_SSL_KX)) {
-        return ec_noName;
-    }
-    for (i = ec_noName + 1; i < ec_pastLastName; i++) {
-        if (ecName2OIDTag[i] == oidData->offset)
-            return i;
-    }
-
-    return ec_noName;
-}
-
-/* Caller must set hiLevel error code. */
-static SECStatus
-ssl3_ComputeECDHKeyHash(SSLHashType hashAlg,
-                        SECItem ec_params, SECItem server_ecpoint,
-                        SSL3Random *client_rand, SSL3Random *server_rand,
-                        SSL3Hashes *hashes, PRBool bypassPKCS11)
-{
-    PRUint8 *hashBuf;
-    PRUint8 *pBuf;
-    SECStatus rv = SECSuccess;
-    unsigned int bufLen;
-    /*
-     * XXX For now, we only support named curves (the appropriate
-     * checks are made before this method is called) so ec_params
-     * takes up only two bytes. ECPoint needs to fit in 256 bytes
-     * (because the spec says the length must fit in one byte)
-     */
-    PRUint8 buf[2 * SSL3_RANDOM_LENGTH + 2 + 1 + 256];
-
-    bufLen = 2 * SSL3_RANDOM_LENGTH + ec_params.len + 1 + server_ecpoint.len;
-    if (bufLen <= sizeof buf) {
-        hashBuf = buf;
-    } else {
-        hashBuf = PORT_Alloc(bufLen);
-        if (!hashBuf) {
-            return SECFailure;
-        }
-    }
-
-    memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH);
-    pBuf = hashBuf + SSL3_RANDOM_LENGTH;
-    memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH);
-    pBuf += SSL3_RANDOM_LENGTH;
-    memcpy(pBuf, ec_params.data, ec_params.len);
-    pBuf += ec_params.len;
-    pBuf[0] = (PRUint8)(server_ecpoint.len);
-    pBuf += 1;
-    memcpy(pBuf, server_ecpoint.data, server_ecpoint.len);
-    pBuf += server_ecpoint.len;
-    PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);
-
-    rv = ssl3_ComputeCommonKeyHash(hashAlg, hashBuf, bufLen, hashes,
-                                   bypassPKCS11);
-
-    PRINT_BUF(95, (NULL, "ECDHkey hash: ", hashBuf, bufLen));
-    PRINT_BUF(95, (NULL, "ECDHkey hash: MD5 result",
-                   hashes->u.s.md5, MD5_LENGTH));
-    PRINT_BUF(95, (NULL, "ECDHkey hash: SHA1 result",
-                   hashes->u.s.sha, SHA1_LENGTH));
-
-    if (hashBuf != buf)
-        PORT_Free(hashBuf);
-    return rv;
-}
-
-/* Called from ssl3_SendClientKeyExchange(). */
-SECStatus
-ssl3_SendECDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey)
-{
-    PK11SymKey *pms = NULL;
-    SECStatus rv = SECFailure;
-    PRBool isTLS, isTLS12;
-    CK_MECHANISM_TYPE target;
-    SECKEYPublicKey *pubKey = NULL;   /* Ephemeral ECDH key */
-    SECKEYPrivateKey *privKey = NULL; /* Ephemeral ECDH key */
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
-    isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
-
-    /* Generate ephemeral EC keypair */
-    if (svrPubKey->keyType != ecKey) {
-        PORT_SetError(SEC_ERROR_BAD_KEY);
-        goto loser;
-    }
-    /* XXX SHOULD CALL ssl3_CreateECDHEphemeralKeys here, instead! */
-    privKey = SECKEY_CreateECPrivateKey(&svrPubKey->u.ec.DEREncodedParams,
-                                        &pubKey, ss->pkcs11PinArg);
-    if (!privKey || !pubKey) {
-        ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
-        rv = SECFailure;
-        goto loser;
-    }
-    PRINT_BUF(50, (ss, "ECDH public value:",
-                   pubKey->u.ec.publicValue.data,
-                   pubKey->u.ec.publicValue.len));
-
-    if (isTLS12) {
-        target = CKM_TLS12_MASTER_KEY_DERIVE_DH;
-    } else if (isTLS) {
-        target = CKM_TLS_MASTER_KEY_DERIVE_DH;
-    } else {
-        target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
-    }
-
-    /*  Determine the PMS */
-    pms = PK11_PubDeriveWithKDF(privKey, svrPubKey, PR_FALSE, NULL, NULL,
-                                CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
-                                CKD_NULL, NULL, NULL);
-
-    if (pms == NULL) {
-        SSL3AlertDescription desc = illegal_parameter;
-        (void)SSL3_SendAlert(ss, alert_fatal, desc);
-        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
-        goto loser;
-    }
-
-    SECKEY_DestroyPrivateKey(privKey);
-    privKey = NULL;
-
-    rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
-                                    pubKey->u.ec.publicValue.len + 1);
-    if (rv != SECSuccess) {
-        goto loser; /* err set by ssl3_AppendHandshake* */
-    }
-
-    rv = ssl3_AppendHandshakeVariable(ss,
-                                      pubKey->u.ec.publicValue.data,
-                                      pubKey->u.ec.publicValue.len, 1);
-    SECKEY_DestroyPublicKey(pubKey);
-    pubKey = NULL;
-
-    if (rv != SECSuccess) {
-        goto loser; /* err set by ssl3_AppendHandshake* */
-    }
-
-    rv = ssl3_InitPendingCipherSpec(ss, pms);
-    PK11_FreeSymKey(pms);
-    pms = NULL;
-
-    if (rv != SECSuccess) {
-        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
-        goto loser;
-    }
-
-    rv = SECSuccess;
-
-loser:
-    if (pms)
-        PK11_FreeSymKey(pms);
-    if (privKey)
-        SECKEY_DestroyPrivateKey(privKey);
-    if (pubKey)
-        SECKEY_DestroyPublicKey(pubKey);
-    return rv;
-}
-
-ECName
-tls13_GroupForECDHEKeyShare(ssl3KeyPair *pair)
-{
-    return ssl3_PubKey2ECName(pair->pubKey);
-}
-
-/* This function returns the size of the key_exchange field in
- * the KeyShareEntry structure. */
-unsigned int
-tls13_SizeOfECDHEKeyShareKEX(ssl3KeyPair *pair)
-{
-    return 1 + /* Length */
-           pair->pubKey->u.ec.publicValue.len;
-}
-
-/* This function encodes the key_exchange field in
- * the KeyShareEntry structure. */
-SECStatus
-tls13_EncodeECDHEKeyShareKEX(sslSocket *ss, ssl3KeyPair *pair)
-{
-    const SECItem *publicValue;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    publicValue = &pair->pubKey->u.ec.publicValue;
-
-    return ssl3_AppendHandshakeVariable(ss, publicValue->data,
-                                        publicValue->len, 1);
-}
-
-/*
-** Called from ssl3_HandleClientKeyExchange()
-*/
-SECStatus
-ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
-                                 PRUint32 length,
-                                 SECKEYPublicKey *srvrPubKey,
-                                 SECKEYPrivateKey *srvrPrivKey)
-{
-    PK11SymKey *pms;
-    SECStatus rv;
-    SECKEYPublicKey clntPubKey;
-    CK_MECHANISM_TYPE target;
-    PRBool isTLS, isTLS12;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    clntPubKey.keyType = ecKey;
-    clntPubKey.u.ec.DEREncodedParams.len =
-        srvrPubKey->u.ec.DEREncodedParams.len;
-    clntPubKey.u.ec.DEREncodedParams.data =
-        srvrPubKey->u.ec.DEREncodedParams.data;
-
-    rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.ec.publicValue,
-                                       1, &b, &length);
-    if (rv != SECSuccess) {
-        SEND_ALERT
-        return SECFailure; /* XXX Who sets the error code?? */
-    }
-
-    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
-    isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
-
-    if (isTLS12) {
-        target = CKM_TLS12_MASTER_KEY_DERIVE_DH;
-    } else if (isTLS) {
-        target = CKM_TLS_MASTER_KEY_DERIVE_DH;
-    } else {
-        target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
-    }
-
-    /*  Determine the PMS */
-    pms = PK11_PubDeriveWithKDF(srvrPrivKey, &clntPubKey, PR_FALSE, NULL, NULL,
-                                CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
-                                CKD_NULL, NULL, NULL);
-
-    if (pms == NULL) {
-        /* last gasp.  */
-        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
-        return SECFailure;
-    }
-
-    rv = ssl3_InitPendingCipherSpec(ss, pms);
-    PK11_FreeSymKey(pms);
-    if (rv != SECSuccess) {
-        SEND_ALERT
-        return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */
-    }
-    return SECSuccess;
-}
-
-/*
-** Take an encoded key share and make a public key out of it.
-** returns NULL on error.
-*/
-SECKEYPublicKey *
-tls13_ImportECDHKeyShare(sslSocket *ss, SSL3Opaque *b,
-                         PRUint32 length, ECName curve)
-{
-    PLArenaPool *arena = NULL;
-    SECKEYPublicKey *peerKey = NULL;
-    SECStatus rv;
-    SECItem ecPoint = { siBuffer, NULL, 0 };
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    rv = ssl3_ConsumeHandshakeVariable(ss, &ecPoint, 1, &b, &length);
-    if (rv != SECSuccess) {
-        tls13_FatalError(ss, SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE,
-                         illegal_parameter);
-        return NULL;
-    }
-    if (length || !ecPoint.len) {
-        tls13_FatalError(ss, SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE,
-                         illegal_parameter);
-        return NULL;
-    }
-
-    /* Fail if the ec point uses compressed representation */
-    if (ecPoint.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
-        tls13_FatalError(ss, SEC_ERROR_UNSUPPORTED_EC_POINT_FORM,
-                         illegal_parameter);
-        return NULL;
-    }
-
-    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-    if (arena == NULL) {
-        goto no_memory;
-    }
-
-    peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
-    if (peerKey == NULL) {
-        goto no_memory;
-    }
-
-    peerKey->arena = arena;
-    peerKey->keyType = ecKey;
-    /* Set up the encoded params */
-    rv = ssl3_ECName2Params(arena, curve, &peerKey->u.ec.DEREncodedParams);
-    if (rv != SECSuccess) {
-        goto no_memory;
-    }
-
-    /* copy publicValue in peerKey */
-    if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue, &ecPoint) !=
-        SECSuccess) {
-        goto no_memory;
-    }
-    peerKey->pkcs11Slot = NULL;
-    peerKey->pkcs11ID = CK_INVALID_HANDLE;
-
-    return peerKey;
-
-no_memory: /* no-memory error has already been set. */
-    PORT_FreeArena(arena, PR_FALSE);
-    ssl_MapLowLevelError(SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE);
-    return NULL;
-}
-
-PK11SymKey *
-tls13_ComputeECDHSharedKey(sslSocket *ss,
-                           SECKEYPrivateKey *myPrivKey,
-                           SECKEYPublicKey *peerKey)
-{
-    PK11SymKey *shared;
-
-    /* Determine the PMS */
-    shared = PK11_PubDeriveWithKDF(myPrivKey, peerKey, PR_FALSE, NULL, NULL,
-                                   CKM_ECDH1_DERIVE,
-                                   tls13_GetHkdfMechanism(ss), CKA_DERIVE, 0,
-                                   CKD_NULL, NULL, NULL);
-
-    if (!shared) {
-        ssl_MapLowLevelError(SSL_ERROR_KEY_EXCHANGE_FAILURE);
-        return NULL;
-    }
-
-    return shared;
-}
-
-ECName
-ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits)
-{
-    int i;
-
-    for (i = 0; bits2curve[i].curve != ec_noName; i++) {
-        if (bits2curve[i].bits < requiredECCbits)
-            continue;
-        if (SSL_IS_CURVE_NEGOTIATED(curvemsk, bits2curve[i].curve)) {
-            return bits2curve[i].curve;
-        }
-    }
-    PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
-    return ec_noName;
-}
-
-/* find the "weakest link".  Get strength of signature key and of sym key.
- * choose curve for the weakest of those two.
- */
-ECName
-ssl3_GetCurveNameForServerSocket(sslSocket *ss)
-{
-    SECKEYPublicKey *svrPublicKey = NULL;
-    ECName ec_curve = ec_noName;
-    int signatureKeyStrength = 521;
-    int requiredECCbits = ss->sec.secretKeyBits * 2;
-
-    if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa) {
-        svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_ecdh);
-        if (svrPublicKey)
-            ec_curve = ssl3_PubKey2ECName(svrPublicKey);
-        if (!SSL_IS_CURVE_NEGOTIATED(ss->ssl3.hs.negotiatedECCurves, ec_curve)) {
-            PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
-            return ec_noName;
-        }
-        signatureKeyStrength = curve2bits[ec_curve];
-    } else {
-        /* RSA is our signing cert */
-        int serverKeyStrengthInBits;
-
-        svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_rsa);
-        if (!svrPublicKey) {
-            PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
-            return ec_noName;
-        }
-
-        /* currently strength in bytes */
-        serverKeyStrengthInBits = svrPublicKey->u.rsa.modulus.len;
-        if (svrPublicKey->u.rsa.modulus.data[0] == 0) {
-            serverKeyStrengthInBits--;
-        }
-        /* convert to strength in bits */
-        serverKeyStrengthInBits *= BPB;
-
-        signatureKeyStrength =
-            SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits);
-    }
-    if (requiredECCbits > signatureKeyStrength)
-        requiredECCbits = signatureKeyStrength;
-
-    return ssl3_GetCurveWithECKeyStrength(ss->ssl3.hs.negotiatedECCurves,
-                                          requiredECCbits);
-}
-
-/* function to clear out the lists */
-static SECStatus
-ssl3_ShutdownECDHECurves(void *appData, void *nssData)
-{
-    int i;
-    ECDHEKeyPair *keyPair = &gECDHEKeyPairs[0];
-
-    for (i = 0; i < ec_pastLastName; i++, keyPair++) {
-        if (keyPair->pair) {
-            ssl3_FreeKeyPair(keyPair->pair);
-        }
-    }
-    memset(gECDHEKeyPairs, 0, sizeof gECDHEKeyPairs);
-    return SECSuccess;
-}
-
-static PRStatus
-ssl3_ECRegister(void)
-{
-    SECStatus rv;
-    rv = NSS_RegisterShutdown(ssl3_ShutdownECDHECurves, gECDHEKeyPairs);
-    if (rv != SECSuccess) {
-        gECDHEKeyPairs[ec_noName].error = PORT_GetError();
-    }
-    return (PRStatus)rv;
-}
-
-/* Create an ECDHE key pair for a given curve */
-SECStatus
-ssl3_CreateECDHEphemeralKeyPair(ECName ec_curve, ssl3KeyPair **keyPair)
-{
-    SECKEYPrivateKey *privKey = NULL;
-    SECKEYPublicKey *pubKey = NULL;
-    SECKEYECParams ecParams = { siBuffer, NULL, 0 };
-
-    if (ssl3_ECName2Params(NULL, ec_curve, &ecParams) != SECSuccess) {
-        return SECFailure;
-    }
-    privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, NULL);
-    SECITEM_FreeItem(&ecParams, PR_FALSE);
-
-    if (!privKey || !pubKey || !(*keyPair = ssl3_NewKeyPair(privKey, pubKey))) {
-        if (privKey) {
-            SECKEY_DestroyPrivateKey(privKey);
-        }
-        if (pubKey) {
-            SECKEY_DestroyPublicKey(pubKey);
-        }
-        ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
-        return SECFailure;
-    }
-
-    return SECSuccess;
-}
-
-/* CallOnce function, called once for each named curve. */
-static PRStatus
-ssl3_CreateECDHEphemeralKeyPairOnce(void *arg)
-{
-    ECName ec_curve = (ECName)arg;
-    ssl3KeyPair *keyPair = NULL;
-
-    PORT_Assert(gECDHEKeyPairs[ec_curve].pair == NULL);
-
-    /* ok, no one has generated a global key for this curve yet, do so */
-    if (ssl3_CreateECDHEphemeralKeyPair(ec_curve, &keyPair) != SECSuccess) {
-        gECDHEKeyPairs[ec_curve].error = PORT_GetError();
-        return PR_FAILURE;
-    }
-
-    gECDHEKeyPairs[ec_curve].pair = keyPair;
-    return PR_SUCCESS;
-}
-
-/*
- * Creates the ephemeral public and private ECDH keys used by
- * server in ECDHE_RSA and ECDHE_ECDSA handshakes.
- * For now, the elliptic curve is chosen to be the same
- * strength as the signing certificate (ECC or RSA).
- * We need an API to specify the curve. This won't be a real
- * issue until we further develop server-side support for ECC
- * cipher suites.
- */
-static SECStatus
-ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve)
-{
-    ssl3KeyPair *keyPair = NULL;
-
-    /* if there's no global key for this curve, make one. */
-    if (gECDHEKeyPairs[ec_curve].pair == NULL) {
-        PRStatus status;
-
-        status = PR_CallOnce(&gECDHEKeyPairs[ec_noName].once, ssl3_ECRegister);
-        if (status != PR_SUCCESS) {
-            PORT_SetError(gECDHEKeyPairs[ec_noName].error);
-            return SECFailure;
-        }
-        status = PR_CallOnceWithArg(&gECDHEKeyPairs[ec_curve].once,
-                                    ssl3_CreateECDHEphemeralKeyPairOnce,
-                                    (void *)ec_curve);
-        if (status != PR_SUCCESS) {
-            PORT_SetError(gECDHEKeyPairs[ec_curve].error);
-            return SECFailure;
-        }
-    }
-
-    keyPair = gECDHEKeyPairs[ec_curve].pair;
-    PORT_Assert(keyPair != NULL);
-    if (!keyPair)
-        return SECFailure;
-    ss->ephemeralECDHKeyPair = ssl3_GetKeyPairRef(keyPair);
-
-    return SECSuccess;
-}
-
-SECStatus
-ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    PLArenaPool *arena = NULL;
-    SECKEYPublicKey *peerKey = NULL;
-    PRBool isTLS, isTLS12;
-    SECStatus rv;
-    int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
-    SSL3AlertDescription desc = illegal_parameter;
-    SSL3Hashes hashes;
-    SECItem signature = { siBuffer, NULL, 0 };
-
-    SECItem ec_params = { siBuffer, NULL, 0 };
-    SECItem ec_point = { siBuffer, NULL, 0 };
-    unsigned char paramBuf[3]; /* only for curve_type == named_curve */
-    SSLSignatureAndHashAlg sigAndHash;
-
-    sigAndHash.hashAlg = ssl_hash_none;
-
-    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
-    isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
-
-    /* XXX This works only for named curves, revisit this when
-     * we support generic curves.
-     */
-    ec_params.len = sizeof paramBuf;
-    ec_params.data = paramBuf;
-    rv = ssl3_ConsumeHandshake(ss, ec_params.data, ec_params.len, &b, &length);
-    if (rv != SECSuccess) {
-        goto loser; /* malformed. */
-    }
-
-    /* Fail if the curve is not a named curve */
-    if ((ec_params.data[0] != ec_type_named) ||
-        (ec_params.data[1] != 0) ||
-        !supportedCurve(ec_params.data[2])) {
-        errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
-        desc = handshake_failure;
-        goto alert_loser;
-    }
-
-    rv = ssl3_ConsumeHandshakeVariable(ss, &ec_point, 1, &b, &length);
-    if (rv != SECSuccess) {
-        goto loser; /* malformed. */
-    }
-    /* Fail if the ec point uses compressed representation */
-    if (ec_point.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
-        errCode = SEC_ERROR_UNSUPPORTED_EC_POINT_FORM;
-        desc = handshake_failure;
-        goto alert_loser;
-    }
-
-    if (isTLS12) {
-        rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
-                                                   &sigAndHash);
-        if (rv != SECSuccess) {
-            goto loser; /* malformed or unsupported. */
-        }
-        rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
-            ss, &sigAndHash, ss->sec.peerCert);
-        if (rv != SECSuccess) {
-            goto loser;
-        }
-    }
-
-    rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
-    if (rv != SECSuccess) {
-        goto loser; /* malformed. */
-    }
-
-    if (length != 0) {
-        if (isTLS)
-            desc = decode_error;
-        goto alert_loser; /* malformed. */
-    }
-
-    PRINT_BUF(60, (NULL, "Server EC params", ec_params.data,
-                   ec_params.len));
-    PRINT_BUF(60, (NULL, "Server EC point", ec_point.data, ec_point.len));
-
-    /* failures after this point are not malformed handshakes. */
-    /* TLS: send decrypt_error if signature failed. */
-    desc = isTLS ? decrypt_error : handshake_failure;
-
-    /*
-     *  check to make sure the hash is signed by right guy
-     */
-    rv = ssl3_ComputeECDHKeyHash(sigAndHash.hashAlg, ec_params, ec_point,
-                                 &ss->ssl3.hs.client_random,
-                                 &ss->ssl3.hs.server_random,
-                                 &hashes, ss->opt.bypassPKCS11);
-
-    if (rv != SECSuccess) {
-        errCode =
-            ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-        goto alert_loser;
-    }
-    rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
-                                 isTLS, ss->pkcs11PinArg);
-    if (rv != SECSuccess) {
-        errCode =
-            ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-        goto alert_loser;
-    }
-
-    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-    if (arena == NULL) {
-        goto no_memory;
-    }
-
-    peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
-    if (peerKey == NULL) {
-        goto no_memory;
-    }
-
-    peerKey->arena = arena;
-    peerKey->keyType = ecKey;
-
-    /* set up EC parameters in peerKey */
-    if (ssl3_ECName2Params(arena, ec_params.data[2],
-                           &peerKey->u.ec.DEREncodedParams) !=
-        SECSuccess) {
-        /* we should never get here since we already
-         * checked that we are dealing with a supported curve
-         */
-        errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
-        goto alert_loser;
-    }
-
-    /* copy publicValue in peerKey */
-    if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue, &ec_point)) {
-        goto no_memory;
-    }
-    peerKey->pkcs11Slot = NULL;
-    peerKey->pkcs11ID = CK_INVALID_HANDLE;
-
-    ss->sec.peerKey = peerKey;
-    ss->ssl3.hs.ws = wait_cert_request;
-
-    return SECSuccess;
-
-alert_loser:
-    (void)SSL3_SendAlert(ss, alert_fatal, desc);
-loser:
-    if (arena) {
-        PORT_FreeArena(arena, PR_FALSE);
-    }
-    PORT_SetError(errCode);
-    return SECFailure;
-
-no_memory: /* no-memory error has already been set. */
-    if (arena) {
-        PORT_FreeArena(arena, PR_FALSE);
-    }
-    ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-    return SECFailure;
-}
-
-SECStatus
-ssl3_SendECDHServerKeyExchange(
-    sslSocket *ss,
-    const SSLSignatureAndHashAlg *sigAndHash)
-{
-    const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
-    SECStatus rv = SECFailure;
-    int length;
-    PRBool isTLS, isTLS12;
-    SECItem signed_hash = { siBuffer, NULL, 0 };
-    SSL3Hashes hashes;
-
-    SECKEYPublicKey *ecdhePub;
-    SECItem ec_params = { siBuffer, NULL, 0 };
-    unsigned char paramBuf[3];
-    ECName curve;
-    SSL3KEAType certIndex;
-
-    /* Generate ephemeral ECDH key pair and send the public key */
-    curve = ssl3_GetCurveNameForServerSocket(ss);
-    if (curve == ec_noName) {
-        goto loser;
-    }
-
-    if (ss->opt.reuseServerECDHEKey) {
-        rv = ssl3_CreateECDHEphemeralKeys(ss, curve);
-    } else {
-        rv = ssl3_CreateECDHEphemeralKeyPair(curve, &ss->ephemeralECDHKeyPair);
-    }
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-
-    ecdhePub = ss->ephemeralECDHKeyPair->pubKey;
-    PORT_Assert(ecdhePub != NULL);
-    if (!ecdhePub) {
-        PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-        return SECFailure;
-    }
-
-    ec_params.len = sizeof paramBuf;
-    ec_params.data = paramBuf;
-    curve = ssl3_PubKey2ECName(ecdhePub);
-    if (curve != ec_noName) {
-        ec_params.data[0] = ec_type_named;
-        ec_params.data[1] = 0x00;
-        ec_params.data[2] = curve;
-    } else {
-        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
-        goto loser;
-    }
-
-    rv = ssl3_ComputeECDHKeyHash(sigAndHash->hashAlg,
-                                 ec_params,
-                                 ecdhePub->u.ec.publicValue,
-                                 &ss->ssl3.hs.client_random,
-                                 &ss->ssl3.hs.server_random,
-                                 &hashes, ss->opt.bypassPKCS11);
-    if (rv != SECSuccess) {
-        ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-        goto loser;
-    }
-
-    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
-    isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
-
-    /* XXX SSLKEAType isn't really a good choice for
-     * indexing certificates but that's all we have
-     * for now.
-     */
-    if (kea_def->kea == kea_ecdhe_rsa)
-        certIndex = kt_rsa;
-    else /* kea_def->kea == kea_ecdhe_ecdsa */
-        certIndex = kt_ecdh;
-
-    rv = ssl3_SignHashes(&hashes, ss->serverCerts[certIndex].SERVERKEY,
-                         &signed_hash, isTLS);
-    if (rv != SECSuccess) {
-        goto loser; /* ssl3_SignHashes has set err. */
-    }
-    if (signed_hash.data == NULL) {
-        /* how can this happen and rv == SECSuccess ?? */
-        PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-        goto loser;
-    }
-
-    length = ec_params.len +
-             1 + ecdhePub->u.ec.publicValue.len +
-             (isTLS12 ? 2 : 0) + 2 + signed_hash.len;
-
-    rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
-    if (rv != SECSuccess) {
-        goto loser; /* err set by AppendHandshake. */
-    }
-
-    rv = ssl3_AppendHandshake(ss, ec_params.data, ec_params.len);
-    if (rv != SECSuccess) {
-        goto loser; /* err set by AppendHandshake. */
-    }
-
-    rv = ssl3_AppendHandshakeVariable(ss, ecdhePub->u.ec.publicValue.data,
-                                      ecdhePub->u.ec.publicValue.len, 1);
-    if (rv != SECSuccess) {
-        goto loser; /* err set by AppendHandshake. */
-    }
-
-    if (isTLS12) {
-        rv = ssl3_AppendSignatureAndHashAlgorithm(ss, sigAndHash);
-        if (rv != SECSuccess) {
-            goto loser; /* err set by AppendHandshake. */
-        }
-    }
-
-    rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
-                                      signed_hash.len, 2);
-    if (rv != SECSuccess) {
-        goto loser; /* err set by AppendHandshake. */
-    }
-
-    PORT_Free(signed_hash.data);
-    return SECSuccess;
-
-loser:
-    if (signed_hash.data != NULL)
-        PORT_Free(signed_hash.data);
-    return SECFailure;
-}
-
-/* Lists of ECC cipher suites for searching and disabling. */
-
-static const ssl3CipherSuite ecdh_suites[] = {
-    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
-    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
-    TLS_ECDH_ECDSA_WITH_NULL_SHA,
-    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
-    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
-    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
-    TLS_ECDH_RSA_WITH_NULL_SHA,
-    TLS_ECDH_RSA_WITH_RC4_128_SHA,
-    0 /* end of list marker */
-};
-
-static const ssl3CipherSuite ecdh_ecdsa_suites[] = {
-    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
-    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
-    TLS_ECDH_ECDSA_WITH_NULL_SHA,
-    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
-    0 /* end of list marker */
-};
-
-static const ssl3CipherSuite ecdh_rsa_suites[] = {
-    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
-    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
-    TLS_ECDH_RSA_WITH_NULL_SHA,
-    TLS_ECDH_RSA_WITH_RC4_128_SHA,
-    0 /* end of list marker */
-};
-
-static const ssl3CipherSuite ecdhe_ecdsa_suites[] = {
-    TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
-    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
-    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
-    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
-    TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
-    TLS_ECDHE_ECDSA_WITH_NULL_SHA,
-    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
-    0 /* end of list marker */
-};
-
-static const ssl3CipherSuite ecdhe_rsa_suites[] = {
-    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
-    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
-    TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-    TLS_ECDHE_RSA_WITH_NULL_SHA,
-    TLS_ECDHE_RSA_WITH_RC4_128_SHA,
-    0 /* end of list marker */
-};
-
-/* List of all ECC cipher suites */
-static const ssl3CipherSuite ecSuites[] = {
-    TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
-    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
-    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
-    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
-    TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
-    TLS_ECDHE_ECDSA_WITH_NULL_SHA,
-    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
-    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
-    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
-    TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-    TLS_ECDHE_RSA_WITH_NULL_SHA,
-    TLS_ECDHE_RSA_WITH_RC4_128_SHA,
-    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
-    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
-    TLS_ECDH_ECDSA_WITH_NULL_SHA,
-    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
-    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
-    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
-    TLS_ECDH_RSA_WITH_NULL_SHA,
-    TLS_ECDH_RSA_WITH_RC4_128_SHA,
-    0 /* end of list marker */
-};
-
-/* On this socket, Disable the ECC cipher suites in the argument's list */
-SECStatus
-ssl3_DisableECCSuites(sslSocket *ss, const ssl3CipherSuite *suite)
-{
-    if (!suite)
-        suite = ecSuites;
-    for (; *suite; ++suite) {
-        PORT_CheckSuccess(ssl3_CipherPrefSet(ss, *suite, PR_FALSE));
-    }
-    return SECSuccess;
-}
-
-/* Look at the server certs configured on this socket, and disable any
- * ECC cipher suites that are not supported by those certs.
- */
-void
-ssl3_FilterECCipherSuitesByServerCerts(sslSocket *ss)
-{
-    CERTCertificate *svrCert;
-
-    svrCert = ss->serverCerts[kt_rsa].serverCert;
-    if (!svrCert) {
-        ssl3_DisableECCSuites(ss, ecdhe_rsa_suites);
-    }
-
-    svrCert = ss->serverCerts[kt_ecdh].serverCert;
-    if (!svrCert) {
-        ssl3_DisableECCSuites(ss, ecdh_suites);
-        ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites);
-    } else {
-        SECOidTag sigTag = SECOID_GetAlgorithmTag(&svrCert->signature);
-
-        switch (sigTag) {
-            case SEC_OID_PKCS1_RSA_ENCRYPTION:
-            case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
-            case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
-            case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
-            case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
-            case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
-            case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
-            case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
-            case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
-                ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites);
-                break;
-            case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
-            case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
-            case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
-            case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
-            case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
-            case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
-            case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
-                ssl3_DisableECCSuites(ss, ecdh_rsa_suites);
-                break;
-            default:
-                ssl3_DisableECCSuites(ss, ecdh_suites);
-                break;
-        }
-    }
-}
-
-/* Ask: is ANY ECC cipher suite enabled on this socket? */
-/* Order(N^2).  Yuk.  Also, this ignores export policy. */
-PRBool
-ssl3_IsECCEnabled(sslSocket *ss)
-{
-    const ssl3CipherSuite *suite;
-    PK11SlotInfo *slot;
-
-    /* make sure we can do ECC */
-    slot = PK11_GetBestSlot(CKM_ECDH1_DERIVE, ss->pkcs11PinArg);
-    if (!slot) {
-        return PR_FALSE;
-    }
-    PK11_FreeSlot(slot);
-
-    /* make sure an ECC cipher is enabled */
-    for (suite = ecSuites; *suite; ++suite) {
-        PRBool enabled = PR_FALSE;
-        SECStatus rv = ssl3_CipherPrefGet(ss, *suite, &enabled);
-
-        PORT_Assert(rv == SECSuccess); /* else is coding error */
-        if (rv == SECSuccess && enabled)
-            return PR_TRUE;
-    }
-    return PR_FALSE;
-}
-
-#define BE(n) 0, n
-
-/* Prefabricated TLS client hello extension, Elliptic Curves List,
- * offers only 3 curves, the Suite B curves, 23-25
- */
-static const PRUint8 suiteBECList[] = {
-    23, 24, 25
-};
-
-/* Prefabricated TLS client hello extension, Elliptic Curves List,
- * offers curves 1-25.
- */
-/* clang-format off */
-static const PRUint8 tlsECList[] = {
-     1,  2,  3,  4,  5,  6,  7,  8,
-     9, 10, 11, 12, 13, 14, 15, 16,
-    17, 18, 19, 20, 21, 22, 23, 24,
-    25
-};
-/* clang-format on */
-
-static const PRUint8 ecPtFmt[6] = {
-    BE(11), /* Extension type */
-    BE(2),  /* octets that follow */
-    1,      /* octets that follow */
-    0       /* uncompressed type only */
-};
-
-/* This function already presumes we can do ECC, ssl3_IsECCEnabled must be
- * called before this function. It looks to see if we have a token which
- * is capable of doing smaller than SuiteB curves. If the token can, we
- * presume the token can do the whole SSL suite of curves. If it can't we
- * presume the token that allowed ECC to be enabled can only do suite B
- * curves. */
-static PRBool
-ssl3_SuiteBOnly(sslSocket *ss)
-{
-    /* See if we can support small curves (like 163). If not, assume we can
-     * only support Suite-B curves (P-256, P-384, P-521). */
-    PK11SlotInfo *slot =
-        PK11_GetBestSlotWithAttributes(CKM_ECDH1_DERIVE, 0, 163,
-                                       ss ? ss->pkcs11PinArg : NULL);
-
-    if (!slot) {
-        /* nope, presume we can only do suite B */
-        return PR_TRUE;
-    }
-    /* we can, presume we can do all curves */
-    PK11_FreeSlot(slot);
-    return PR_FALSE;
-}
-
-#define APPEND_CURVE(CURVE_ID)                                       \
-    if ((NSS_GetAlgorithmPolicy(ecName2OIDTag[CURVE_ID], &policy) == \
-         SECFailure) ||                                              \
-        (policy & NSS_USE_ALG_IN_SSL_KX)) {                          \
-        enabledCurves[pos++] = 0;                                    \
-        enabledCurves[pos++] = CURVE_ID;                             \
-    }
-
-/* Send our "canned" (precompiled) Supported Elliptic Curves extension,
- * which says that we support all TLS-defined named curves.
- */
-PRInt32
-ssl3_SendSupportedCurvesXtn(
-    sslSocket *ss,
-    PRBool append,
-    PRUint32 maxBytes)
-{
-    unsigned char enabledCurves[64];
-    PRUint32 policy;
-    PRInt32 extension_length;
-    PRInt32 ecListSize = 0;
-    unsigned int pos = 0;
-    unsigned int i;
-
-    if (!ss || !ssl3_IsECCEnabled(ss))
-        return 0;
-
-    PORT_Assert(sizeof(enabledCurves) > sizeof(tlsECList) * 2);
-    if (ssl3_SuiteBOnly(ss)) {
-        for (i = 0; i < sizeof(suiteBECList); i++) {
-            APPEND_CURVE(suiteBECList[i]);
-        }
-        ecListSize = pos;
-    } else {
-        for (i = 0; i < sizeof(tlsECList); i++) {
-            APPEND_CURVE(tlsECList[i]);
-        }
-        ecListSize = pos;
-    }
-    extension_length =
-        2 /* extension type */ +
-        2 /* extension length */ +
-        2 /* elliptic curves length */ +
-        ecListSize;
-
-    if (maxBytes < (PRUint32)extension_length) {
-        return 0;
-    }
-
-    if (append) {
-        SECStatus rv;
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_elliptic_curves_xtn, 2);
-        if (rv != SECSuccess)
-            return -1;
-        rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
-        if (rv != SECSuccess)
-            return -1;
-        rv = ssl3_AppendHandshakeVariable(ss, enabledCurves, ecListSize, 2);
-        if (rv != SECSuccess)
-            return -1;
-        if (!ss->sec.isServer) {
-            TLSExtensionData *xtnData = &ss->xtnData;
-            xtnData->advertised[xtnData->numAdvertised++] =
-                ssl_elliptic_curves_xtn;
-        }
-    }
-    return extension_length;
-}
-
-PRUint32
-ssl3_GetSupportedECCurveMask(sslSocket *ss)
-{
-    int i;
-    PRUint32 curves = 0;
-    PRUint32 policyFlags = 0;
-
-    PORT_Assert(ec_pastLastName < sizeof(PRUint32) * 8);
-
-    if (ssl3_SuiteBOnly(ss)) {
-        curves = SSL3_SUITE_B_SUPPORTED_CURVES_MASK;
-    } else {
-        curves = SSL3_ALL_SUPPORTED_CURVES_MASK;
-    }
-
-    for (i = ec_noName + 1; i < ec_pastLastName; i++) {
-        PRUint32 curve_bit = (1U << i);
-        if ((curves & curve_bit) &&
-            (NSS_GetAlgorithmPolicy(ecName2OIDTag[i], &policyFlags) ==
-             SECSuccess) &&
-            !(policyFlags & NSS_USE_ALG_IN_SSL_KX)) {
-            curves &= ~curve_bit;
-        }
-    }
-    return curves;
-}
-
-/* Send our "canned" (precompiled) Supported Point Formats extension,
- * which says that we only support uncompressed points.
- */
-PRInt32
-ssl3_SendSupportedPointFormatsXtn(
-    sslSocket *ss,
-    PRBool append,
-    PRUint32 maxBytes)
-{
-    if (!ss || !ssl3_IsECCEnabled(ss))
-        return 0;
-    if (append && maxBytes >= (sizeof ecPtFmt)) {
-        SECStatus rv = ssl3_AppendHandshake(ss, ecPtFmt, (sizeof ecPtFmt));
-        if (rv != SECSuccess)
-            return -1;
-        if (!ss->sec.isServer) {
-            TLSExtensionData *xtnData = &ss->xtnData;
-            xtnData->advertised[xtnData->numAdvertised++] =
-                ssl_ec_point_formats_xtn;
-        }
-    }
-    return (sizeof ecPtFmt);
-}
-
-/* Just make sure that the remote client supports uncompressed points,
- * Since that is all we support.  Disable ECC cipher suites if it doesn't.
- */
-SECStatus
-ssl3_HandleSupportedPointFormatsXtn(sslSocket *ss, PRUint16 ex_type,
-                                    SECItem *data)
-{
-    int i;
-
-    if (data->len < 2 || data->len > 255 || !data->data ||
-        data->len != (unsigned int)data->data[0] + 1) {
-        return ssl3_DecodeError(ss);
-    }
-    for (i = data->len; --i > 0;) {
-        if (data->data[i] == 0) {
-            /* indicate that we should send a reply */
-            SECStatus rv;
-            rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
-                                                         &ssl3_SendSupportedPointFormatsXtn);
-            return rv;
-        }
-    }
-
-    /* evil client doesn't support uncompressed */
-    ssl3_DisableECCSuites(ss, ecSuites);
-    return SECSuccess;
-}
-
-#define SSL3_GET_SERVER_PUBLICKEY(sock, type)                                          \
-    (ss->serverCerts[type].serverKeyPair ? ss->serverCerts[type].serverKeyPair->pubKey \
-                                         : NULL)
-
-/* Extract the TLS curve name for the public key in our EC server cert. */
-ECName
-ssl3_GetSvrCertCurveName(sslSocket *ss)
-{
-    SECKEYPublicKey *srvPublicKey;
-    ECName ec_curve = ec_noName;
-
-    srvPublicKey = SSL3_GET_SERVER_PUBLICKEY(ss, kt_ecdh);
-    if (srvPublicKey) {
-        ec_curve = ssl3_PubKey2ECName(srvPublicKey);
-    }
-    return ec_curve;
-}
-
-/* Ensure that the curve in our server cert is one of the ones supported
- * by the remote client, and disable all ECC cipher suites if not.
- */
-SECStatus
-ssl3_HandleSupportedCurvesXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
-{
-    PRInt32 list_len;
-    PRUint32 peerCurves = 0;
-    PRUint32 mutualCurves = 0;
-    PRUint16 svrCertCurveName;
-
-    if (!data->data || data->len < 4) {
-        (void)ssl3_DecodeError(ss);
-        return SECFailure;
-    }
-
-    /* get the length of elliptic_curve_list */
-    list_len = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
-    if (list_len < 0 || data->len != list_len || (data->len % 2) != 0) {
-        (void)ssl3_DecodeError(ss);
-        return SECFailure;
-    }
-    /* build bit vector of peer's supported curve names */
-    while (data->len) {
-        PRInt32 curve_name =
-            ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
-        if (curve_name < 0) {
-            return SECFailure; /* fatal alert already sent */
-        }
-        if (curve_name > ec_noName && curve_name < ec_pastLastName) {
-            peerCurves |= (1U << curve_name);
-        }
-    }
-    /* What curves do we support in common? */
-    mutualCurves = ss->ssl3.hs.negotiatedECCurves &= peerCurves;
-    if (!mutualCurves) {
-        /* no mutually supported EC Curves, disable ECC */
-        ssl3_DisableECCSuites(ss, ecSuites);
-        return SECSuccess;
-    }
-
-    /* if our ECC cert doesn't use one of these supported curves,
-     * disable ECC cipher suites that require an ECC cert.
-     */
-    svrCertCurveName = ssl3_GetSvrCertCurveName(ss);
-    if (svrCertCurveName != ec_noName &&
-        (mutualCurves & (1U << svrCertCurveName)) != 0) {
-        return SECSuccess;
-    }
-    /* Our EC cert doesn't contain a mutually supported curve.
-     * Disable all ECC cipher suites that require an EC cert
-     */
-    ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites);
-    ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites);
-    return SECSuccess;
-}
-
-#endif /* NSS_DISABLE_ECC */
diff --git a/net/third_party/nss/ssl/ssl3ext.c b/net/third_party/nss/ssl/ssl3ext.c
deleted file mode 100644
index 3b48c9e..0000000
--- a/net/third_party/nss/ssl/ssl3ext.c
+++ /dev/null
@@ -1,3290 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * SSL3 Protocol
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* TLS extension code moved here from ssl3ecc.c */
-
-#include "nssrenam.h"
-#include "nss.h"
-#include "ssl.h"
-#include "sslproto.h"
-#include "sslimpl.h"
-#include "pk11pub.h"
-#ifdef NO_PKCS11_BYPASS
-#include "blapit.h"
-#else
-#include "blapi.h"
-#endif
-#include "prinit.h"
-
-static unsigned char key_name[SESS_TICKET_KEY_NAME_LEN];
-static PK11SymKey *session_ticket_enc_key_pkcs11 = NULL;
-static PK11SymKey *session_ticket_mac_key_pkcs11 = NULL;
-
-#ifndef NO_PKCS11_BYPASS
-static unsigned char session_ticket_enc_key[AES_256_KEY_LENGTH];
-static unsigned char session_ticket_mac_key[SHA256_LENGTH];
-
-static PRBool session_ticket_keys_initialized = PR_FALSE;
-#endif
-static PRCallOnceType generate_session_keys_once;
-
-/* forward static function declarations */
-static SECStatus ssl3_ParseEncryptedSessionTicket(sslSocket *ss,
-                                                  SECItem *data, EncryptedSessionTicket *enc_session_ticket);
-static SECStatus ssl3_AppendToItem(SECItem *item, const unsigned char *buf,
-                                   PRUint32 bytes);
-static SECStatus ssl3_AppendNumberToItem(SECItem *item, PRUint32 num,
-                                         PRInt32 lenSize);
-static SECStatus ssl3_GetSessionTicketKeysPKCS11(sslSocket *ss,
-                                                 PK11SymKey **aes_key, PK11SymKey **mac_key);
-#ifndef NO_PKCS11_BYPASS
-static SECStatus ssl3_GetSessionTicketKeys(const unsigned char **aes_key,
-                                           PRUint32 *aes_key_length, const unsigned char **mac_key,
-                                           PRUint32 *mac_key_length);
-#endif
-static PRInt32 ssl3_SendRenegotiationInfoXtn(sslSocket *ss,
-                                             PRBool append, PRUint32 maxBytes);
-static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss,
-                                                 PRUint16 ex_type, SECItem *data);
-static SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss,
-                                                   PRUint16 ex_type, SECItem *data);
-static SECStatus ssl3_ClientHandleAppProtoXtn(sslSocket *ss,
-                                              PRUint16 ex_type, SECItem *data);
-static SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss,
-                                                   PRUint16 ex_type, SECItem *data);
-static SECStatus ssl3_ServerHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type,
-                                              SECItem *data);
-static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append,
-                                               PRUint32 maxBytes);
-static PRInt32 ssl3_ClientSendAppProtoXtn(sslSocket *ss, PRBool append,
-                                          PRUint32 maxBytes);
-static PRInt32 ssl3_ServerSendAppProtoXtn(sslSocket *ss, PRBool append,
-                                          PRUint32 maxBytes);
-static PRInt32 ssl3_ClientSendUseSRTPXtn(sslSocket *ss, PRBool append,
-                                         PRUint32 maxBytes);
-static PRInt32 ssl3_ServerSendUseSRTPXtn(sslSocket *ss, PRBool append,
-                                         PRUint32 maxBytes);
-static SECStatus ssl3_ClientHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type,
-                                             SECItem *data);
-static SECStatus ssl3_ServerHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type,
-                                             SECItem *data);
-static SECStatus ssl3_ClientHandleChannelIDXtn(sslSocket *ss,
-                                               PRUint16 ex_type, SECItem *data);
-static PRInt32 ssl3_ClientSendChannelIDXtn(sslSocket *ss, PRBool append,
-                                           PRUint32 maxBytes);
-static PRInt32 ssl3_ServerSendStatusRequestXtn(sslSocket *ss,
-                                               PRBool append, PRUint32 maxBytes);
-static SECStatus ssl3_ServerHandleStatusRequestXtn(sslSocket *ss,
-                                                   PRUint16 ex_type, SECItem *data);
-static SECStatus ssl3_ClientHandleStatusRequestXtn(sslSocket *ss,
-                                                   PRUint16 ex_type,
-                                                   SECItem *data);
-static PRInt32 ssl3_ClientSendStatusRequestXtn(sslSocket *ss, PRBool append,
-                                               PRUint32 maxBytes);
-static PRInt32 ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append,
-                                         PRUint32 maxBytes);
-static SECStatus ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type,
-                                             SECItem *data);
-
-static PRInt32 ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss,
-                                                     PRBool append,
-                                                     PRUint32 maxBytes);
-static SECStatus ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss,
-                                                         PRUint16 ex_type,
-                                                         SECItem *data);
-static PRInt32 ssl3_ServerSendSignedCertTimestampXtn(sslSocket *ss,
-                                                     PRBool append,
-                                                     PRUint32 maxBytes);
-static SECStatus ssl3_ServerHandleSignedCertTimestampXtn(sslSocket *ss,
-                                                         PRUint16 ex_type,
-                                                         SECItem *data);
-static PRInt32 ssl3_ClientSendDraftVersionXtn(sslSocket *ss, PRBool append,
-                                              PRUint32 maxBytes);
-static SECStatus ssl3_ServerHandleDraftVersionXtn(sslSocket *ss, PRUint16 ex_type,
-                                                  SECItem *data);
-static PRInt32 ssl3_SendExtendedMasterSecretXtn(sslSocket *ss, PRBool append,
-                                                PRUint32 maxBytes);
-static SECStatus ssl3_HandleExtendedMasterSecretXtn(sslSocket *ss,
-                                                    PRUint16 ex_type,
-                                                    SECItem *data);
-static PRInt32 tls13_ClientSendKeyShareXtn(sslSocket *ss, PRBool append,
-                                           PRUint32 maxBytes);
-static SECStatus tls13_ClientHandleKeyShareXtn(sslSocket *ss,
-                                               PRUint16 ex_type,
-                                               SECItem *data);
-static SECStatus tls13_ServerHandleKeyShareXtn(sslSocket *ss,
-                                               PRUint16 ex_type,
-                                               SECItem *data);
-
-/*
- * Write bytes.  Using this function means the SECItem structure
- * cannot be freed.  The caller is expected to call this function
- * on a shallow copy of the structure.
- */
-static SECStatus
-ssl3_AppendToItem(SECItem *item, const unsigned char *buf, PRUint32 bytes)
-{
-    if (bytes > item->len)
-        return SECFailure;
-
-    PORT_Memcpy(item->data, buf, bytes);
-    item->data += bytes;
-    item->len -= bytes;
-    return SECSuccess;
-}
-
-/*
- * Write a number in network byte order. Using this function means the
- * SECItem structure cannot be freed.  The caller is expected to call
- * this function on a shallow copy of the structure.
- */
-static SECStatus
-ssl3_AppendNumberToItem(SECItem *item, PRUint32 num, PRInt32 lenSize)
-{
-    SECStatus rv;
-    PRUint8 b[4];
-    PRUint8 *p = b;
-
-    switch (lenSize) {
-        case 4:
-            *p++ = (PRUint8)(num >> 24);
-        case 3:
-            *p++ = (PRUint8)(num >> 16);
-        case 2:
-            *p++ = (PRUint8)(num >> 8);
-        case 1:
-            *p = (PRUint8)num;
-    }
-    rv = ssl3_AppendToItem(item, &b[0], lenSize);
-    return rv;
-}
-
-static SECStatus
-ssl3_SessionTicketShutdown(void *appData, void *nssData)
-{
-    if (session_ticket_enc_key_pkcs11) {
-        PK11_FreeSymKey(session_ticket_enc_key_pkcs11);
-        session_ticket_enc_key_pkcs11 = NULL;
-    }
-    if (session_ticket_mac_key_pkcs11) {
-        PK11_FreeSymKey(session_ticket_mac_key_pkcs11);
-        session_ticket_mac_key_pkcs11 = NULL;
-    }
-    PORT_Memset(&generate_session_keys_once, 0,
-                sizeof(generate_session_keys_once));
-    return SECSuccess;
-}
-
-static PRStatus
-ssl3_GenerateSessionTicketKeysPKCS11(void *data)
-{
-    SECStatus rv;
-    sslSocket *ss = (sslSocket *)data;
-    SECKEYPrivateKey *svrPrivKey = ss->serverCerts[kt_rsa].SERVERKEY;
-    SECKEYPublicKey *svrPubKey = ss->serverCerts[kt_rsa].serverKeyPair->pubKey;
-
-    if (svrPrivKey == NULL || svrPubKey == NULL) {
-        SSL_DBG(("%d: SSL[%d]: Pub or priv key(s) is NULL.",
-                 SSL_GETPID(), ss->fd));
-        goto loser;
-    }
-
-    /* Get a copy of the session keys from shared memory. */
-    PORT_Memcpy(key_name, SESS_TICKET_KEY_NAME_PREFIX,
-                sizeof(SESS_TICKET_KEY_NAME_PREFIX));
-    if (!ssl_GetSessionTicketKeysPKCS11(svrPrivKey, svrPubKey,
-                                        ss->pkcs11PinArg, &key_name[SESS_TICKET_KEY_NAME_PREFIX_LEN],
-                                        &session_ticket_enc_key_pkcs11, &session_ticket_mac_key_pkcs11))
-        return PR_FAILURE;
-
-    rv = NSS_RegisterShutdown(ssl3_SessionTicketShutdown, NULL);
-    if (rv != SECSuccess)
-        goto loser;
-
-    return PR_SUCCESS;
-
-loser:
-    ssl3_SessionTicketShutdown(NULL, NULL);
-    return PR_FAILURE;
-}
-
-static SECStatus
-ssl3_GetSessionTicketKeysPKCS11(sslSocket *ss, PK11SymKey **aes_key,
-                                PK11SymKey **mac_key)
-{
-    if (PR_CallOnceWithArg(&generate_session_keys_once,
-                           ssl3_GenerateSessionTicketKeysPKCS11, ss) !=
-        PR_SUCCESS)
-        return SECFailure;
-
-    if (session_ticket_enc_key_pkcs11 == NULL ||
-        session_ticket_mac_key_pkcs11 == NULL)
-        return SECFailure;
-
-    *aes_key = session_ticket_enc_key_pkcs11;
-    *mac_key = session_ticket_mac_key_pkcs11;
-    return SECSuccess;
-}
-
-#ifndef NO_PKCS11_BYPASS
-static PRStatus
-ssl3_GenerateSessionTicketKeys(void)
-{
-    PORT_Memcpy(key_name, SESS_TICKET_KEY_NAME_PREFIX,
-                sizeof(SESS_TICKET_KEY_NAME_PREFIX));
-
-    if (!ssl_GetSessionTicketKeys(&key_name[SESS_TICKET_KEY_NAME_PREFIX_LEN],
-                                  session_ticket_enc_key, session_ticket_mac_key))
-        return PR_FAILURE;
-
-    session_ticket_keys_initialized = PR_TRUE;
-    return PR_SUCCESS;
-}
-
-static SECStatus
-ssl3_GetSessionTicketKeys(const unsigned char **aes_key,
-                          PRUint32 *aes_key_length, const unsigned char **mac_key,
-                          PRUint32 *mac_key_length)
-{
-    if (PR_CallOnce(&generate_session_keys_once,
-                    ssl3_GenerateSessionTicketKeys) != PR_SUCCESS)
-        return SECFailure;
-
-    if (!session_ticket_keys_initialized)
-        return SECFailure;
-
-    *aes_key = session_ticket_enc_key;
-    *aes_key_length = sizeof(session_ticket_enc_key);
-    *mac_key = session_ticket_mac_key;
-    *mac_key_length = sizeof(session_ticket_mac_key);
-
-    return SECSuccess;
-}
-#endif
-
-/* Table of handlers for received TLS hello extensions, one per extension.
- * In the second generation, this table will be dynamic, and functions
- * will be registered here.
- */
-/* This table is used by the server, to handle client hello extensions. */
-static const ssl3HelloExtensionHandler clientHelloHandlers[] = {
-    { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
-#ifndef NSS_DISABLE_ECC
-    { ssl_elliptic_curves_xtn, &ssl3_HandleSupportedCurvesXtn },
-    { ssl_ec_point_formats_xtn, &ssl3_HandleSupportedPointFormatsXtn },
-#endif
-    { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn },
-    { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
-    { ssl_next_proto_nego_xtn, &ssl3_ServerHandleNextProtoNegoXtn },
-    { ssl_app_layer_protocol_xtn, &ssl3_ServerHandleAppProtoXtn },
-    { ssl_use_srtp_xtn, &ssl3_ServerHandleUseSRTPXtn },
-    { ssl_cert_status_xtn, &ssl3_ServerHandleStatusRequestXtn },
-    { ssl_signature_algorithms_xtn, &ssl3_ServerHandleSigAlgsXtn },
-    { ssl_tls13_draft_version_xtn, &ssl3_ServerHandleDraftVersionXtn },
-    { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn },
-    { ssl_signed_cert_timestamp_xtn, &ssl3_ServerHandleSignedCertTimestampXtn },
-    { ssl_tls13_key_share_xtn, &tls13_ServerHandleKeyShareXtn },
-    { -1, NULL }
-};
-
-/* These two tables are used by the client, to handle server hello
- * extensions. */
-static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
-    { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
-    /* TODO: add a handler for ssl_ec_point_formats_xtn */
-    { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn },
-    { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
-    { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
-    { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn },
-    { ssl_use_srtp_xtn, &ssl3_ClientHandleUseSRTPXtn },
-    { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
-    { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
-    { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn },
-    { ssl_signed_cert_timestamp_xtn, &ssl3_ClientHandleSignedCertTimestampXtn },
-    { ssl_tls13_key_share_xtn, &tls13_ClientHandleKeyShareXtn },
-    { -1, NULL }
-};
-
-static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = {
-    { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
-    { -1, NULL }
-};
-
-/* Tables of functions to format TLS hello extensions, one function per
- * extension.
- * These static tables are for the formatting of client hello extensions.
- * The server's table of hello senders is dynamic, in the socket struct,
- * and sender functions are registered there.
- */
-static const ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] =
-    {
-      { ssl_server_name_xtn, &ssl3_SendServerNameXtn },
-      { ssl_extended_master_secret_xtn, &ssl3_SendExtendedMasterSecretXtn },
-      { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn },
-#ifndef NSS_DISABLE_ECC
-      { ssl_elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn },
-      { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn },
-#endif
-      { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn },
-      { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn },
-      { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn },
-      { ssl_use_srtp_xtn, &ssl3_ClientSendUseSRTPXtn },
-      { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
-      { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
-      { ssl_tls13_draft_version_xtn, &ssl3_ClientSendDraftVersionXtn },
-      { ssl_signed_cert_timestamp_xtn, &ssl3_ClientSendSignedCertTimestampXtn },
-      { ssl_tls13_key_share_xtn, &tls13_ClientSendKeyShareXtn },
-      /* Some servers (e.g. WebSphere Application Server 7.0 and Tomcat) will
-       * time out or terminate the connection if the last extension in the
-       * client hello is empty. They are not intolerant of TLS 1.2, so list
-       * signature_algorithms at the end. See bug 1243641. */
-      { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
-      /* any extra entries will appear as { 0, NULL }    */
-    };
-
-static const ssl3HelloExtensionSender clientHelloSendersSSL3[SSL_MAX_EXTENSIONS] =
-    {
-      { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }
-      /* any extra entries will appear as { 0, NULL }    */
-    };
-
-static PRBool
-arrayContainsExtension(const PRUint16 *array, PRUint32 len, PRUint16 ex_type)
-{
-    unsigned int i;
-    for (i = 0; i < len; i++) {
-        if (ex_type == array[i])
-            return PR_TRUE;
-    }
-    return PR_FALSE;
-}
-
-PRBool
-ssl3_ExtensionNegotiated(sslSocket *ss, PRUint16 ex_type)
-{
-    TLSExtensionData *xtnData = &ss->xtnData;
-    return arrayContainsExtension(xtnData->negotiated,
-                                  xtnData->numNegotiated, ex_type);
-}
-
-static PRBool
-ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type)
-{
-    TLSExtensionData *xtnData = &ss->xtnData;
-    return arrayContainsExtension(xtnData->advertised,
-                                  xtnData->numAdvertised, ex_type);
-}
-
-/* Format an SNI extension, using the name from the socket's URL,
- * unless that name is a dotted decimal string.
- * Used by client and server.
- */
-PRInt32
-ssl3_SendServerNameXtn(sslSocket *ss, PRBool append,
-                       PRUint32 maxBytes)
-{
-    SECStatus rv;
-    if (!ss)
-        return 0;
-    if (!ss->sec.isServer) {
-        PRUint32 len;
-        PRNetAddr netAddr;
-
-        /* must have a hostname */
-        if (!ss->url || !ss->url[0])
-            return 0;
-        /* must not be an IPv4 or IPv6 address */
-        if (PR_SUCCESS == PR_StringToNetAddr(ss->url, &netAddr)) {
-            /* is an IP address (v4 or v6) */
-            return 0;
-        }
-        len = PORT_Strlen(ss->url);
-        if (append && maxBytes >= len + 9) {
-            /* extension_type */
-            rv = ssl3_AppendHandshakeNumber(ss, ssl_server_name_xtn, 2);
-            if (rv != SECSuccess)
-                return -1;
-            /* length of extension_data */
-            rv = ssl3_AppendHandshakeNumber(ss, len + 5, 2);
-            if (rv != SECSuccess)
-                return -1;
-            /* length of server_name_list */
-            rv = ssl3_AppendHandshakeNumber(ss, len + 3, 2);
-            if (rv != SECSuccess)
-                return -1;
-            /* Name Type (sni_host_name) */
-            rv = ssl3_AppendHandshake(ss, "\0", 1);
-            if (rv != SECSuccess)
-                return -1;
-            /* HostName (length and value) */
-            rv = ssl3_AppendHandshakeVariable(ss, (PRUint8 *)ss->url, len, 2);
-            if (rv != SECSuccess)
-                return -1;
-            if (!ss->sec.isServer) {
-                TLSExtensionData *xtnData = &ss->xtnData;
-                xtnData->advertised[xtnData->numAdvertised++] =
-                    ssl_server_name_xtn;
-            }
-        }
-        return len + 9;
-    }
-    /* Server side */
-    if (append && maxBytes >= 4) {
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_server_name_xtn, 2);
-        if (rv != SECSuccess)
-            return -1;
-        /* length of extension_data */
-        rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
-        if (rv != SECSuccess)
-            return -1;
-    }
-    return 4;
-}
-
-/* handle an incoming SNI extension, by ignoring it. */
-SECStatus
-ssl3_HandleServerNameXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
-{
-    SECItem *names = NULL;
-    PRUint32 listCount = 0, namesPos = 0, i;
-    TLSExtensionData *xtnData = &ss->xtnData;
-    SECItem ldata;
-    PRInt32 listLenBytes = 0;
-
-    if (!ss->sec.isServer) {
-        return SECSuccess; /* ignore extension */
-    }
-
-    /* Server side - consume client data and register server sender. */
-    /* do not parse the data if don't have user extension handling function. */
-    if (!ss->sniSocketConfig) {
-        return SECSuccess;
-    }
-    /* length of server_name_list */
-    listLenBytes = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
-    if (listLenBytes < 0) {
-        return SECFailure;
-    }
-    if (listLenBytes == 0 || listLenBytes != data->len) {
-        (void)ssl3_DecodeError(ss);
-        return SECFailure;
-    }
-    ldata = *data;
-    /* Calculate the size of the array.*/
-    while (listLenBytes > 0) {
-        SECItem litem;
-        SECStatus rv;
-        PRInt32 type;
-        /* Skip Name Type (sni_host_name); checks are on the second pass */
-        type = ssl3_ConsumeHandshakeNumber(ss, 1, &ldata.data, &ldata.len);
-        if (type < 0) { /* i.e., SECFailure cast to PRint32 */
-            return SECFailure;
-        }
-        rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 2, &ldata.data, &ldata.len);
-        if (rv != SECSuccess) {
-            return rv;
-        }
-        /* Adjust total length for consumed item, item len and type.*/
-        listLenBytes -= litem.len + 3;
-        if (listLenBytes > 0 && !ldata.len) {
-            (void)ssl3_DecodeError(ss);
-            return SECFailure;
-        }
-        listCount += 1;
-    }
-    names = PORT_ZNewArray(SECItem, listCount);
-    if (!names) {
-        return SECFailure;
-    }
-    for (i = 0; i < listCount; i++) {
-        unsigned int j;
-        PRInt32 type;
-        SECStatus rv;
-        PRBool nametypePresent = PR_FALSE;
-        /* Name Type (sni_host_name) */
-        type = ssl3_ConsumeHandshakeNumber(ss, 1, &data->data, &data->len);
-        /* Check if we have such type in the list */
-        for (j = 0; j < listCount && names[j].data; j++) {
-            /* TODO bug 998524: .type is not assigned a value */
-            if (names[j].type == type) {
-                nametypePresent = PR_TRUE;
-                break;
-            }
-        }
-        /* HostName (length and value) */
-        rv = ssl3_ConsumeHandshakeVariable(ss, &names[namesPos], 2,
-                                           &data->data, &data->len);
-        if (rv != SECSuccess) {
-            PORT_Assert(0);
-            PORT_Free(names);
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            return rv;
-        }
-        if (nametypePresent == PR_FALSE) {
-            namesPos += 1;
-        }
-    }
-    /* Free old and set the new data. */
-    if (xtnData->sniNameArr) {
-        PORT_Free(ss->xtnData.sniNameArr);
-    }
-    xtnData->sniNameArr = names;
-    xtnData->sniNameArrSize = namesPos;
-    xtnData->negotiated[xtnData->numNegotiated++] = ssl_server_name_xtn;
-
-    return SECSuccess;
-}
-
-/* Called by both clients and servers.
- * Clients sends a filled in session ticket if one is available, and otherwise
- * sends an empty ticket.  Servers always send empty tickets.
- */
-PRInt32
-ssl3_SendSessionTicketXtn(
-    sslSocket *ss,
-    PRBool append,
-    PRUint32 maxBytes)
-{
-    PRInt32 extension_length;
-    NewSessionTicket *session_ticket = NULL;
-    sslSessionID *sid = ss->sec.ci.sid;
-
-    /* Ignore the SessionTicket extension if processing is disabled. */
-    if (!ss->opt.enableSessionTickets)
-        return 0;
-
-    /* Empty extension length = extension_type (2-bytes) +
-     * length(extension_data) (2-bytes)
-     */
-    extension_length = 4;
-
-    /* If we are a client then send a session ticket if one is availble.
-     * Servers that support the extension and are willing to negotiate the
-     * the extension always respond with an empty extension.
-     */
-    if (!ss->sec.isServer) {
-        /* The caller must be holding sid->u.ssl3.lock for reading. We cannot
-         * just acquire and release the lock within this function because the
-         * caller will call this function twice, and we need the inputs to be
-         * consistent between the two calls. Note that currently the caller
-         * will only be holding the lock when we are the client and when we're
-         * attempting to resume an existing session.
-         */
-
-        session_ticket = &sid->u.ssl3.locked.sessionTicket;
-        if (session_ticket->ticket.data) {
-            if (ss->xtnData.ticketTimestampVerified) {
-                extension_length += session_ticket->ticket.len;
-            } else if (!append &&
-                       (session_ticket->ticket_lifetime_hint == 0 ||
-                        (session_ticket->ticket_lifetime_hint +
-                             session_ticket->received_timestamp >
-                         ssl_Time()))) {
-                extension_length += session_ticket->ticket.len;
-                ss->xtnData.ticketTimestampVerified = PR_TRUE;
-            }
-        }
-    }
-
-    if (maxBytes < (PRUint32)extension_length) {
-        PORT_Assert(0);
-        return 0;
-    }
-    if (append) {
-        SECStatus rv;
-        /* extension_type */
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_session_ticket_xtn, 2);
-        if (rv != SECSuccess)
-            goto loser;
-        if (session_ticket && session_ticket->ticket.data &&
-            ss->xtnData.ticketTimestampVerified) {
-            rv = ssl3_AppendHandshakeVariable(ss, session_ticket->ticket.data,
-                                              session_ticket->ticket.len, 2);
-            ss->xtnData.ticketTimestampVerified = PR_FALSE;
-            ss->xtnData.sentSessionTicketInClientHello = PR_TRUE;
-        } else {
-            rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
-        }
-        if (rv != SECSuccess)
-            goto loser;
-
-        if (!ss->sec.isServer) {
-            TLSExtensionData *xtnData = &ss->xtnData;
-            xtnData->advertised[xtnData->numAdvertised++] =
-                ssl_session_ticket_xtn;
-        }
-    }
-    return extension_length;
-
-loser:
-    ss->xtnData.ticketTimestampVerified = PR_FALSE;
-    return -1;
-}
-
-/* handle an incoming Next Protocol Negotiation extension. */
-static SECStatus
-ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
-                                  SECItem *data)
-{
-    if (ss->firstHsDone || data->len != 0) {
-        /* Clients MUST send an empty NPN extension, if any. */
-        PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
-        return SECFailure;
-    }
-
-    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-
-    /* TODO: server side NPN support would require calling
-     * ssl3_RegisterServerHelloExtensionSender here in order to echo the
-     * extension back to the client. */
-
-    return SECSuccess;
-}
-
-/* ssl3_ValidateNextProtoNego checks that the given block of data is valid: none
- * of the lengths may be 0 and the sum of the lengths must equal the length of
- * the block. */
-SECStatus
-ssl3_ValidateNextProtoNego(const unsigned char *data, unsigned int length)
-{
-    unsigned int offset = 0;
-
-    while (offset < length) {
-        unsigned int newOffset = offset + 1 + (unsigned int)data[offset];
-        /* Reject embedded nulls to protect against buggy applications that
-         * store protocol identifiers in null-terminated strings.
-         */
-        if (newOffset > length || data[offset] == 0) {
-            return SECFailure;
-        }
-        offset = newOffset;
-    }
-
-    return SECSuccess;
-}
-
-/* protocol selection handler for ALPN (server side) and NPN (client side) */
-static SECStatus
-ssl3_SelectAppProtocol(sslSocket *ss, PRUint16 ex_type, SECItem *data)
-{
-    SECStatus rv;
-    unsigned char resultBuffer[255];
-    SECItem result = { siBuffer, resultBuffer, 0 };
-
-    rv = ssl3_ValidateNextProtoNego(data->data, data->len);
-    if (rv != SECSuccess) {
-        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
-        PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
-        return rv;
-    }
-
-    PORT_Assert(ss->nextProtoCallback);
-    /* For ALPN, the cipher suite isn't selected yet.  Note that extensions
-     * sometimes affect what cipher suite is selected, e.g., for ECC. */
-    PORT_Assert((ss->ssl3.hs.preliminaryInfo &
-                 ssl_preinfo_all & ~ssl_preinfo_cipher_suite) ==
-                (ssl_preinfo_all & ~ssl_preinfo_cipher_suite));
-    rv = ss->nextProtoCallback(ss->nextProtoArg, ss->fd, data->data, data->len,
-                               result.data, &result.len, sizeof(resultBuffer));
-    if (rv != SECSuccess) {
-        /* Expect callback to call PORT_SetError() */
-        (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
-        return SECFailure;
-    }
-
-    /* If the callback wrote more than allowed to |result| it has corrupted our
-     * stack. */
-    if (result.len > sizeof(resultBuffer)) {
-        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
-        /* TODO: crash */
-        return SECFailure;
-    }
-
-    SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
-
-    if (ex_type == ssl_app_layer_protocol_xtn &&
-        ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NEGOTIATED) {
-        /* The callback might say OK, but then it picks a default value - one
-         * that was not listed.  That's OK for NPN, but not ALPN. */
-        (void)SSL3_SendAlert(ss, alert_fatal, no_application_protocol);
-        PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL);
-        return SECFailure;
-    }
-
-    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-    return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &result);
-}
-
-/* handle an incoming ALPN extension at the server */
-static SECStatus
-ssl3_ServerHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
-{
-    int count;
-    SECStatus rv;
-
-    /* We expressly don't want to allow ALPN on renegotiation,
-     * despite it being permitted by the spec. */
-    if (ss->firstHsDone || data->len == 0) {
-        /* Clients MUST send a non-empty ALPN extension. */
-        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
-        PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
-        return SECFailure;
-    }
-
-    /* Unlike NPN, ALPN has extra redundant length information so that
-     * the extension is the same in both ClientHello and ServerHello. */
-    count = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
-    if (count != data->len) {
-        (void)ssl3_DecodeError(ss);
-        return SECFailure;
-    }
-
-    if (!ss->nextProtoCallback) {
-        /* we're not configured for it */
-        return SECSuccess;
-    }
-
-    rv = ssl3_SelectAppProtocol(ss, ex_type, data);
-    if (rv != SECSuccess) {
-        return rv;
-    }
-
-    /* prepare to send back a response, if we negotiated */
-    if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NEGOTIATED) {
-        rv = ssl3_RegisterServerHelloExtensionSender(
-            ss, ex_type, ssl3_ServerSendAppProtoXtn);
-        if (rv != SECSuccess) {
-            (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            return rv;
-        }
-    }
-    return SECSuccess;
-}
-
-static SECStatus
-ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
-                                  SECItem *data)
-{
-    PORT_Assert(!ss->firstHsDone);
-
-    if (ssl3_ExtensionNegotiated(ss, ssl_app_layer_protocol_xtn)) {
-        /* If the server negotiated ALPN then it has already told us what
-         * protocol to use, so it doesn't make sense for us to try to negotiate
-         * a different one by sending the NPN handshake message. However, if
-         * we've negotiated NPN then we're required to send the NPN handshake
-         * message. Thus, these two extensions cannot both be negotiated on the
-         * same connection. */
-        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
-        PORT_SetError(SSL_ERROR_BAD_SERVER);
-        return SECFailure;
-    }
-
-    /* We should only get this call if we sent the extension, so
-     * ss->nextProtoCallback needs to be non-NULL.  However, it is possible
-     * that an application erroneously cleared the callback between the time
-     * we sent the ClientHello and now. */
-    if (!ss->nextProtoCallback) {
-        PORT_Assert(0);
-        (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
-        PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK);
-        return SECFailure;
-    }
-
-    return ssl3_SelectAppProtocol(ss, ex_type, data);
-}
-
-static SECStatus
-ssl3_ClientHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
-{
-    SECStatus rv;
-    PRInt32 list_len;
-    SECItem protocol_name;
-
-    if (ssl3_ExtensionNegotiated(ss, ssl_next_proto_nego_xtn)) {
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        return SECFailure;
-    }
-
-    /* The extension data from the server has the following format:
-     *   uint16 name_list_len;
-     *   uint8 len;  // where len >= 1
-     *   uint8 protocol_name[len]; */
-    if (data->len < 4 || data->len > 2 + 1 + 255) {
-        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
-        PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
-        return SECFailure;
-    }
-
-    list_len = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
-    /* The list has to be the entire extension. */
-    if (list_len != data->len) {
-        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
-        PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
-        return SECFailure;
-    }
-
-    rv = ssl3_ConsumeHandshakeVariable(ss, &protocol_name, 1,
-                                       &data->data, &data->len);
-    /* The list must have exactly one value. */
-    if (rv != SECSuccess || data->len != 0) {
-        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
-        PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
-        return SECFailure;
-    }
-
-    SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
-    ss->ssl3.nextProtoState = SSL_NEXT_PROTO_SELECTED;
-    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-    return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &protocol_name);
-}
-
-static PRInt32
-ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append,
-                                PRUint32 maxBytes)
-{
-    PRInt32 extension_length;
-
-    /* Renegotiations do not send this extension. */
-    if (!ss->opt.enableNPN || !ss->nextProtoCallback || ss->firstHsDone) {
-        return 0;
-    }
-
-    extension_length = 4;
-
-    if (maxBytes < (PRUint32)extension_length) {
-        return 0;
-    }
-    if (append) {
-        SECStatus rv;
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_next_proto_nego_xtn, 2);
-        if (rv != SECSuccess)
-            goto loser;
-        rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
-        if (rv != SECSuccess)
-            goto loser;
-        ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
-            ssl_next_proto_nego_xtn;
-    }
-
-    return extension_length;
-
-loser:
-    return -1;
-}
-
-static PRInt32
-ssl3_ClientSendAppProtoXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
-{
-    PRInt32 extension_length;
-    unsigned char *alpn_protos = NULL;
-
-    /* Renegotiations do not send this extension. */
-    if (!ss->opt.enableALPN || !ss->opt.nextProtoNego.data || ss->firstHsDone) {
-        return 0;
-    }
-
-    extension_length = 2 /* extension type */ + 2 /* extension length */ +
-                       2 /* protocol name list length */ +
-                       ss->opt.nextProtoNego.len;
-
-    if (maxBytes < (PRUint32)extension_length) {
-        return 0;
-    }
-    if (append) {
-        /* NPN requires that the client's fallback protocol is first in the
-         * list. However, ALPN sends protocols in preference order. So we
-         * allocate a buffer and move the first protocol to the end of the
-         * list. */
-        SECStatus rv;
-        const unsigned int len = ss->opt.nextProtoNego.len;
-
-        alpn_protos = PORT_Alloc(len);
-        if (alpn_protos == NULL) {
-            return SECFailure;
-        }
-        if (len > 0) {
-            /* Each protocol string is prefixed with a single byte length. */
-            unsigned int i = ss->opt.nextProtoNego.data[0] + 1;
-            if (i <= len) {
-                memcpy(alpn_protos, &ss->opt.nextProtoNego.data[i], len - i);
-                memcpy(alpn_protos + len - i, ss->opt.nextProtoNego.data, i);
-            } else {
-                /* This seems to be invalid data so we'll send as-is. */
-                memcpy(alpn_protos, ss->opt.nextProtoNego.data, len);
-            }
-        }
-
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2);
-        if (rv != SECSuccess) {
-            goto loser;
-        }
-        rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
-        if (rv != SECSuccess) {
-            goto loser;
-        }
-        rv = ssl3_AppendHandshakeVariable(ss, alpn_protos, len, 2);
-        PORT_Free(alpn_protos);
-        alpn_protos = NULL;
-        if (rv != SECSuccess) {
-            goto loser;
-        }
-        ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
-            ssl_app_layer_protocol_xtn;
-    }
-
-    return extension_length;
-
-loser:
-    if (alpn_protos) {
-        PORT_Free(alpn_protos);
-    }
-    return -1;
-}
-
-static PRInt32
-ssl3_ServerSendAppProtoXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
-{
-    PRInt32 extension_length;
-
-    /* we're in over our heads if any of these fail */
-    PORT_Assert(ss->opt.enableALPN);
-    PORT_Assert(ss->ssl3.nextProto.data);
-    PORT_Assert(ss->ssl3.nextProto.len > 0);
-    PORT_Assert(ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NEGOTIATED);
-    PORT_Assert(!ss->firstHsDone);
-
-    extension_length = 2 /* extension type */ + 2 /* extension length */ +
-                       2 /* protocol name list */ + 1 /* name length */ +
-                       ss->ssl3.nextProto.len;
-
-    if (maxBytes < (PRUint32)extension_length) {
-        return 0;
-    }
-    if (append) {
-        SECStatus rv;
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2);
-        if (rv != SECSuccess) {
-            return -1;
-        }
-        rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
-        if (rv != SECSuccess) {
-            return -1;
-        }
-        rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.nextProto.len + 1, 2);
-        if (rv != SECSuccess) {
-            return -1;
-        }
-        rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.nextProto.data,
-                                          ss->ssl3.nextProto.len, 1);
-        if (rv != SECSuccess) {
-            return -1;
-        }
-    }
-
-    return extension_length;
-}
-
-static SECStatus
-ssl3_ClientHandleChannelIDXtn(sslSocket *ss, PRUint16 ex_type,
-                              SECItem *data)
-{
-    PORT_Assert(ss->getChannelID != NULL);
-
-    if (data->len) {
-        PORT_SetError(SSL_ERROR_BAD_CHANNEL_ID_DATA);
-        return SECFailure;
-    }
-    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-    return SECSuccess;
-}
-
-static PRInt32
-ssl3_ClientSendChannelIDXtn(sslSocket *ss, PRBool append,
-                            PRUint32 maxBytes)
-{
-    PRInt32 extension_length = 4;
-
-    if (!ss->getChannelID)
-        return 0;
-
-    if (maxBytes < extension_length) {
-        PORT_Assert(0);
-        return 0;
-    }
-
-    if (ss->sec.ci.sid->cached != never_cached &&
-        ss->sec.ci.sid->u.ssl3.originalHandshakeHash.len == 0) {
-        /* We can't do ChannelID on a connection if we're resuming and didn't
-         * do ChannelID on the original connection: without ChannelID on the
-         * original connection we didn't record the handshake hashes needed for
-         * the signature. */
-        return 0;
-    }
-
-    if (append) {
-        SECStatus rv;
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2);
-        if (rv != SECSuccess)
-            goto loser;
-        rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
-        if (rv != SECSuccess)
-            goto loser;
-        ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
-            ssl_channel_id_xtn;
-    }
-
-    return extension_length;
-
-loser:
-    return -1;
-}
-
-static SECStatus
-ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type,
-                                  SECItem *data)
-{
-    /* The echoed extension must be empty. */
-    if (data->len != 0) {
-        return SECSuccess; /* Ignore the extension. */
-    }
-
-    /* Keep track of negotiated extensions. */
-    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-
-    return SECSuccess;
-}
-
-static PRInt32
-ssl3_ServerSendStatusRequestXtn(
-    sslSocket *ss,
-    PRBool append,
-    PRUint32 maxBytes)
-{
-    PRInt32 extension_length;
-    SSLKEAType effectiveExchKeyType;
-    SECStatus rv;
-
-    /* ssl3_SendCertificateStatus (which sents the certificate status data)
-     * uses the exact same logic to select the server certificate
-     * and determine if we have the status for that certificate. */
-
-    if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa ||
-        ss->ssl3.hs.kea_def->kea == kea_dhe_rsa) {
-        effectiveExchKeyType = ssl_kea_rsa;
-    } else {
-        effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType;
-    }
-
-    if (!ss->certStatusArray[effectiveExchKeyType] ||
-        !ss->certStatusArray[effectiveExchKeyType]->len) {
-        return 0;
-    }
-
-    extension_length = 2 + 2;
-    if (maxBytes < (PRUint32)extension_length) {
-        return 0;
-    }
-    if (append) {
-        /* extension_type */
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_cert_status_xtn, 2);
-        if (rv != SECSuccess)
-            return -1;
-        /* length of extension_data */
-        rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
-        if (rv != SECSuccess)
-            return -1;
-        /* The certificate status data is sent in ssl3_SendCertificateStatus. */
-    }
-
-    return extension_length;
-}
-
-/* ssl3_ClientSendStatusRequestXtn builds the status_request extension on the
- * client side. See RFC 4366 section 3.6. */
-static PRInt32
-ssl3_ClientSendStatusRequestXtn(sslSocket *ss, PRBool append,
-                                PRUint32 maxBytes)
-{
-    PRInt32 extension_length;
-
-    if (!ss->opt.enableOCSPStapling)
-        return 0;
-
-    /* extension_type (2-bytes) +
-     * length(extension_data) (2-bytes) +
-     * status_type (1) +
-     * responder_id_list length (2) +
-     * request_extensions length (2)
-     */
-    extension_length = 9;
-
-    if (maxBytes < (PRUint32)extension_length) {
-        PORT_Assert(0);
-        return 0;
-    }
-    if (append) {
-        SECStatus rv;
-        TLSExtensionData *xtnData;
-
-        /* extension_type */
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_cert_status_xtn, 2);
-        if (rv != SECSuccess)
-            return -1;
-        rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
-        if (rv != SECSuccess)
-            return -1;
-        rv = ssl3_AppendHandshakeNumber(ss, 1 /* status_type ocsp */, 1);
-        if (rv != SECSuccess)
-            return -1;
-        /* A zero length responder_id_list means that the responders are
-         * implicitly known to the server. */
-        rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
-        if (rv != SECSuccess)
-            return -1;
-        /* A zero length request_extensions means that there are no extensions.
-         * Specifically, we don't set the id-pkix-ocsp-nonce extension. This
-         * means that the server can replay a cached OCSP response to us. */
-        rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
-        if (rv != SECSuccess)
-            return -1;
-
-        xtnData = &ss->xtnData;
-        xtnData->advertised[xtnData->numAdvertised++] = ssl_cert_status_xtn;
-    }
-    return extension_length;
-}
-
-/*
- * NewSessionTicket
- * Called from ssl3_HandleFinished
- */
-SECStatus
-ssl3_SendNewSessionTicket(sslSocket *ss)
-{
-    PRUint32 i;
-    SECStatus rv;
-    NewSessionTicket ticket;
-    SECItem plaintext;
-    SECItem plaintext_item = { 0, NULL, 0 };
-    SECItem ciphertext = { 0, NULL, 0 };
-    PRUint32 ciphertext_length;
-    PRBool ms_is_wrapped;
-    unsigned char wrapped_ms[SSL3_MASTER_SECRET_LENGTH];
-    SECItem ms_item = { 0, NULL, 0 };
-    SSL3KEAType effectiveExchKeyType = ssl_kea_null;
-    PRUint32 padding_length;
-    PRUint32 message_length;
-    PRUint32 cert_length = 0;
-    PRUint8 length_buf[4];
-    PRUint32 now;
-    PK11SymKey *aes_key_pkcs11;
-    PK11SymKey *mac_key_pkcs11;
-#ifndef NO_PKCS11_BYPASS
-    const unsigned char *aes_key;
-    const unsigned char *mac_key;
-    PRUint32 aes_key_length;
-    PRUint32 mac_key_length;
-    PRUint64 aes_ctx_buf[MAX_CIPHER_CONTEXT_LLONGS];
-    AESContext *aes_ctx;
-    const SECHashObject *hashObj = NULL;
-    PRUint64 hmac_ctx_buf[MAX_MAC_CONTEXT_LLONGS];
-    HMACContext *hmac_ctx;
-#endif
-    CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC;
-    PK11Context *aes_ctx_pkcs11;
-    CK_MECHANISM_TYPE macMech = CKM_SHA256_HMAC;
-    PK11Context *hmac_ctx_pkcs11 = NULL;
-    unsigned char computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH];
-    unsigned int computed_mac_length;
-    unsigned char iv[AES_BLOCK_SIZE];
-    SECItem ivItem;
-    SECItem *srvName = NULL;
-    PRUint32 srvNameLen = 0;
-    CK_MECHANISM_TYPE msWrapMech = 0; /* dummy default value,
-                                          * must be >= 0 */
-
-    SSL_TRC(3, ("%d: SSL3[%d]: send session_ticket handshake",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    ticket.ticket_lifetime_hint = TLS_EX_SESS_TICKET_LIFETIME_HINT;
-    if (ss->opt.requestCertificate && ss->sec.ci.sid->peerCert) {
-        cert_length = 3 + ss->sec.ci.sid->peerCert->derCert.len;
-    }
-
-    /* Get IV and encryption keys */
-    ivItem.data = iv;
-    ivItem.len = sizeof(iv);
-    rv = PK11_GenerateRandom(iv, sizeof(iv));
-    if (rv != SECSuccess)
-        goto loser;
-
-#ifndef NO_PKCS11_BYPASS
-    if (ss->opt.bypassPKCS11) {
-        rv = ssl3_GetSessionTicketKeys(&aes_key, &aes_key_length,
-                                       &mac_key, &mac_key_length);
-    } else
-#endif
-    {
-        rv = ssl3_GetSessionTicketKeysPKCS11(ss, &aes_key_pkcs11,
-                                             &mac_key_pkcs11);
-    }
-    if (rv != SECSuccess)
-        goto loser;
-
-    if (ss->ssl3.pwSpec->msItem.len && ss->ssl3.pwSpec->msItem.data) {
-        /* The master secret is available unwrapped. */
-        ms_item.data = ss->ssl3.pwSpec->msItem.data;
-        ms_item.len = ss->ssl3.pwSpec->msItem.len;
-        ms_is_wrapped = PR_FALSE;
-    } else {
-        /* Extract the master secret wrapped. */
-        sslSessionID sid;
-        PORT_Memset(&sid, 0, sizeof(sslSessionID));
-
-        if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa ||
-            ss->ssl3.hs.kea_def->kea == kea_dhe_rsa) {
-            effectiveExchKeyType = kt_rsa;
-        } else {
-            effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType;
-        }
-
-        rv = ssl3_CacheWrappedMasterSecret(ss, &sid, ss->ssl3.pwSpec,
-                                           effectiveExchKeyType);
-        if (rv == SECSuccess) {
-            if (sid.u.ssl3.keys.wrapped_master_secret_len > sizeof(wrapped_ms))
-                goto loser;
-            memcpy(wrapped_ms, sid.u.ssl3.keys.wrapped_master_secret,
-                   sid.u.ssl3.keys.wrapped_master_secret_len);
-            ms_item.data = wrapped_ms;
-            ms_item.len = sid.u.ssl3.keys.wrapped_master_secret_len;
-            msWrapMech = sid.u.ssl3.masterWrapMech;
-        } else {
-            /* TODO: else send an empty ticket. */
-            goto loser;
-        }
-        ms_is_wrapped = PR_TRUE;
-    }
-    /* Prep to send negotiated name */
-    srvName = &ss->ssl3.pwSpec->srvVirtName;
-    if (srvName->data && srvName->len) {
-        srvNameLen = 2 + srvName->len; /* len bytes + name len */
-    }
-
-    ciphertext_length =
-        sizeof(PRUint16)              /* ticket_version */
-        + sizeof(SSL3ProtocolVersion) /* ssl_version */
-        + sizeof(ssl3CipherSuite)     /* ciphersuite */
-        + 1                           /* compression */
-        + 10                          /* cipher spec parameters */
-        + 1                           /* SessionTicket.ms_is_wrapped */
-        + 1                           /* effectiveExchKeyType */
-        + 4                           /* msWrapMech */
-        + 2                           /* master_secret.length */
-        + ms_item.len                 /* master_secret */
-        + 1                           /* client_auth_type */
-        + cert_length                 /* cert */
-        + 1                           /* server name type */
-        + srvNameLen                  /* name len + length field */
-        + 1                           /* extendedMasterSecretUsed */
-        + sizeof(ticket.ticket_lifetime_hint);
-    padding_length = AES_BLOCK_SIZE -
-                     (ciphertext_length %
-                      AES_BLOCK_SIZE);
-    ciphertext_length += padding_length;
-
-    message_length =
-        sizeof(ticket.ticket_lifetime_hint) /* ticket_lifetime_hint */
-        + 2                                 /* length field for NewSessionTicket.ticket */
-        + SESS_TICKET_KEY_NAME_LEN          /* key_name */
-        + AES_BLOCK_SIZE                    /* iv */
-        + 2                                 /* length field for NewSessionTicket.ticket.encrypted_state */
-        + ciphertext_length                 /* encrypted_state */
-        + TLS_EX_SESS_TICKET_MAC_LENGTH;    /* mac */
-
-    if (SECITEM_AllocItem(NULL, &plaintext_item, ciphertext_length) == NULL)
-        goto loser;
-
-    plaintext = plaintext_item;
-
-    /* ticket_version */
-    rv = ssl3_AppendNumberToItem(&plaintext, TLS_EX_SESS_TICKET_VERSION,
-                                 sizeof(PRUint16));
-    if (rv != SECSuccess)
-        goto loser;
-
-    /* ssl_version */
-    rv = ssl3_AppendNumberToItem(&plaintext, ss->version,
-                                 sizeof(SSL3ProtocolVersion));
-    if (rv != SECSuccess)
-        goto loser;
-
-    /* ciphersuite */
-    rv = ssl3_AppendNumberToItem(&plaintext, ss->ssl3.hs.cipher_suite,
-                                 sizeof(ssl3CipherSuite));
-    if (rv != SECSuccess)
-        goto loser;
-
-    /* compression */
-    rv = ssl3_AppendNumberToItem(&plaintext, ss->ssl3.hs.compression, 1);
-    if (rv != SECSuccess)
-        goto loser;
-
-    /* cipher spec parameters */
-    rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.authAlgorithm, 1);
-    if (rv != SECSuccess)
-        goto loser;
-    rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.authKeyBits, 4);
-    if (rv != SECSuccess)
-        goto loser;
-    rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.keaType, 1);
-    if (rv != SECSuccess)
-        goto loser;
-    rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.keaKeyBits, 4);
-    if (rv != SECSuccess)
-        goto loser;
-
-    /* master_secret */
-    rv = ssl3_AppendNumberToItem(&plaintext, ms_is_wrapped, 1);
-    if (rv != SECSuccess)
-        goto loser;
-    rv = ssl3_AppendNumberToItem(&plaintext, effectiveExchKeyType, 1);
-    if (rv != SECSuccess)
-        goto loser;
-    rv = ssl3_AppendNumberToItem(&plaintext, msWrapMech, 4);
-    if (rv != SECSuccess)
-        goto loser;
-    rv = ssl3_AppendNumberToItem(&plaintext, ms_item.len, 2);
-    if (rv != SECSuccess)
-        goto loser;
-    rv = ssl3_AppendToItem(&plaintext, ms_item.data, ms_item.len);
-    if (rv != SECSuccess)
-        goto loser;
-
-    /* client_identity */
-    if (ss->opt.requestCertificate && ss->sec.ci.sid->peerCert) {
-        rv = ssl3_AppendNumberToItem(&plaintext, CLIENT_AUTH_CERTIFICATE, 1);
-        if (rv != SECSuccess)
-            goto loser;
-        rv = ssl3_AppendNumberToItem(&plaintext,
-                                     ss->sec.ci.sid->peerCert->derCert.len, 3);
-        if (rv != SECSuccess)
-            goto loser;
-        rv = ssl3_AppendToItem(&plaintext,
-                               ss->sec.ci.sid->peerCert->derCert.data,
-                               ss->sec.ci.sid->peerCert->derCert.len);
-        if (rv != SECSuccess)
-            goto loser;
-    } else {
-        rv = ssl3_AppendNumberToItem(&plaintext, 0, 1);
-        if (rv != SECSuccess)
-            goto loser;
-    }
-
-    /* timestamp */
-    now = ssl_Time();
-    rv = ssl3_AppendNumberToItem(&plaintext, now,
-                                 sizeof(ticket.ticket_lifetime_hint));
-    if (rv != SECSuccess)
-        goto loser;
-
-    if (srvNameLen) {
-        /* Name Type (sni_host_name) */
-        rv = ssl3_AppendNumberToItem(&plaintext, srvName->type, 1);
-        if (rv != SECSuccess)
-            goto loser;
-        /* HostName (length and value) */
-        rv = ssl3_AppendNumberToItem(&plaintext, srvName->len, 2);
-        if (rv != SECSuccess)
-            goto loser;
-        rv = ssl3_AppendToItem(&plaintext, srvName->data, srvName->len);
-        if (rv != SECSuccess)
-            goto loser;
-    } else {
-        /* No Name */
-        rv = ssl3_AppendNumberToItem(&plaintext, (char)TLS_STE_NO_SERVER_NAME, 1);
-        if (rv != SECSuccess)
-            goto loser;
-    }
-
-    /* extendedMasterSecretUsed */
-    rv = ssl3_AppendNumberToItem(
-        &plaintext, ss->sec.ci.sid->u.ssl3.keys.extendedMasterSecretUsed, 1);
-    if (rv != SECSuccess)
-        goto loser;
-
-    PORT_Assert(plaintext.len == padding_length);
-    for (i = 0; i < padding_length; i++)
-        plaintext.data[i] = (unsigned char)padding_length;
-
-    if (SECITEM_AllocItem(NULL, &ciphertext, ciphertext_length) == NULL) {
-        rv = SECFailure;
-        goto loser;
-    }
-
-/* Generate encrypted portion of ticket. */
-#ifndef NO_PKCS11_BYPASS
-    if (ss->opt.bypassPKCS11) {
-        aes_ctx = (AESContext *)aes_ctx_buf;
-        rv = AES_InitContext(aes_ctx, aes_key, aes_key_length, iv,
-                             NSS_AES_CBC, 1, AES_BLOCK_SIZE);
-        if (rv != SECSuccess)
-            goto loser;
-
-        rv = AES_Encrypt(aes_ctx, ciphertext.data, &ciphertext.len,
-                         ciphertext.len, plaintext_item.data,
-                         plaintext_item.len);
-        if (rv != SECSuccess)
-            goto loser;
-    } else
-#endif
-    {
-        aes_ctx_pkcs11 = PK11_CreateContextBySymKey(cipherMech,
-                                                    CKA_ENCRYPT, aes_key_pkcs11, &ivItem);
-        if (!aes_ctx_pkcs11)
-            goto loser;
-
-        rv = PK11_CipherOp(aes_ctx_pkcs11, ciphertext.data,
-                           (int *)&ciphertext.len, ciphertext.len,
-                           plaintext_item.data, plaintext_item.len);
-        PK11_Finalize(aes_ctx_pkcs11);
-        PK11_DestroyContext(aes_ctx_pkcs11, PR_TRUE);
-        if (rv != SECSuccess)
-            goto loser;
-    }
-
-    /* Convert ciphertext length to network order. */
-    length_buf[0] = (ciphertext.len >> 8) & 0xff;
-    length_buf[1] = (ciphertext.len) & 0xff;
-
-/* Compute MAC. */
-#ifndef NO_PKCS11_BYPASS
-    if (ss->opt.bypassPKCS11) {
-        hmac_ctx = (HMACContext *)hmac_ctx_buf;
-        hashObj = HASH_GetRawHashObject(HASH_AlgSHA256);
-        if (HMAC_Init(hmac_ctx, hashObj, mac_key,
-                      mac_key_length, PR_FALSE) != SECSuccess)
-            goto loser;
-
-        HMAC_Begin(hmac_ctx);
-        HMAC_Update(hmac_ctx, key_name, SESS_TICKET_KEY_NAME_LEN);
-        HMAC_Update(hmac_ctx, iv, sizeof(iv));
-        HMAC_Update(hmac_ctx, (unsigned char *)length_buf, 2);
-        HMAC_Update(hmac_ctx, ciphertext.data, ciphertext.len);
-        HMAC_Finish(hmac_ctx, computed_mac, &computed_mac_length,
-                    sizeof(computed_mac));
-    } else
-#endif
-    {
-        SECItem macParam;
-        macParam.data = NULL;
-        macParam.len = 0;
-        hmac_ctx_pkcs11 = PK11_CreateContextBySymKey(macMech,
-                                                     CKA_SIGN, mac_key_pkcs11, &macParam);
-        if (!hmac_ctx_pkcs11)
-            goto loser;
-
-        rv = PK11_DigestBegin(hmac_ctx_pkcs11);
-        if (rv != SECSuccess)
-            goto loser;
-        rv = PK11_DigestOp(hmac_ctx_pkcs11, key_name,
-                           SESS_TICKET_KEY_NAME_LEN);
-        if (rv != SECSuccess)
-            goto loser;
-        rv = PK11_DigestOp(hmac_ctx_pkcs11, iv, sizeof(iv));
-        if (rv != SECSuccess)
-            goto loser;
-        rv = PK11_DigestOp(hmac_ctx_pkcs11, (unsigned char *)length_buf, 2);
-        if (rv != SECSuccess)
-            goto loser;
-        rv = PK11_DigestOp(hmac_ctx_pkcs11, ciphertext.data, ciphertext.len);
-        if (rv != SECSuccess)
-            goto loser;
-        rv = PK11_DigestFinal(hmac_ctx_pkcs11, computed_mac,
-                              &computed_mac_length, sizeof(computed_mac));
-        if (rv != SECSuccess)
-            goto loser;
-    }
-
-    /* Serialize the handshake message. */
-    rv = ssl3_AppendHandshakeHeader(ss, new_session_ticket, message_length);
-    if (rv != SECSuccess)
-        goto loser;
-
-    rv = ssl3_AppendHandshakeNumber(ss, ticket.ticket_lifetime_hint,
-                                    sizeof(ticket.ticket_lifetime_hint));
-    if (rv != SECSuccess)
-        goto loser;
-
-    rv = ssl3_AppendHandshakeNumber(ss,
-                                    message_length - sizeof(ticket.ticket_lifetime_hint) - 2,
-                                    2);
-    if (rv != SECSuccess)
-        goto loser;
-
-    rv = ssl3_AppendHandshake(ss, key_name, SESS_TICKET_KEY_NAME_LEN);
-    if (rv != SECSuccess)
-        goto loser;
-
-    rv = ssl3_AppendHandshake(ss, iv, sizeof(iv));
-    if (rv != SECSuccess)
-        goto loser;
-
-    rv = ssl3_AppendHandshakeVariable(ss, ciphertext.data, ciphertext.len, 2);
-    if (rv != SECSuccess)
-        goto loser;
-
-    rv = ssl3_AppendHandshake(ss, computed_mac, computed_mac_length);
-    if (rv != SECSuccess)
-        goto loser;
-
-loser:
-    if (hmac_ctx_pkcs11)
-        PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE);
-    if (plaintext_item.data)
-        SECITEM_FreeItem(&plaintext_item, PR_FALSE);
-    if (ciphertext.data)
-        SECITEM_FreeItem(&ciphertext, PR_FALSE);
-
-    return rv;
-}
-
-/* When a client receives a SessionTicket extension a NewSessionTicket
- * message is expected during the handshake.
- */
-SECStatus
-ssl3_ClientHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
-                                  SECItem *data)
-{
-    if (data->len != 0) {
-        return SECSuccess; /* Ignore the extension. */
-    }
-
-    /* Keep track of negotiated extensions. */
-    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-    return SECSuccess;
-}
-
-SECStatus
-ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
-                                  SECItem *data)
-{
-    SECStatus rv;
-    SECItem *decrypted_state = NULL;
-    SessionTicket *parsed_session_ticket = NULL;
-    sslSessionID *sid = NULL;
-    SSL3Statistics *ssl3stats;
-
-    /* Ignore the SessionTicket extension if processing is disabled. */
-    if (!ss->opt.enableSessionTickets) {
-        return SECSuccess;
-    }
-
-    /* Keep track of negotiated extensions. */
-    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-
-    /* Parse the received ticket sent in by the client.  We are
-     * lenient about some parse errors, falling back to a fullshake
-     * instead of terminating the current connection.
-     */
-    if (data->len == 0) {
-        ss->xtnData.emptySessionTicket = PR_TRUE;
-    } else {
-        PRUint32 i;
-        SECItem extension_data;
-        EncryptedSessionTicket enc_session_ticket;
-        unsigned char computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH];
-        unsigned int computed_mac_length;
-#ifndef NO_PKCS11_BYPASS
-        const SECHashObject *hashObj;
-        const unsigned char *aes_key;
-        const unsigned char *mac_key;
-        PRUint32 aes_key_length;
-        PRUint32 mac_key_length;
-        PRUint64 hmac_ctx_buf[MAX_MAC_CONTEXT_LLONGS];
-        HMACContext *hmac_ctx;
-        PRUint64 aes_ctx_buf[MAX_CIPHER_CONTEXT_LLONGS];
-        AESContext *aes_ctx;
-#endif
-        PK11SymKey *aes_key_pkcs11;
-        PK11SymKey *mac_key_pkcs11;
-        PK11Context *hmac_ctx_pkcs11;
-        CK_MECHANISM_TYPE macMech = CKM_SHA256_HMAC;
-        PK11Context *aes_ctx_pkcs11;
-        CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC;
-        unsigned char *padding;
-        PRUint32 padding_length;
-        unsigned char *buffer;
-        unsigned int buffer_len;
-        PRInt32 temp;
-        SECItem cert_item;
-        PRInt8 nameType = TLS_STE_NO_SERVER_NAME;
-
-        /* Turn off stateless session resumption if the client sends a
-         * SessionTicket extension, even if the extension turns out to be
-         * malformed (ss->sec.ci.sid is non-NULL when doing session
-         * renegotiation.)
-         */
-        if (ss->sec.ci.sid != NULL) {
-            if (ss->sec.uncache)
-                ss->sec.uncache(ss->sec.ci.sid);
-            ssl_FreeSID(ss->sec.ci.sid);
-            ss->sec.ci.sid = NULL;
-        }
-
-        extension_data.data = data->data; /* Keep a copy for future use. */
-        extension_data.len = data->len;
-
-        if (ssl3_ParseEncryptedSessionTicket(ss, data, &enc_session_ticket) !=
-            SECSuccess) {
-            return SECSuccess; /* Pretend it isn't there */
-        }
-
-/* Get session ticket keys. */
-#ifndef NO_PKCS11_BYPASS
-        if (ss->opt.bypassPKCS11) {
-            rv = ssl3_GetSessionTicketKeys(&aes_key, &aes_key_length,
-                                           &mac_key, &mac_key_length);
-        } else
-#endif
-        {
-            rv = ssl3_GetSessionTicketKeysPKCS11(ss, &aes_key_pkcs11,
-                                                 &mac_key_pkcs11);
-        }
-        if (rv != SECSuccess) {
-            SSL_DBG(("%d: SSL[%d]: Unable to get/generate session ticket keys.",
-                     SSL_GETPID(), ss->fd));
-            goto loser;
-        }
-
-        /* If the ticket sent by the client was generated under a key different
-         * from the one we have, bypass ticket processing.
-         */
-        if (PORT_Memcmp(enc_session_ticket.key_name, key_name,
-                        SESS_TICKET_KEY_NAME_LEN) != 0) {
-            SSL_DBG(("%d: SSL[%d]: Session ticket key_name sent mismatch.",
-                     SSL_GETPID(), ss->fd));
-            goto no_ticket;
-        }
-
-        /* Verify the MAC on the ticket.  MAC verification may also
-         * fail if the MAC key has been recently refreshed.
-         */
-#ifndef NO_PKCS11_BYPASS
-        if (ss->opt.bypassPKCS11) {
-            hmac_ctx = (HMACContext *)hmac_ctx_buf;
-            hashObj = HASH_GetRawHashObject(HASH_AlgSHA256);
-            if (HMAC_Init(hmac_ctx, hashObj, mac_key,
-                          sizeof(session_ticket_mac_key), PR_FALSE) != SECSuccess)
-                goto no_ticket;
-            HMAC_Begin(hmac_ctx);
-            HMAC_Update(hmac_ctx, extension_data.data,
-                        extension_data.len - TLS_EX_SESS_TICKET_MAC_LENGTH);
-            if (HMAC_Finish(hmac_ctx, computed_mac, &computed_mac_length,
-                            sizeof(computed_mac)) != SECSuccess)
-                goto no_ticket;
-        } else
-#endif
-        {
-            SECItem macParam;
-            macParam.data = NULL;
-            macParam.len = 0;
-            hmac_ctx_pkcs11 = PK11_CreateContextBySymKey(macMech,
-                                                         CKA_SIGN, mac_key_pkcs11, &macParam);
-            if (!hmac_ctx_pkcs11) {
-                SSL_DBG(("%d: SSL[%d]: Unable to create HMAC context: %d.",
-                         SSL_GETPID(), ss->fd, PORT_GetError()));
-                goto no_ticket;
-            } else {
-                SSL_DBG(("%d: SSL[%d]: Successfully created HMAC context.",
-                         SSL_GETPID(), ss->fd));
-            }
-            rv = PK11_DigestBegin(hmac_ctx_pkcs11);
-            rv = PK11_DigestOp(hmac_ctx_pkcs11, extension_data.data,
-                               extension_data.len -
-                                   TLS_EX_SESS_TICKET_MAC_LENGTH);
-            if (rv != SECSuccess) {
-                PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE);
-                goto no_ticket;
-            }
-            rv = PK11_DigestFinal(hmac_ctx_pkcs11, computed_mac,
-                                  &computed_mac_length, sizeof(computed_mac));
-            PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE);
-            if (rv != SECSuccess)
-                goto no_ticket;
-        }
-        if (NSS_SecureMemcmp(computed_mac, enc_session_ticket.mac,
-                             computed_mac_length) !=
-            0) {
-            SSL_DBG(("%d: SSL[%d]: Session ticket MAC mismatch.",
-                     SSL_GETPID(), ss->fd));
-            goto no_ticket;
-        }
-
-        /* We ignore key_name for now.
-         * This is ok as MAC verification succeeded.
-         */
-
-        /* Decrypt the ticket. */
-
-        /* Plaintext is shorter than the ciphertext due to padding. */
-        decrypted_state = SECITEM_AllocItem(NULL, NULL,
-                                            enc_session_ticket.encrypted_state.len);
-
-#ifndef NO_PKCS11_BYPASS
-        if (ss->opt.bypassPKCS11) {
-            aes_ctx = (AESContext *)aes_ctx_buf;
-            rv = AES_InitContext(aes_ctx, aes_key,
-                                 sizeof(session_ticket_enc_key), enc_session_ticket.iv,
-                                 NSS_AES_CBC, 0, AES_BLOCK_SIZE);
-            if (rv != SECSuccess) {
-                SSL_DBG(("%d: SSL[%d]: Unable to create AES context.",
-                         SSL_GETPID(), ss->fd));
-                goto no_ticket;
-            }
-
-            rv = AES_Decrypt(aes_ctx, decrypted_state->data,
-                             &decrypted_state->len, decrypted_state->len,
-                             enc_session_ticket.encrypted_state.data,
-                             enc_session_ticket.encrypted_state.len);
-            if (rv != SECSuccess)
-                goto no_ticket;
-        } else
-#endif
-        {
-            SECItem ivItem;
-            ivItem.data = enc_session_ticket.iv;
-            ivItem.len = AES_BLOCK_SIZE;
-            aes_ctx_pkcs11 = PK11_CreateContextBySymKey(cipherMech,
-                                                        CKA_DECRYPT, aes_key_pkcs11, &ivItem);
-            if (!aes_ctx_pkcs11) {
-                SSL_DBG(("%d: SSL[%d]: Unable to create AES context.",
-                         SSL_GETPID(), ss->fd));
-                goto no_ticket;
-            }
-
-            rv = PK11_CipherOp(aes_ctx_pkcs11, decrypted_state->data,
-                               (int *)&decrypted_state->len, decrypted_state->len,
-                               enc_session_ticket.encrypted_state.data,
-                               enc_session_ticket.encrypted_state.len);
-            PK11_Finalize(aes_ctx_pkcs11);
-            PK11_DestroyContext(aes_ctx_pkcs11, PR_TRUE);
-            if (rv != SECSuccess)
-                goto no_ticket;
-        }
-
-        /* Check padding. */
-        padding_length =
-            (PRUint32)decrypted_state->data[decrypted_state->len - 1];
-        if (padding_length == 0 || padding_length > AES_BLOCK_SIZE)
-            goto no_ticket;
-
-        padding = &decrypted_state->data[decrypted_state->len - padding_length];
-        for (i = 0; i < padding_length; i++, padding++) {
-            if (padding_length != (PRUint32)*padding)
-                goto no_ticket;
-        }
-
-        /* Deserialize session state. */
-        buffer = decrypted_state->data;
-        buffer_len = decrypted_state->len;
-
-        parsed_session_ticket = PORT_ZAlloc(sizeof(SessionTicket));
-        if (parsed_session_ticket == NULL) {
-            rv = SECFailure;
-            goto loser;
-        }
-
-        /* Read ticket_version and reject if the version is wrong */
-        temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
-        if (temp != TLS_EX_SESS_TICKET_VERSION)
-            goto no_ticket;
-
-        parsed_session_ticket->ticket_version = (SSL3ProtocolVersion)temp;
-
-        /* Read SSLVersion. */
-        temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
-        if (temp < 0)
-            goto no_ticket;
-        parsed_session_ticket->ssl_version = (SSL3ProtocolVersion)temp;
-
-        /* Read cipher_suite. */
-        temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
-        if (temp < 0)
-            goto no_ticket;
-        parsed_session_ticket->cipher_suite = (ssl3CipherSuite)temp;
-
-        /* Read compression_method. */
-        temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
-        if (temp < 0)
-            goto no_ticket;
-        parsed_session_ticket->compression_method = (SSLCompressionMethod)temp;
-
-        /* Read cipher spec parameters. */
-        temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
-        if (temp < 0)
-            goto no_ticket;
-        parsed_session_ticket->authAlgorithm = (SSLSignType)temp;
-        temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len);
-        if (temp < 0)
-            goto no_ticket;
-        parsed_session_ticket->authKeyBits = (PRUint32)temp;
-        temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
-        if (temp < 0)
-            goto no_ticket;
-        parsed_session_ticket->keaType = (SSLKEAType)temp;
-        temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len);
-        if (temp < 0)
-            goto no_ticket;
-        parsed_session_ticket->keaKeyBits = (PRUint32)temp;
-
-        /* Read wrapped master_secret. */
-        temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
-        if (temp < 0)
-            goto no_ticket;
-        parsed_session_ticket->ms_is_wrapped = (PRBool)temp;
-
-        temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
-        if (temp < 0)
-            goto no_ticket;
-        parsed_session_ticket->exchKeyType = (SSL3KEAType)temp;
-
-        temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len);
-        if (temp < 0)
-            goto no_ticket;
-        parsed_session_ticket->msWrapMech = (CK_MECHANISM_TYPE)temp;
-
-        temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
-        if (temp < 0)
-            goto no_ticket;
-        parsed_session_ticket->ms_length = (PRUint16)temp;
-        if (parsed_session_ticket->ms_length == 0 || /* sanity check MS. */
-            parsed_session_ticket->ms_length >
-                sizeof(parsed_session_ticket->master_secret))
-            goto no_ticket;
-
-        /* Allow for the wrapped master secret to be longer. */
-        if (buffer_len < parsed_session_ticket->ms_length)
-            goto no_ticket;
-        PORT_Memcpy(parsed_session_ticket->master_secret, buffer,
-                    parsed_session_ticket->ms_length);
-        buffer += parsed_session_ticket->ms_length;
-        buffer_len -= parsed_session_ticket->ms_length;
-
-        /* Read client_identity */
-        temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
-        if (temp < 0)
-            goto no_ticket;
-        parsed_session_ticket->client_identity.client_auth_type =
-            (ClientAuthenticationType)temp;
-        switch (parsed_session_ticket->client_identity.client_auth_type) {
-            case CLIENT_AUTH_ANONYMOUS:
-                break;
-            case CLIENT_AUTH_CERTIFICATE:
-                rv = ssl3_ConsumeHandshakeVariable(ss, &cert_item, 3,
-                                                   &buffer, &buffer_len);
-                if (rv != SECSuccess)
-                    goto no_ticket;
-                rv = SECITEM_CopyItem(NULL, &parsed_session_ticket->peer_cert,
-                                      &cert_item);
-                if (rv != SECSuccess)
-                    goto no_ticket;
-                break;
-            default:
-                goto no_ticket;
-        }
-        /* Read timestamp. */
-        temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len);
-        if (temp < 0)
-            goto no_ticket;
-        parsed_session_ticket->timestamp = (PRUint32)temp;
-
-        /* Read server name */
-        nameType =
-            ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
-        if (nameType != TLS_STE_NO_SERVER_NAME) {
-            SECItem name_item;
-            rv = ssl3_ConsumeHandshakeVariable(ss, &name_item, 2, &buffer,
-                                               &buffer_len);
-            if (rv != SECSuccess)
-                goto no_ticket;
-            rv = SECITEM_CopyItem(NULL, &parsed_session_ticket->srvName,
-                                  &name_item);
-            if (rv != SECSuccess)
-                goto no_ticket;
-            parsed_session_ticket->srvName.type = nameType;
-        }
-
-        /* Read extendedMasterSecretUsed */
-        temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
-        if (temp < 0)
-            goto no_ticket;
-        PORT_Assert(temp == PR_TRUE || temp == PR_FALSE);
-        parsed_session_ticket->extendedMasterSecretUsed = (PRBool)temp;
-
-        /* Done parsing.  Check that all bytes have been consumed. */
-        if (buffer_len != padding_length)
-            goto no_ticket;
-
-        /* Use the ticket if it has not expired, otherwise free the allocated
-         * memory since the ticket is of no use.
-         */
-        if (parsed_session_ticket->timestamp != 0 &&
-            parsed_session_ticket->timestamp +
-                    TLS_EX_SESS_TICKET_LIFETIME_HINT >
-                ssl_Time()) {
-
-            sid = ssl3_NewSessionID(ss, PR_TRUE);
-            if (sid == NULL) {
-                rv = SECFailure;
-                goto loser;
-            }
-
-            /* Copy over parameters. */
-            sid->version = parsed_session_ticket->ssl_version;
-            sid->u.ssl3.cipherSuite = parsed_session_ticket->cipher_suite;
-            sid->u.ssl3.compression = parsed_session_ticket->compression_method;
-            sid->authAlgorithm = parsed_session_ticket->authAlgorithm;
-            sid->authKeyBits = parsed_session_ticket->authKeyBits;
-            sid->keaType = parsed_session_ticket->keaType;
-            sid->keaKeyBits = parsed_session_ticket->keaKeyBits;
-
-/* Copy master secret. */
-#ifndef NO_PKCS11_BYPASS
-            if (ss->opt.bypassPKCS11 &&
-                parsed_session_ticket->ms_is_wrapped)
-                goto no_ticket;
-#endif
-            if (parsed_session_ticket->ms_length >
-                sizeof(sid->u.ssl3.keys.wrapped_master_secret))
-                goto no_ticket;
-            PORT_Memcpy(sid->u.ssl3.keys.wrapped_master_secret,
-                        parsed_session_ticket->master_secret,
-                        parsed_session_ticket->ms_length);
-            sid->u.ssl3.keys.wrapped_master_secret_len =
-                parsed_session_ticket->ms_length;
-            sid->u.ssl3.exchKeyType = parsed_session_ticket->exchKeyType;
-            sid->u.ssl3.masterWrapMech = parsed_session_ticket->msWrapMech;
-            sid->u.ssl3.keys.msIsWrapped =
-                parsed_session_ticket->ms_is_wrapped;
-            sid->u.ssl3.masterValid = PR_TRUE;
-            sid->u.ssl3.keys.resumable = PR_TRUE;
-            sid->u.ssl3.keys.extendedMasterSecretUsed = parsed_session_ticket->extendedMasterSecretUsed;
-
-            /* Copy over client cert from session ticket if there is one. */
-            if (parsed_session_ticket->peer_cert.data != NULL) {
-                if (sid->peerCert != NULL)
-                    CERT_DestroyCertificate(sid->peerCert);
-                sid->peerCert = CERT_NewTempCertificate(ss->dbHandle,
-                                                        &parsed_session_ticket->peer_cert, NULL, PR_FALSE, PR_TRUE);
-                if (sid->peerCert == NULL) {
-                    rv = SECFailure;
-                    goto loser;
-                }
-            }
-            if (parsed_session_ticket->srvName.data != NULL) {
-                sid->u.ssl3.srvName = parsed_session_ticket->srvName;
-            }
-            ss->statelessResume = PR_TRUE;
-            ss->sec.ci.sid = sid;
-        }
-    }
-
-    if (0) {
-    no_ticket:
-        SSL_DBG(("%d: SSL[%d]: Session ticket parsing failed.",
-                 SSL_GETPID(), ss->fd));
-        ssl3stats = SSL_GetStatistics();
-        SSL_AtomicIncrementLong(&ssl3stats->hch_sid_ticket_parse_failures);
-    }
-    rv = SECSuccess;
-
-loser:
-    /* ss->sec.ci.sid == sid if it did NOT come here via goto statement
-     * in that case do not free sid
-     */
-    if (sid && (ss->sec.ci.sid != sid)) {
-        ssl_FreeSID(sid);
-        sid = NULL;
-    }
-    if (decrypted_state != NULL) {
-        SECITEM_FreeItem(decrypted_state, PR_TRUE);
-        decrypted_state = NULL;
-    }
-
-    if (parsed_session_ticket != NULL) {
-        if (parsed_session_ticket->peer_cert.data) {
-            SECITEM_FreeItem(&parsed_session_ticket->peer_cert, PR_FALSE);
-        }
-        PORT_ZFree(parsed_session_ticket, sizeof(SessionTicket));
-    }
-
-    return rv;
-}
-
-/*
- * Read bytes.  Using this function means the SECItem structure
- * cannot be freed.  The caller is expected to call this function
- * on a shallow copy of the structure.
- */
-static SECStatus
-ssl3_ConsumeFromItem(SECItem *item, unsigned char **buf, PRUint32 bytes)
-{
-    if (bytes > item->len)
-        return SECFailure;
-
-    *buf = item->data;
-    item->data += bytes;
-    item->len -= bytes;
-    return SECSuccess;
-}
-
-static SECStatus
-ssl3_ParseEncryptedSessionTicket(sslSocket *ss, SECItem *data,
-                                 EncryptedSessionTicket *enc_session_ticket)
-{
-    if (ssl3_ConsumeFromItem(data, &enc_session_ticket->key_name,
-                             SESS_TICKET_KEY_NAME_LEN) !=
-        SECSuccess)
-        return SECFailure;
-    if (ssl3_ConsumeFromItem(data, &enc_session_ticket->iv,
-                             AES_BLOCK_SIZE) !=
-        SECSuccess)
-        return SECFailure;
-    if (ssl3_ConsumeHandshakeVariable(ss, &enc_session_ticket->encrypted_state,
-                                      2, &data->data, &data->len) !=
-        SECSuccess)
-        return SECFailure;
-    if (ssl3_ConsumeFromItem(data, &enc_session_ticket->mac,
-                             TLS_EX_SESS_TICKET_MAC_LENGTH) !=
-        SECSuccess)
-        return SECFailure;
-    if (data->len != 0) /* Make sure that we have consumed all bytes. */
-        return SECFailure;
-
-    return SECSuccess;
-}
-
-/* go through hello extensions in buffer "b".
- * For each one, find the extension handler in the table, and
- * if present, invoke that handler.
- * Servers ignore any extensions with unknown extension types.
- * Clients reject any extensions with unadvertised extension types.
- * In TLS >= 1.3, the client checks that extensions appear in the
- * right phase.
- */
-SECStatus
-ssl3_HandleHelloExtensions(sslSocket *ss, SSL3Opaque **b, PRUint32 *length,
-                           SSL3HandshakeType handshakeMessage)
-{
-    const ssl3HelloExtensionHandler *handlers;
-    PRBool isTLS13 = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3;
-
-    switch (handshakeMessage) {
-        case client_hello:
-            handlers = clientHelloHandlers;
-            break;
-        case encrypted_extensions:
-            PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
-        /* fall through */
-        case server_hello:
-            if (ss->version > SSL_LIBRARY_VERSION_3_0) {
-                handlers = serverHelloHandlersTLS;
-            } else {
-                handlers = serverHelloHandlersSSL3;
-            }
-            break;
-        default:
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            PORT_Assert(0);
-            return SECFailure;
-    }
-
-    while (*length) {
-        const ssl3HelloExtensionHandler *handler;
-        SECStatus rv;
-        PRInt32 extension_type;
-        SECItem extension_data;
-
-        /* Get the extension's type field */
-        extension_type = ssl3_ConsumeHandshakeNumber(ss, 2, b, length);
-        if (extension_type < 0) /* failure to decode extension_type */
-            return SECFailure;  /* alert already sent */
-
-        /* get the data for this extension, so we can pass it or skip it. */
-        rv = ssl3_ConsumeHandshakeVariable(ss, &extension_data, 2, b, length);
-        if (rv != SECSuccess)
-            return rv; /* alert already sent */
-
-        /* Check whether the server sent an extension which was not advertised
-         * in the ClientHello */
-        if (!ss->sec.isServer &&
-            !ssl3_ClientExtensionAdvertised(ss, extension_type)) {
-            (void)SSL3_SendAlert(ss, alert_fatal, unsupported_extension);
-            return SECFailure;
-        }
-
-        /* Check whether an extension has been sent multiple times. */
-        if (ssl3_ExtensionNegotiated(ss, extension_type)) {
-            (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
-            return SECFailure;
-        }
-
-        /* Check that this is a legal extension in TLS 1.3 */
-        if (isTLS13 && !tls13_ExtensionAllowed(extension_type, handshakeMessage)) {
-            if (handshakeMessage == client_hello) {
-                /* Skip extensions not used in TLS 1.3 */
-                continue;
-            }
-            tls13_FatalError(ss, SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION,
-                             unsupported_extension);
-            return SECFailure;
-        }
-
-        /* find extension_type in table of Hello Extension Handlers */
-        for (handler = handlers; handler->ex_type >= 0; handler++) {
-            /* if found, call this handler */
-            if (handler->ex_type == extension_type) {
-                rv = (*handler->ex_handler)(ss, (PRUint16)extension_type,
-                                            &extension_data);
-                if (rv != SECSuccess) {
-                    if (!ss->ssl3.fatalAlertSent) {
-                        /* send a generic alert if the handler didn't already */
-                        (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure);
-                    }
-                    return SECFailure;
-                }
-            }
-        }
-    }
-    return SECSuccess;
-}
-
-/* Add a callback function to the table of senders of server hello extensions.
- */
-SECStatus
-ssl3_RegisterServerHelloExtensionSender(sslSocket *ss, PRUint16 ex_type,
-                                        ssl3HelloExtensionSenderFunc cb)
-{
-    int i;
-    ssl3HelloExtensionSender *sender;
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        sender = &ss->xtnData.serverHelloSenders[0];
-    } else {
-        if (tls13_ExtensionAllowed(ex_type, server_hello)) {
-            PORT_Assert(!tls13_ExtensionAllowed(ex_type, encrypted_extensions));
-            sender = &ss->xtnData.serverHelloSenders[0];
-        } else {
-            PORT_Assert(tls13_ExtensionAllowed(ex_type, encrypted_extensions));
-            sender = &ss->xtnData.encryptedExtensionsSenders[0];
-        }
-    }
-
-    for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) {
-        if (!sender->ex_sender) {
-            sender->ex_type = ex_type;
-            sender->ex_sender = cb;
-            return SECSuccess;
-        }
-        /* detect duplicate senders */
-        PORT_Assert(sender->ex_type != ex_type);
-        if (sender->ex_type == ex_type) {
-            /* duplicate */
-            break;
-        }
-    }
-    PORT_Assert(i < SSL_MAX_EXTENSIONS); /* table needs to grow */
-    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-    return SECFailure;
-}
-
-/* call each of the extension senders and return the accumulated length */
-PRInt32
-ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
-                               const ssl3HelloExtensionSender *sender)
-{
-    PRInt32 total_exten_len = 0;
-    int i;
-
-    if (!sender) {
-        if (ss->version > SSL_LIBRARY_VERSION_3_0) {
-            sender = &clientHelloSendersTLS[0];
-        } else {
-            sender = &clientHelloSendersSSL3[0];
-        }
-    }
-
-    for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) {
-        if (sender->ex_sender) {
-            PRInt32 extLen = (*sender->ex_sender)(ss, append, maxBytes);
-            if (extLen < 0)
-                return -1;
-            maxBytes -= extLen;
-            total_exten_len += extLen;
-        }
-    }
-    return total_exten_len;
-}
-
-/* Extension format:
- * Extension number:   2 bytes
- * Extension length:   2 bytes
- * Verify Data Length: 1 byte
- * Verify Data (TLS): 12 bytes (client) or 24 bytes (server)
- * Verify Data (SSL): 36 bytes (client) or 72 bytes (server)
- */
-static PRInt32
-ssl3_SendRenegotiationInfoXtn(
-    sslSocket *ss,
-    PRBool append,
-    PRUint32 maxBytes)
-{
-    PRInt32 len = 0;
-    PRInt32 needed;
-
-    /* In draft-ietf-tls-renegotiation-03, it is NOT RECOMMENDED to send
-     * both the SCSV and the empty RI, so when we send SCSV in
-     * the initial handshake, we don't also send RI.
-     */
-    if (!ss || ss->ssl3.hs.sendingSCSV)
-        return 0;
-    if (ss->firstHsDone) {
-        len = ss->sec.isServer ? ss->ssl3.hs.finishedBytes * 2
-                               : ss->ssl3.hs.finishedBytes;
-    }
-    needed = 5 + len;
-    if (maxBytes < (PRUint32)needed) {
-        return 0;
-    }
-    if (append) {
-        SECStatus rv;
-        /* extension_type */
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_renegotiation_info_xtn, 2);
-        if (rv != SECSuccess)
-            return -1;
-        /* length of extension_data */
-        rv = ssl3_AppendHandshakeNumber(ss, len + 1, 2);
-        if (rv != SECSuccess)
-            return -1;
-        /* verify_Data from previous Finished message(s) */
-        rv = ssl3_AppendHandshakeVariable(ss,
-                                          ss->ssl3.hs.finishedMsgs.data, len, 1);
-        if (rv != SECSuccess)
-            return -1;
-        if (!ss->sec.isServer) {
-            TLSExtensionData *xtnData = &ss->xtnData;
-            xtnData->advertised[xtnData->numAdvertised++] =
-                ssl_renegotiation_info_xtn;
-        }
-    }
-    return needed;
-}
-
-static SECStatus
-ssl3_ServerHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type,
-                                  SECItem *data)
-{
-    SECStatus rv = SECSuccess;
-
-    /* remember that we got this extension. */
-    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-    PORT_Assert(ss->sec.isServer);
-    /* prepare to send back the appropriate response */
-    rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
-                                                 ssl3_ServerSendStatusRequestXtn);
-    return rv;
-}
-
-/* This function runs in both the client and server.  */
-static SECStatus
-ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
-{
-    SECStatus rv = SECSuccess;
-    PRUint32 len = 0;
-
-    if (ss->firstHsDone) {
-        len = ss->sec.isServer ? ss->ssl3.hs.finishedBytes
-                               : ss->ssl3.hs.finishedBytes * 2;
-    }
-    if (data->len != 1 + len || data->data[0] != len) {
-        (void)ssl3_DecodeError(ss);
-        return SECFailure;
-    }
-    if (len && NSS_SecureMemcmp(ss->ssl3.hs.finishedMsgs.data,
-                                data->data + 1, len)) {
-        (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure);
-        PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
-        return SECFailure;
-    }
-    /* remember that we got this extension and it was correct. */
-    ss->peerRequestedProtection = 1;
-    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-    if (ss->sec.isServer) {
-        /* prepare to send back the appropriate response */
-        rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
-                                                     ssl3_SendRenegotiationInfoXtn);
-    }
-    return rv;
-}
-
-static PRInt32
-ssl3_ClientSendUseSRTPXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
-{
-    PRUint32 ext_data_len;
-    PRInt16 i;
-    SECStatus rv;
-
-    if (!ss)
-        return 0;
-
-    if (!IS_DTLS(ss) || !ss->ssl3.dtlsSRTPCipherCount)
-        return 0; /* Not relevant */
-
-    ext_data_len = 2 + 2 * ss->ssl3.dtlsSRTPCipherCount + 1;
-
-    if (append && maxBytes >= 4 + ext_data_len) {
-        /* Extension type */
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2);
-        if (rv != SECSuccess)
-            return -1;
-        /* Length of extension data */
-        rv = ssl3_AppendHandshakeNumber(ss, ext_data_len, 2);
-        if (rv != SECSuccess)
-            return -1;
-        /* Length of the SRTP cipher list */
-        rv = ssl3_AppendHandshakeNumber(ss,
-                                        2 * ss->ssl3.dtlsSRTPCipherCount,
-                                        2);
-        if (rv != SECSuccess)
-            return -1;
-        /* The SRTP ciphers */
-        for (i = 0; i < ss->ssl3.dtlsSRTPCipherCount; i++) {
-            rv = ssl3_AppendHandshakeNumber(ss,
-                                            ss->ssl3.dtlsSRTPCiphers[i],
-                                            2);
-        }
-        /* Empty MKI value */
-        ssl3_AppendHandshakeVariable(ss, NULL, 0, 1);
-
-        ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
-            ssl_use_srtp_xtn;
-    }
-
-    return 4 + ext_data_len;
-}
-
-static PRInt32
-ssl3_ServerSendUseSRTPXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
-{
-    SECStatus rv;
-
-    /* Server side */
-    if (!append || maxBytes < 9) {
-        return 9;
-    }
-
-    /* Extension type */
-    rv = ssl3_AppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2);
-    if (rv != SECSuccess)
-        return -1;
-    /* Length of extension data */
-    rv = ssl3_AppendHandshakeNumber(ss, 5, 2);
-    if (rv != SECSuccess)
-        return -1;
-    /* Length of the SRTP cipher list */
-    rv = ssl3_AppendHandshakeNumber(ss, 2, 2);
-    if (rv != SECSuccess)
-        return -1;
-    /* The selected cipher */
-    rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.dtlsSRTPCipherSuite, 2);
-    if (rv != SECSuccess)
-        return -1;
-    /* Empty MKI value */
-    ssl3_AppendHandshakeVariable(ss, NULL, 0, 1);
-
-    return 9;
-}
-
-static SECStatus
-ssl3_ClientHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
-{
-    SECStatus rv;
-    SECItem ciphers = { siBuffer, NULL, 0 };
-    PRUint16 i;
-    PRUint16 cipher = 0;
-    PRBool found = PR_FALSE;
-    SECItem litem;
-
-    if (!data->data || !data->len) {
-        (void)ssl3_DecodeError(ss);
-        return SECFailure;
-    }
-
-    /* Get the cipher list */
-    rv = ssl3_ConsumeHandshakeVariable(ss, &ciphers, 2,
-                                       &data->data, &data->len);
-    if (rv != SECSuccess) {
-        return SECFailure; /* fatal alert already sent */
-    }
-    /* Now check that the server has picked just 1 (i.e., len = 2) */
-    if (ciphers.len != 2) {
-        (void)ssl3_DecodeError(ss);
-        return SECFailure;
-    }
-
-    /* Get the selected cipher */
-    cipher = (ciphers.data[0] << 8) | ciphers.data[1];
-
-    /* Now check that this is one of the ciphers we offered */
-    for (i = 0; i < ss->ssl3.dtlsSRTPCipherCount; i++) {
-        if (cipher == ss->ssl3.dtlsSRTPCiphers[i]) {
-            found = PR_TRUE;
-            break;
-        }
-    }
-
-    if (!found) {
-        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
-        PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
-        return SECFailure;
-    }
-
-    /* Get the srtp_mki value */
-    rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 1,
-                                       &data->data, &data->len);
-    if (rv != SECSuccess) {
-        return SECFailure; /* alert already sent */
-    }
-
-    /* We didn't offer an MKI, so this must be 0 length */
-    if (litem.len != 0) {
-        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
-        PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
-        return SECFailure;
-    }
-
-    /* extra trailing bytes */
-    if (data->len != 0) {
-        (void)ssl3_DecodeError(ss);
-        return SECFailure;
-    }
-
-    /* OK, this looks fine. */
-    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ssl_use_srtp_xtn;
-    ss->ssl3.dtlsSRTPCipherSuite = cipher;
-    return SECSuccess;
-}
-
-static SECStatus
-ssl3_ServerHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
-{
-    SECStatus rv;
-    SECItem ciphers = { siBuffer, NULL, 0 };
-    PRUint16 i;
-    unsigned int j;
-    PRUint16 cipher = 0;
-    PRBool found = PR_FALSE;
-    SECItem litem;
-
-    if (!IS_DTLS(ss) || !ss->ssl3.dtlsSRTPCipherCount) {
-        /* Ignore the extension if we aren't doing DTLS or no DTLS-SRTP
-         * preferences have been set. */
-        return SECSuccess;
-    }
-
-    if (!data->data || data->len < 5) {
-        (void)ssl3_DecodeError(ss);
-        return SECFailure;
-    }
-
-    /* Get the cipher list */
-    rv = ssl3_ConsumeHandshakeVariable(ss, &ciphers, 2,
-                                       &data->data, &data->len);
-    if (rv != SECSuccess) {
-        return SECFailure; /* alert already sent */
-    }
-    /* Check that the list is even length */
-    if (ciphers.len % 2) {
-        (void)ssl3_DecodeError(ss);
-        return SECFailure;
-    }
-
-    /* Walk through the offered list and pick the most preferred of our
-     * ciphers, if any */
-    for (i = 0; !found && i < ss->ssl3.dtlsSRTPCipherCount; i++) {
-        for (j = 0; j + 1 < ciphers.len; j += 2) {
-            cipher = (ciphers.data[j] << 8) | ciphers.data[j + 1];
-            if (cipher == ss->ssl3.dtlsSRTPCiphers[i]) {
-                found = PR_TRUE;
-                break;
-            }
-        }
-    }
-
-    /* Get the srtp_mki value */
-    rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 1, &data->data, &data->len);
-    if (rv != SECSuccess) {
-        return SECFailure;
-    }
-
-    if (data->len != 0) {
-        (void)ssl3_DecodeError(ss); /* trailing bytes */
-        return SECFailure;
-    }
-
-    /* Now figure out what to do */
-    if (!found) {
-        /* No matching ciphers, pretend we don't support use_srtp */
-        return SECSuccess;
-    }
-
-    /* OK, we have a valid cipher and we've selected it */
-    ss->ssl3.dtlsSRTPCipherSuite = cipher;
-    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ssl_use_srtp_xtn;
-
-    return ssl3_RegisterServerHelloExtensionSender(ss, ssl_use_srtp_xtn,
-                                                   ssl3_ServerSendUseSRTPXtn);
-}
-
-/* ssl3_ServerHandleSigAlgsXtn handles the signature_algorithms extension
- * from a client.
- * See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
-static SECStatus
-ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
-{
-    SECStatus rv;
-    SECItem algorithms;
-    const unsigned char *b;
-    unsigned int numAlgorithms, i;
-
-    /* Ignore this extension if we aren't doing TLS 1.2 or greater. */
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_2) {
-        return SECSuccess;
-    }
-
-    rv = ssl3_ConsumeHandshakeVariable(ss, &algorithms, 2, &data->data,
-                                       &data->len);
-    if (rv != SECSuccess) {
-        return SECFailure;
-    }
-    /* Trailing data, empty value, or odd-length value is invalid. */
-    if (data->len != 0 || algorithms.len == 0 || (algorithms.len & 1) != 0) {
-        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
-        PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
-        return SECFailure;
-    }
-
-    numAlgorithms = algorithms.len / 2;
-
-    /* We don't care to process excessive numbers of algorithms. */
-    if (numAlgorithms > 512) {
-        numAlgorithms = 512;
-    }
-
-    ss->ssl3.hs.clientSigAndHash =
-        PORT_NewArray(SSLSignatureAndHashAlg, numAlgorithms);
-    if (!ss->ssl3.hs.clientSigAndHash) {
-        (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
-        PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
-        return SECFailure;
-    }
-    ss->ssl3.hs.numClientSigAndHash = 0;
-
-    b = algorithms.data;
-    ss->ssl3.hs.numClientSigAndHash = 0;
-    for (i = 0; i < numAlgorithms; i++) {
-        SSLSignatureAndHashAlg *sigAndHash =
-            &ss->ssl3.hs.clientSigAndHash[ss->ssl3.hs.numClientSigAndHash];
-        sigAndHash->hashAlg = (SSLHashType) * (b++);
-        sigAndHash->sigAlg = (SSLSignType) * (b++);
-        if (ssl3_IsSupportedSignatureAlgorithm(sigAndHash)) {
-            ++ss->ssl3.hs.numClientSigAndHash;
-        }
-    }
-
-    if (!ss->ssl3.hs.numClientSigAndHash) {
-        /* We didn't understand any of the client's requested signature
-         * formats. We'll use the defaults. */
-        PORT_Free(ss->ssl3.hs.clientSigAndHash);
-        ss->ssl3.hs.clientSigAndHash = NULL;
-    }
-
-    /* Keep track of negotiated extensions. */
-    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-    return SECSuccess;
-}
-
-/* ssl3_ClientSendSigAlgsXtn sends the signature_algorithm extension for TLS
- * 1.2 ClientHellos. */
-static PRInt32
-ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
-{
-    PRInt32 extension_length;
-    unsigned int i;
-    PRInt32 pos = 0;
-    PRUint32 policy;
-    PRUint8 buf[MAX_SIGNATURE_ALGORITHMS * 2];
-
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_2) {
-        return 0;
-    }
-
-    for (i = 0; i < ss->ssl3.signatureAlgorithmCount; i++) {
-        SECOidTag hashOID = ssl3_TLSHashAlgorithmToOID(
-            ss->ssl3.signatureAlgorithms[i].hashAlg);
-        if ((NSS_GetAlgorithmPolicy(hashOID, &policy) != SECSuccess) ||
-            (policy & NSS_USE_ALG_IN_SSL_KX)) {
-            buf[pos++] = ss->ssl3.signatureAlgorithms[i].hashAlg;
-            buf[pos++] = ss->ssl3.signatureAlgorithms[i].sigAlg;
-        }
-    }
-
-    extension_length =
-        2 /* extension type */ +
-        2 /* extension length */ +
-        2 /* supported_signature_algorithms length */ +
-        pos;
-
-    if (maxBytes < extension_length) {
-        PORT_Assert(0);
-        return 0;
-    }
-
-    if (append) {
-        SECStatus rv;
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_signature_algorithms_xtn, 2);
-        if (rv != SECSuccess) {
-            return -1;
-        }
-        rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
-        if (rv != SECSuccess) {
-            return -1;
-        }
-
-        rv = ssl3_AppendHandshakeVariable(ss, buf, extension_length - 6, 2);
-        if (rv != SECSuccess) {
-            return -1;
-        }
-
-        ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
-            ssl_signature_algorithms_xtn;
-    }
-
-    return extension_length;
-}
-
-unsigned int
-ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength)
-{
-    unsigned int recordLength = 1 /* handshake message type */ +
-                                3 /* handshake message length */ +
-                                clientHelloLength;
-    unsigned int extensionLength;
-
-    if (recordLength < 256 || recordLength >= 512) {
-        return 0;
-    }
-
-    extensionLength = 512 - recordLength;
-    /* Extensions take at least four bytes to encode. Always include at least
-     * one byte of data if including the extension. WebSphere Application
-     * Server 7.0 is intolerant to the last extension being zero-length. */
-    if (extensionLength < 4 + 1) {
-        extensionLength = 4 + 1;
-    }
-
-    return extensionLength;
-}
-
-/* ssl3_AppendPaddingExtension possibly adds an extension which ensures that a
- * ClientHello record is either < 256 bytes or is >= 512 bytes. This ensures
- * that we don't trigger bugs in F5 products. */
-PRInt32
-ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
-                            PRUint32 maxBytes)
-{
-    unsigned int paddingLen = extensionLen - 4;
-    static unsigned char padding[256];
-
-    if (extensionLen == 0) {
-        return 0;
-    }
-
-    if (extensionLen < 4 ||
-        extensionLen > maxBytes ||
-        paddingLen > sizeof(padding)) {
-        PORT_Assert(0);
-        return -1;
-    }
-
-    if (SECSuccess != ssl3_AppendHandshakeNumber(ss, ssl_padding_xtn, 2))
-        return -1;
-    if (SECSuccess != ssl3_AppendHandshakeNumber(ss, paddingLen, 2))
-        return -1;
-    if (SECSuccess != ssl3_AppendHandshake(ss, padding, paddingLen))
-        return -1;
-
-    return extensionLen;
-}
-
-/* ssl3_ClientSendDraftVersionXtn sends the TLS 1.3 temporary draft
- * version extension.
- * TODO(ekr@rtfm.com): Remove when TLS 1.3 is published. */
-static PRInt32
-ssl3_ClientSendDraftVersionXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
-{
-    PRInt32 extension_length;
-
-    if (ss->version != SSL_LIBRARY_VERSION_TLS_1_3) {
-        return 0;
-    }
-
-    extension_length = 6; /* Type + length + number */
-    if (maxBytes < (PRUint32)extension_length) {
-        PORT_Assert(0);
-        return 0;
-    }
-    if (append) {
-        SECStatus rv;
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_draft_version_xtn, 2);
-        if (rv != SECSuccess)
-            goto loser;
-        rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
-        if (rv != SECSuccess)
-            goto loser;
-        rv = ssl3_AppendHandshakeNumber(ss, TLS_1_3_DRAFT_VERSION, 2);
-        if (rv != SECSuccess)
-            goto loser;
-        ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
-            ssl_tls13_draft_version_xtn;
-    }
-
-    return extension_length;
-
-loser:
-    return -1;
-}
-
-/* ssl3_ServerHandleDraftVersionXtn handles the TLS 1.3 temporary draft
- * version extension.
- * TODO(ekr@rtfm.com): Remove when TLS 1.3 is published. */
-static SECStatus
-ssl3_ServerHandleDraftVersionXtn(sslSocket *ss, PRUint16 ex_type,
-                                 SECItem *data)
-{
-    PRInt32 draft_version;
-
-    /* Ignore this extension if we aren't doing TLS 1.3 */
-    if (ss->version != SSL_LIBRARY_VERSION_TLS_1_3) {
-        return SECSuccess;
-    }
-
-    if (data->len != 2) {
-        (void)ssl3_DecodeError(ss);
-        return SECFailure;
-    }
-
-    /* Get the draft version out of the handshake */
-    draft_version = ssl3_ConsumeHandshakeNumber(ss, 2,
-                                                &data->data, &data->len);
-    if (draft_version < 0) {
-        return SECFailure;
-    }
-
-    /*  Keep track of negotiated extensions. */
-    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-
-    if (draft_version != TLS_1_3_DRAFT_VERSION) {
-        /*
-         * Incompatible/broken TLS 1.3 implementation. Fall back to TLS 1.2.
-         * TODO(ekr@rtfm.com): It's not entirely clear it's safe to roll back
-         * here. Need to double-check.
-         */
-        SSL_TRC(30, ("%d: SSL3[%d]: Incompatible version of TLS 1.3 (%d), "
-                     "expected %d",
-                     SSL_GETPID(), ss->fd, draft_version, TLS_1_3_DRAFT_VERSION));
-        ss->version = SSL_LIBRARY_VERSION_TLS_1_2;
-    }
-
-    return SECSuccess;
-}
-
-static PRInt32
-ssl3_SendExtendedMasterSecretXtn(sslSocket *ss, PRBool append,
-                                 PRUint32 maxBytes)
-{
-    PRInt32 extension_length;
-
-    if (!ss->opt.enableExtendedMS) {
-        return 0;
-    }
-
-#ifndef NO_PKCS11_BYPASS
-    /* Extended MS can only be used w/o bypass mode */
-    if (ss->opt.bypassPKCS11) {
-        PORT_Assert(0);
-        PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
-        return -1;
-    }
-#endif
-
-    /* Always send the extension in this function, since the
-     * client always sends it and this function is only called on
-     * the server if we negotiated the extension. */
-    extension_length = 4; /* Type + length (0) */
-    if (maxBytes < extension_length) {
-        PORT_Assert(0);
-        return 0;
-    }
-
-    if (append) {
-        SECStatus rv;
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_extended_master_secret_xtn, 2);
-        if (rv != SECSuccess)
-            goto loser;
-        rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
-        if (rv != SECSuccess)
-            goto loser;
-        ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
-            ssl_extended_master_secret_xtn;
-    }
-
-    return extension_length;
-
-loser:
-    return -1;
-}
-
-static SECStatus
-ssl3_HandleExtendedMasterSecretXtn(sslSocket *ss, PRUint16 ex_type,
-                                   SECItem *data)
-{
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_0) {
-        return SECSuccess;
-    }
-
-    if (!ss->opt.enableExtendedMS) {
-        return SECSuccess;
-    }
-
-#ifndef NO_PKCS11_BYPASS
-    /* Extended MS can only be used w/o bypass mode */
-    if (ss->opt.bypassPKCS11) {
-        PORT_Assert(0);
-        PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
-        return SECFailure;
-    }
-#endif
-
-    if (data->len != 0) {
-        SSL_TRC(30, ("%d: SSL3[%d]: Bogus extended master secret extension",
-                     SSL_GETPID(), ss->fd));
-        return SECFailure;
-    }
-
-    SSL_DBG(("%d: SSL[%d]: Negotiated extended master secret extension.",
-             SSL_GETPID(), ss->fd));
-
-    /* Keep track of negotiated extensions. */
-    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-
-    if (ss->sec.isServer) {
-        return ssl3_RegisterServerHelloExtensionSender(
-            ss, ex_type, ssl3_SendExtendedMasterSecretXtn);
-    }
-    return SECSuccess;
-}
-
-/* ssl3_ClientSendSignedCertTimestampXtn sends the signed_certificate_timestamp
- * extension for TLS ClientHellos. */
-static PRInt32
-ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss, PRBool append,
-                                      PRUint32 maxBytes)
-{
-    PRInt32 extension_length = 2 /* extension_type */ +
-                               2 /* length(extension_data) */;
-
-    /* Only send the extension if processing is enabled. */
-    if (!ss->opt.enableSignedCertTimestamps)
-        return 0;
-
-    if (append && maxBytes >= extension_length) {
-        SECStatus rv;
-        /* extension_type */
-        rv = ssl3_AppendHandshakeNumber(ss,
-                                        ssl_signed_cert_timestamp_xtn,
-                                        2);
-        if (rv != SECSuccess)
-            goto loser;
-        /* zero length */
-        rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
-        if (rv != SECSuccess)
-            goto loser;
-        ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
-            ssl_signed_cert_timestamp_xtn;
-    } else if (maxBytes < extension_length) {
-        PORT_Assert(0);
-        return 0;
-    }
-
-    return extension_length;
-loser:
-    return -1;
-}
-
-static SECStatus
-ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss, PRUint16 ex_type,
-                                        SECItem *data)
-{
-    /* We do not yet know whether we'll be resuming a session or creating
-     * a new one, so we keep a pointer to the data in the TLSExtensionData
-     * structure. This pointer is only valid in the scope of
-     * ssl3_HandleServerHello, and, if not resuming a session, the data is
-     * copied once a new session structure has been set up.
-     * All parsing is currently left to the application and we accept
-     * everything, including empty data.
-     */
-    SECItem *scts = &ss->xtnData.signedCertTimestamps;
-    PORT_Assert(!scts->data && !scts->len);
-
-    if (!data->len) {
-        /* Empty extension data: RFC 6962 mandates non-empty contents. */
-        return SECFailure;
-    }
-    *scts = *data;
-    /* Keep track of negotiated extensions. */
-    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-    return SECSuccess;
-}
-
-static PRInt32
-ssl3_ServerSendSignedCertTimestampXtn(sslSocket *ss,
-                                      PRBool append,
-                                      PRUint32 maxBytes)
-{
-    PRInt32 extension_length;
-    SSLKEAType effectiveExchKeyType;
-    const SECItem *scts;
-
-    if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa ||
-        ss->ssl3.hs.kea_def->kea == kea_dhe_rsa) {
-        effectiveExchKeyType = ssl_kea_rsa;
-    } else {
-        effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType;
-    }
-
-    scts = &ss->signedCertTimestamps[effectiveExchKeyType];
-
-    if (!scts->len) {
-        /* No timestamps to send */
-        return 0;
-    }
-
-    extension_length = 2 /* extension_type */ +
-                       2 /* length(extension_data) */ +
-                       scts->len;
-
-    if (maxBytes < extension_length) {
-        PORT_Assert(0);
-        return 0;
-    }
-    if (append) {
-        SECStatus rv;
-        /* extension_type */
-        rv = ssl3_AppendHandshakeNumber(ss,
-                                        ssl_signed_cert_timestamp_xtn,
-                                        2);
-        if (rv != SECSuccess)
-            goto loser;
-        /* extension_data */
-        rv = ssl3_AppendHandshakeVariable(ss, scts->data, scts->len, 2);
-        if (rv != SECSuccess)
-            goto loser;
-    }
-
-    return extension_length;
-
-loser:
-    return -1;
-}
-
-static SECStatus
-ssl3_ServerHandleSignedCertTimestampXtn(sslSocket *ss, PRUint16 ex_type,
-                                        SECItem *data)
-{
-    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-    PORT_Assert(ss->sec.isServer);
-    return ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
-                                                   ssl3_ServerSendSignedCertTimestampXtn);
-}
-
-/*
- *     [draft-ietf-tls-tls13-11] Section 6.3.2.3.
- *
- *     struct {
- *         NamedGroup group;
- *         opaque key_exchange<1..2^16-1>;
- *     } KeyShareEntry;
- *
- *     struct {
- *         select (role) {
- *             case client:
- *                 KeyShareEntry client_shares<4..2^16-1>;
- *
- *             case server:
- *                 KeyShareEntry server_share;
- *         }
- *     } KeyShare;
- */
-static SECStatus
-tls13_SizeOfKeyShareEntry(ssl3KeyPair *pair)
-{
-    return 2 + 2 + tls13_SizeOfECDHEKeyShareKEX(pair);
-}
-
-static SECStatus
-tls13_EncodeKeyShareEntry(sslSocket *ss, ssl3KeyPair *pair)
-{
-    SECStatus rv;
-
-    /* This currently only works for ECC keys */
-    PORT_Assert(pair->pubKey->keyType == ecKey);
-    if (pair->pubKey->keyType != ecKey) {
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        return SECFailure;
-    }
-
-    rv = ssl3_AppendHandshakeNumber(ss, tls13_GroupForECDHEKeyShare(pair), 2);
-    if (rv != SECSuccess)
-        return rv;
-
-    rv = ssl3_AppendHandshakeNumber(ss, tls13_SizeOfECDHEKeyShareKEX(pair), 2);
-    if (rv != SECSuccess)
-        return rv;
-
-    rv = tls13_EncodeECDHEKeyShareKEX(ss, pair);
-    if (rv != SECSuccess)
-        return rv;
-
-    return SECSuccess;
-}
-
-static PRInt32
-tls13_ClientSendKeyShareXtn(sslSocket *ss, PRBool append,
-                            PRUint32 maxBytes)
-{
-    SECStatus rv;
-    PRUint32 entry_length;
-    PRUint32 extension_length;
-
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        return 0;
-    }
-
-    /* Optimistically try to send an ECDHE key using the
-     * preexisting key (in future will be keys) */
-    SSL_TRC(3, ("%d: TLS13[%d]: send client key share xtn",
-                SSL_GETPID(), ss->fd));
-
-    entry_length = tls13_SizeOfKeyShareEntry(ss->ephemeralECDHKeyPair);
-    /* Type + length + vector_length + entry */
-    extension_length = 2 + 2 + 2 + entry_length;
-
-    if (maxBytes < extension_length) {
-        PORT_Assert(0);
-        return 0;
-    }
-
-    if (append) {
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_key_share_xtn, 2);
-        if (rv != SECSuccess)
-            goto loser;
-        rv = ssl3_AppendHandshakeNumber(ss, entry_length + 2, 2); /* Extension length */
-        if (rv != SECSuccess)
-            goto loser;
-        rv = ssl3_AppendHandshakeNumber(ss, entry_length, 2); /* Vector length */
-        if (rv != SECSuccess)
-            goto loser;
-        rv = tls13_EncodeKeyShareEntry(ss, ss->ephemeralECDHKeyPair);
-        if (rv != SECSuccess)
-            goto loser;
-
-        ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
-            ssl_tls13_key_share_xtn;
-    }
-
-    return extension_length;
-
-loser:
-    return -1;
-}
-
-static SECStatus
-tls13_HandleKeyShareEntry(sslSocket *ss, SECItem *data)
-{
-    SECStatus rv;
-    PRInt32 group;
-    TLS13KeyShareEntry *ks = NULL;
-    SECItem share = { siBuffer, NULL, 0 };
-
-    group = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
-    if (group < 0) {
-        PORT_SetError(SSL_ERROR_RX_MALFORMED_KEY_SHARE);
-        goto loser;
-    }
-
-    rv = ssl3_ConsumeHandshakeVariable(ss, &share, 2, &data->data,
-                                       &data->len);
-    if (rv != SECSuccess)
-        goto loser;
-
-    ks = PORT_ZNew(TLS13KeyShareEntry);
-    if (!ks)
-        goto loser;
-    ks->group = group;
-
-    rv = SECITEM_CopyItem(NULL, &ks->key_exchange, &share);
-    if (rv != SECSuccess)
-        goto loser;
-
-    PR_APPEND_LINK(&ks->link, &ss->ssl3.hs.remoteKeyShares);
-    return SECSuccess;
-
-loser:
-    if (ks)
-        tls13_DestroyKeyShareEntry(ks);
-    return SECFailure;
-}
-
-/* Handle an incoming KeyShare extension at the client and copy to
- * |ss->ssl3.hs.remoteKeyShares| for future use. The key
- * share is processed in tls13_HandleServerKeyShare(). */
-static SECStatus
-tls13_ClientHandleKeyShareXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
-{
-    SECStatus rv;
-
-    PORT_Assert(!ss->sec.isServer);
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        /* This can't happen because the extension processing
-         * code filters out TLS 1.3 extensions when not in
-         * TLS 1.3 mode. */
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        return SECFailure;
-    }
-
-    SSL_TRC(3, ("%d: SSL3[%d]: handle key_share extension",
-                SSL_GETPID(), ss->fd));
-
-    rv = tls13_HandleKeyShareEntry(ss, data);
-    if (rv != SECSuccess) {
-        PORT_SetError(SSL_ERROR_RX_MALFORMED_KEY_SHARE);
-        return SECFailure;
-    }
-
-    if (data->len) {
-        PORT_SetError(SSL_ERROR_RX_MALFORMED_KEY_SHARE);
-        return SECFailure;
-    }
-
-    return SECSuccess;
-}
-
-/* Handle an incoming KeyShare extension at the server and copy to
- * |ss->ssl3.hs.remoteKeyShares| for future use. The key
- * share is processed in tls13_HandleClientKeyShare(). */
-static SECStatus
-tls13_ServerHandleKeyShareXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
-{
-    SECStatus rv;
-    PRInt32 length;
-
-    PORT_Assert(ss->sec.isServer);
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        return SECSuccess;
-    }
-
-    SSL_TRC(3, ("%d: SSL3[%d]: handle key_share extension",
-                SSL_GETPID(), ss->fd));
-
-    /* Redundant length because of TLS encoding (this vector consumes
-     * the entire extension.) */
-    length = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data,
-                                         &data->len);
-    if (length < 0)
-        goto loser;
-    if (length != data->len) {
-        /* Check for consistency */
-        PORT_SetError(SSL_ERROR_RX_MALFORMED_KEY_SHARE);
-        goto loser;
-    }
-
-    while (data->len) {
-        rv = tls13_HandleKeyShareEntry(ss, data);
-        if (rv != SECSuccess)
-            goto loser;
-    }
-    return SECSuccess;
-
-loser:
-    tls13_DestroyKeyShares(&ss->ssl3.hs.remoteKeyShares);
-    return SECFailure;
-}
-
-PRInt32
-tls13_ServerSendKeyShareXtn(sslSocket *ss, PRBool append,
-                            PRUint32 maxBytes)
-{
-    PRUint32 extension_length;
-    PRUint32 entry_length;
-    SECStatus rv;
-
-    switch (ss->ssl3.hs.kea_def->exchKeyType) {
-#ifndef NSS_DISABLE_ECC
-        case ssl_kea_ecdh:
-            PORT_Assert(ss->ephemeralECDHKeyPair);
-            break;
-#endif
-        default:
-            /* got an unknown or unsupported Key Exchange Algorithm.
-             * Can't happen because tls13_HandleClientKeyShare
-             * enforces that we are ssl_kea_ecdh. */
-            PORT_Assert(0);
-            tls13_FatalError(ss, SEC_ERROR_UNSUPPORTED_KEYALG, internal_error);
-            return SECFailure;
-    }
-
-    entry_length = tls13_SizeOfKeyShareEntry(ss->ephemeralECDHKeyPair);
-    extension_length = 2 + 2 + entry_length; /* Type + length + entry_length */
-    if (maxBytes < extension_length) {
-        PORT_Assert(0);
-        return 0;
-    }
-
-    if (append) {
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_key_share_xtn, 2);
-        if (rv != SECSuccess)
-            goto loser;
-
-        rv = ssl3_AppendHandshakeNumber(ss, entry_length, 2);
-        if (rv != SECSuccess)
-            goto loser;
-
-        rv = tls13_EncodeKeyShareEntry(ss, ss->ephemeralECDHKeyPair);
-        if (rv != SECSuccess)
-            goto loser;
-    }
-
-    return extension_length;
-
-loser:
-    return -1;
-}
diff --git a/net/third_party/nss/ssl/ssl3gthr.c b/net/third_party/nss/ssl/ssl3gthr.c
deleted file mode 100644
index ea27713..0000000
--- a/net/third_party/nss/ssl/ssl3gthr.c
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- * Gather (Read) entire SSL3 records from socket into buffer.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "cert.h"
-#include "ssl.h"
-#include "sslimpl.h"
-#include "ssl3prot.h"
-
-/*
- * Attempt to read in an entire SSL3 record.
- * Blocks here for blocking sockets, otherwise returns -1 with
- *  PR_WOULD_BLOCK_ERROR when socket would block.
- *
- * returns  1 if received a complete SSL3 record.
- * returns  0 if recv returns EOF
- * returns -1 if recv returns < 0
- *  (The error value may have already been set to PR_WOULD_BLOCK_ERROR)
- *
- * Caller must hold the recv buf lock.
- *
- * The Gather state machine has 3 states:  GS_INIT, GS_HEADER, GS_DATA.
- * GS_HEADER: waiting for the 5-byte SSL3 record header to come in.
- * GS_DATA:   waiting for the body of the SSL3 record   to come in.
- *
- * This loop returns when either
- *      (a) an error or EOF occurs,
- *  (b) PR_WOULD_BLOCK_ERROR,
- *  (c) data (entire SSL3 record) has been received.
- */
-static int
-ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags)
-{
-    unsigned char *bp;
-    unsigned char *lbp;
-    int nb;
-    int err;
-    int rv = 1;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    if (gs->state == GS_INIT) {
-        gs->state = GS_HEADER;
-        gs->remainder = 5;
-        gs->offset = 0;
-        gs->writeOffset = 0;
-        gs->readOffset = 0;
-        gs->inbuf.len = 0;
-    }
-
-    lbp = gs->inbuf.buf;
-    for (;;) {
-        SSL_TRC(30, ("%d: SSL3[%d]: gather state %d (need %d more)",
-                     SSL_GETPID(), ss->fd, gs->state, gs->remainder));
-        bp = ((gs->state != GS_HEADER) ? lbp : gs->hdr) + gs->offset;
-        nb = ssl_DefRecv(ss, bp, gs->remainder, flags);
-
-        if (nb > 0) {
-            PRINT_BUF(60, (ss, "raw gather data:", bp, nb));
-        } else if (nb == 0) {
-            /* EOF */
-            SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd));
-            rv = 0;
-            break;
-        } else /* if (nb < 0) */ {
-            SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd,
-                     PR_GetError()));
-            rv = SECFailure;
-            break;
-        }
-
-        PORT_Assert((unsigned int)nb <= gs->remainder);
-        if ((unsigned int)nb > gs->remainder) {
-            /* ssl_DefRecv is misbehaving!  this error is fatal to SSL. */
-            gs->state = GS_INIT; /* so we don't crash next time */
-            rv = SECFailure;
-            break;
-        }
-
-        gs->offset += nb;
-        gs->remainder -= nb;
-        if (gs->state == GS_DATA)
-            gs->inbuf.len += nb;
-
-        /* if there's more to go, read some more. */
-        if (gs->remainder > 0) {
-            continue;
-        }
-
-        /* have received entire record header, or entire record. */
-        switch (gs->state) {
-            case GS_HEADER:
-              /*
-              ** Have received SSL3 record header in gs->hdr.
-              ** Now extract the length of the following encrypted data,
-              ** and then read in the rest of the SSL3 record into gs->inbuf.
-              */
-                gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4];
-
-                /* This is the max fragment length for an encrypted fragment
-                ** plus the size of the record header.
-                */
-                if (gs->remainder > (MAX_FRAGMENT_LENGTH + 2048 + 5)) {
-                    SSL3_SendAlert(ss, alert_fatal, unexpected_message);
-                    gs->state = GS_INIT;
-                    PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
-                    return SECFailure;
-                }
-
-                gs->state = GS_DATA;
-                gs->offset = 0;
-                gs->inbuf.len = 0;
-
-                if (gs->remainder > gs->inbuf.space) {
-                    err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
-                    if (err) { /* realloc has set error code to no mem. */
-                        return err;
-                    }
-                    lbp = gs->inbuf.buf;
-                }
-                break; /* End this case.  Continue around the loop. */
-
-            case GS_DATA:
-                /*
-                ** SSL3 record has been completely received.
-                */
-                gs->state = GS_INIT;
-                return 1;
-        }
-    }
-
-    return rv;
-}
-
-/*
- * Read in an entire DTLS record.
- *
- * Blocks here for blocking sockets, otherwise returns -1 with
- *  PR_WOULD_BLOCK_ERROR when socket would block.
- *
- * This is simpler than SSL because we are reading on a datagram socket
- * and datagrams must contain >=1 complete records.
- *
- * returns  1 if received a complete DTLS record.
- * returns  0 if recv returns EOF
- * returns -1 if recv returns < 0
- *  (The error value may have already been set to PR_WOULD_BLOCK_ERROR)
- *
- * Caller must hold the recv buf lock.
- *
- * This loop returns when either
- *      (a) an error or EOF occurs,
- *  (b) PR_WOULD_BLOCK_ERROR,
- *  (c) data (entire DTLS record) has been received.
- */
-static int
-dtls_GatherData(sslSocket *ss, sslGather *gs, int flags)
-{
-    int nb;
-    int err;
-    int rv = 1;
-
-    SSL_TRC(30, ("dtls_GatherData"));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-
-    gs->state = GS_HEADER;
-    gs->offset = 0;
-
-    if (gs->dtlsPacketOffset == gs->dtlsPacket.len) { /* No data left */
-        gs->dtlsPacketOffset = 0;
-        gs->dtlsPacket.len = 0;
-
-        /* Resize to the maximum possible size so we can fit a full datagram */
-        /* This is the max fragment length for an encrypted fragment
-        ** plus the size of the record header.
-        ** This magic constant is copied from ssl3_GatherData, with 5 changed
-        ** to 13 (the size of the record header).
-        */
-        if (gs->dtlsPacket.space < MAX_FRAGMENT_LENGTH + 2048 + 13) {
-            err = sslBuffer_Grow(&gs->dtlsPacket,
-                                 MAX_FRAGMENT_LENGTH + 2048 + 13);
-            if (err) { /* realloc has set error code to no mem. */
-                return err;
-            }
-        }
-
-        /* recv() needs to read a full datagram at a time */
-        nb = ssl_DefRecv(ss, gs->dtlsPacket.buf, gs->dtlsPacket.space, flags);
-
-        if (nb > 0) {
-            PRINT_BUF(60, (ss, "raw gather data:", gs->dtlsPacket.buf, nb));
-        } else if (nb == 0) {
-            /* EOF */
-            SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd));
-            rv = 0;
-            return rv;
-        } else /* if (nb < 0) */ {
-            SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd,
-                     PR_GetError()));
-            rv = SECFailure;
-            return rv;
-        }
-
-        gs->dtlsPacket.len = nb;
-    }
-
-    /* At this point we should have >=1 complete records lined up in
-     * dtlsPacket. Read off the header.
-     */
-    if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < 13) {
-        SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet "
-                 "too short to contain header",
-                 SSL_GETPID(), ss->fd));
-        PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
-        gs->dtlsPacketOffset = 0;
-        gs->dtlsPacket.len = 0;
-        rv = SECFailure;
-        return rv;
-    }
-    memcpy(gs->hdr, gs->dtlsPacket.buf + gs->dtlsPacketOffset, 13);
-    gs->dtlsPacketOffset += 13;
-
-    /* Have received SSL3 record header in gs->hdr. */
-    gs->remainder = (gs->hdr[11] << 8) | gs->hdr[12];
-
-    if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < gs->remainder) {
-        SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet too short "
-                 "to contain rest of body",
-                 SSL_GETPID(), ss->fd));
-        PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
-        gs->dtlsPacketOffset = 0;
-        gs->dtlsPacket.len = 0;
-        rv = SECFailure;
-        return rv;
-    }
-
-    /* OK, we have at least one complete packet, copy into inbuf */
-    if (gs->remainder > gs->inbuf.space) {
-        err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
-        if (err) { /* realloc has set error code to no mem. */
-            return err;
-        }
-    }
-
-    memcpy(gs->inbuf.buf, gs->dtlsPacket.buf + gs->dtlsPacketOffset,
-           gs->remainder);
-    gs->inbuf.len = gs->remainder;
-    gs->offset = gs->remainder;
-    gs->dtlsPacketOffset += gs->remainder;
-    gs->state = GS_INIT;
-
-    return 1;
-}
-
-/* Gather in a record and when complete, Handle that record.
- * Repeat this until the handshake is complete,
- * or until application data is available.
- *
- * Returns  1 when the handshake is completed without error, or
- *                 application data is available.
- * Returns  0 if ssl3_GatherData hits EOF.
- * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error.
- * Returns -2 on SECWouldBlock return from ssl3_HandleRecord.
- *
- * Called from ssl_GatherRecord1stHandshake       in sslcon.c,
- *    and from SSL_ForceHandshake in sslsecur.c
- *    and from ssl3_GatherAppDataRecord below (<- DoRecv in sslsecur.c).
- *
- * Caller must hold the recv buf lock.
- */
-int
-ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
-{
-    SSL3Ciphertext cText;
-    int rv;
-    PRBool keepGoing = PR_TRUE;
-
-    SSL_TRC(30, ("ssl3_GatherCompleteHandshake"));
-
-    /* ssl3_HandleRecord may end up eventually calling ssl_FinishHandshake,
-     * which requires the 1stHandshakeLock, which must be acquired before the
-     * RecvBufLock.
-     */
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-
-    do {
-        PRBool handleRecordNow = PR_FALSE;
-
-        ssl_GetSSL3HandshakeLock(ss);
-
-        /* Without this, we may end up wrongly reporting
-         * SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the
-         * peer while we are waiting to be restarted.
-         */
-        if (ss->ssl3.hs.restartTarget) {
-            ssl_ReleaseSSL3HandshakeLock(ss);
-            PORT_SetError(PR_WOULD_BLOCK_ERROR);
-            return (int)SECFailure;
-        }
-
-        /* Treat an empty msgState like a NULL msgState. (Most of the time
-         * when ssl3_HandleHandshake returns SECWouldBlock, it leaves
-         * behind a non-NULL but zero-length msgState).
-         * Test: async_cert_restart_server_sends_hello_request_first_in_separate_record
-         */
-        if (ss->ssl3.hs.msgState.buf) {
-            if (ss->ssl3.hs.msgState.len == 0) {
-                ss->ssl3.hs.msgState.buf = NULL;
-            } else {
-                handleRecordNow = PR_TRUE;
-            }
-        }
-
-        ssl_ReleaseSSL3HandshakeLock(ss);
-
-        if (handleRecordNow) {
-            /* ssl3_HandleHandshake previously returned SECWouldBlock and the
-             * as-yet-unprocessed plaintext of that previous handshake record.
-             * We need to process it now before we overwrite it with the next
-             * handshake record.
-             */
-            rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf);
-        } else {
-            /* bring in the next sslv3 record. */
-            if (ss->recvdCloseNotify) {
-                /* RFC 5246 Section 7.2.1:
-                 *   Any data received after a closure alert is ignored.
-                 */
-                return 0;
-            }
-            if (!IS_DTLS(ss)) {
-                rv = ssl3_GatherData(ss, &ss->gs, flags);
-            } else {
-                rv = dtls_GatherData(ss, &ss->gs, flags);
-
-                /* If we got a would block error, that means that no data was
-                 * available, so we check the timer to see if it's time to
-                 * retransmit */
-                if (rv == SECFailure &&
-                    (PORT_GetError() == PR_WOULD_BLOCK_ERROR)) {
-                    ssl_GetSSL3HandshakeLock(ss);
-                    dtls_CheckTimer(ss);
-                    ssl_ReleaseSSL3HandshakeLock(ss);
-                    /* Restore the error in case something succeeded */
-                    PORT_SetError(PR_WOULD_BLOCK_ERROR);
-                }
-            }
-
-            if (rv <= 0) {
-                return rv;
-            }
-
-            /* decipher it, and handle it if it's a handshake.
-             * If it's application data, ss->gs.buf will not be empty upon return.
-             * If it's a change cipher spec, alert, or handshake message,
-             * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSuccess.
-             */
-            cText.type = (SSL3ContentType)ss->gs.hdr[0];
-            cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2];
-
-            if (IS_DTLS(ss)) {
-                int i;
-
-                cText.version = dtls_DTLSVersionToTLSVersion(cText.version);
-                /* DTLS sequence number */
-                cText.seq_num.high = 0;
-                cText.seq_num.low = 0;
-                for (i = 0; i < 4; i++) {
-                    cText.seq_num.high <<= 8;
-                    cText.seq_num.low <<= 8;
-                    cText.seq_num.high |= ss->gs.hdr[3 + i];
-                    cText.seq_num.low |= ss->gs.hdr[7 + i];
-                }
-            }
-
-            cText.buf = &ss->gs.inbuf;
-            rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf);
-        }
-        if (rv < 0) {
-            return ss->recvdCloseNotify ? 0 : rv;
-        }
-        if (ss->gs.buf.len > 0) {
-            /* We have application data to return to the application. This
-             * prioritizes returning application data to the application over
-             * completing any renegotiation handshake we may be doing.
-             */
-            PORT_Assert(ss->firstHsDone);
-            PORT_Assert(cText.type == content_application_data);
-            break;
-        }
-
-        PORT_Assert(keepGoing);
-        ssl_GetSSL3HandshakeLock(ss);
-        if (ss->ssl3.hs.ws == idle_handshake) {
-            /* We are done with the current handshake so stop trying to
-             * handshake. Note that it would be safe to test ss->firstHsDone
-             * instead of ss->ssl3.hs.ws. By testing ss->ssl3.hs.ws instead,
-             * we prioritize completing a renegotiation handshake over sending
-             * application data.
-             */
-            PORT_Assert(ss->firstHsDone);
-            PORT_Assert(!ss->ssl3.hs.canFalseStart);
-            keepGoing = PR_FALSE;
-        } else if (ss->ssl3.hs.canFalseStart) {
-            /* Prioritize sending application data over trying to complete
-             * the handshake if we're false starting.
-             *
-             * If we were to do this check at the beginning of the loop instead
-             * of here, then this function would become be a no-op after
-             * receiving the ServerHelloDone in the false start case, and we
-             * would never complete the handshake.
-             */
-            PORT_Assert(!ss->firstHsDone);
-
-            if (ssl3_WaitingForServerSecondRound(ss)) {
-                keepGoing = PR_FALSE;
-            } else {
-                ss->ssl3.hs.canFalseStart = PR_FALSE;
-            }
-        }
-        ssl_ReleaseSSL3HandshakeLock(ss);
-    } while (keepGoing);
-
-    ss->gs.readOffset = 0;
-    ss->gs.writeOffset = ss->gs.buf.len;
-    return 1;
-}
-
-/* Repeatedly gather in a record and when complete, Handle that record.
- * Repeat this until some application data is received.
- *
- * Returns  1 when application data is available.
- * Returns  0 if ssl3_GatherData hits EOF.
- * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error.
- * Returns -2 on SECWouldBlock return from ssl3_HandleRecord.
- *
- * Called from DoRecv in sslsecur.c
- * Caller must hold the recv buf lock.
- */
-int
-ssl3_GatherAppDataRecord(sslSocket *ss, int flags)
-{
-    int rv;
-
-    /* ssl3_GatherCompleteHandshake requires both of these locks. */
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-
-    do {
-        rv = ssl3_GatherCompleteHandshake(ss, flags);
-    } while (rv > 0 && ss->gs.buf.len == 0);
-
-    return rv;
-}
diff --git a/net/third_party/nss/ssl/ssl3prot.h b/net/third_party/nss/ssl/ssl3prot.h
deleted file mode 100644
index 928d0596..0000000
--- a/net/third_party/nss/ssl/ssl3prot.h
+++ /dev/null
@@ -1,323 +0,0 @@
-/* Private header file of libSSL.
- * Various and sundry protocol constants. DON'T CHANGE THESE. These
- * values are defined by the SSL 3.0 protocol specification.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef __ssl3proto_h_
-#define __ssl3proto_h_
-
-typedef PRUint8 SSL3Opaque;
-
-typedef PRUint16 SSL3ProtocolVersion;
-/* version numbers are defined in sslproto.h */
-
-/* The TLS 1.3 draft version. Used to avoid negotiating
- * between incompatible pre-standard TLS 1.3 drafts.
- * TODO(ekr@rtfm.com): Remove when TLS 1.3 is published. */
-#define TLS_1_3_DRAFT_VERSION 11
-
-typedef PRUint16 ssl3CipherSuite;
-/* The cipher suites are defined in sslproto.h */
-
-#define MAX_CERT_TYPES 10
-#define MAX_COMPRESSION_METHODS 10
-#define MAX_MAC_LENGTH 64
-#define MAX_PADDING_LENGTH 64
-#define MAX_KEY_LENGTH 64
-#define EXPORT_KEY_LENGTH 5
-#define SSL3_RANDOM_LENGTH 32
-
-#define SSL3_RECORD_HEADER_LENGTH 5
-
-/* SSL3_RECORD_HEADER_LENGTH + epoch/sequence_number */
-#define DTLS_RECORD_HEADER_LENGTH 13
-
-#define MAX_FRAGMENT_LENGTH 16384
-
-typedef enum {
-    content_change_cipher_spec = 20,
-    content_alert = 21,
-    content_handshake = 22,
-    content_application_data = 23
-} SSL3ContentType;
-
-typedef struct {
-    SSL3ContentType type;
-    SSL3ProtocolVersion version;
-    PRUint16 length;
-    SECItem fragment;
-} SSL3Plaintext;
-
-typedef struct {
-    SSL3ContentType type;
-    SSL3ProtocolVersion version;
-    PRUint16 length;
-    SECItem fragment;
-} SSL3Compressed;
-
-typedef struct {
-    SECItem content;
-    SSL3Opaque MAC[MAX_MAC_LENGTH];
-} SSL3GenericStreamCipher;
-
-typedef struct {
-    SECItem content;
-    SSL3Opaque MAC[MAX_MAC_LENGTH];
-    PRUint8 padding[MAX_PADDING_LENGTH];
-    PRUint8 padding_length;
-} SSL3GenericBlockCipher;
-
-typedef enum { change_cipher_spec_choice = 1 } SSL3ChangeCipherSpecChoice;
-
-typedef struct {
-    SSL3ChangeCipherSpecChoice choice;
-} SSL3ChangeCipherSpec;
-
-typedef enum { alert_warning = 1,
-               alert_fatal = 2 } SSL3AlertLevel;
-
-typedef enum {
-    close_notify = 0,
-    unexpected_message = 10,
-    bad_record_mac = 20,
-    decryption_failed_RESERVED = 21, /* do not send; see RFC 5246 */
-    record_overflow = 22,            /* TLS only */
-    decompression_failure = 30,
-    handshake_failure = 40,
-    no_certificate = 41, /* SSL3 only, NOT TLS */
-    bad_certificate = 42,
-    unsupported_certificate = 43,
-    certificate_revoked = 44,
-    certificate_expired = 45,
-    certificate_unknown = 46,
-    illegal_parameter = 47,
-
-    /* All alerts below are TLS only. */
-    unknown_ca = 48,
-    access_denied = 49,
-    decode_error = 50,
-    decrypt_error = 51,
-    export_restriction = 60,
-    protocol_version = 70,
-    insufficient_security = 71,
-    internal_error = 80,
-    inappropriate_fallback = 86, /* could also be sent for SSLv3 */
-    user_canceled = 90,
-    no_renegotiation = 100,
-
-    /* Alerts for client hello extensions */
-    missing_extension = 109,
-    unsupported_extension = 110,
-    certificate_unobtainable = 111,
-    unrecognized_name = 112,
-    bad_certificate_status_response = 113,
-    bad_certificate_hash_value = 114,
-    no_application_protocol = 120
-
-} SSL3AlertDescription;
-
-typedef struct {
-    SSL3AlertLevel level;
-    SSL3AlertDescription description;
-} SSL3Alert;
-
-typedef enum {
-    hello_request = 0,
-    client_hello = 1,
-    server_hello = 2,
-    hello_verify_request = 3,
-    new_session_ticket = 4,
-    hello_retry_request = 6,
-    encrypted_extensions = 8,
-    certificate = 11,
-    server_key_exchange = 12,
-    certificate_request = 13,
-    server_hello_done = 14,
-    certificate_verify = 15,
-    client_key_exchange = 16,
-    finished = 20,
-    certificate_status = 22,
-    next_proto = 67,
-    channelid_encrypted_extensions = 203
-} SSL3HandshakeType;
-
-typedef struct {
-    PRUint8 empty;
-} SSL3HelloRequest;
-
-typedef struct {
-    SSL3Opaque rand[SSL3_RANDOM_LENGTH];
-} SSL3Random;
-
-typedef struct {
-    SSL3Opaque id[32];
-    PRUint8 length;
-} SSL3SessionID;
-
-typedef struct {
-    SSL3ProtocolVersion client_version;
-    SSL3Random random;
-    SSL3SessionID session_id;
-    SECItem cipher_suites;
-    PRUint8 cm_count;
-    SSLCompressionMethod compression_methods[MAX_COMPRESSION_METHODS];
-} SSL3ClientHello;
-
-typedef struct {
-    SSL3ProtocolVersion server_version;
-    SSL3Random random;
-    SSL3SessionID session_id;
-    ssl3CipherSuite cipher_suite;
-    SSLCompressionMethod compression_method;
-} SSL3ServerHello;
-
-typedef struct {
-    SECItem list;
-} SSL3Certificate;
-
-/* SSL3SignType moved to ssl.h */
-
-/* The SSL key exchange method used */
-typedef enum {
-    kea_null,
-    kea_rsa,
-    kea_rsa_export,
-    kea_rsa_export_1024,
-    kea_dh_dss,
-    kea_dh_dss_export,
-    kea_dh_rsa,
-    kea_dh_rsa_export,
-    kea_dhe_dss,
-    kea_dhe_dss_export,
-    kea_dhe_rsa,
-    kea_dhe_rsa_export,
-    kea_dh_anon,
-    kea_dh_anon_export,
-    kea_rsa_fips,
-    kea_ecdh_ecdsa,
-    kea_ecdhe_ecdsa,
-    kea_ecdh_rsa,
-    kea_ecdhe_rsa,
-    kea_ecdh_anon
-} SSL3KeyExchangeAlgorithm;
-
-typedef struct {
-    SECItem modulus;
-    SECItem exponent;
-} SSL3ServerRSAParams;
-
-typedef struct {
-    SECItem p;
-    SECItem g;
-    SECItem Ys;
-} SSL3ServerDHParams;
-
-typedef struct {
-    union {
-        SSL3ServerDHParams dh;
-        SSL3ServerRSAParams rsa;
-    } u;
-} SSL3ServerParams;
-
-/* SSL3HashesIndividually contains a combination MD5/SHA1 hash, as used in TLS
- * prior to 1.2. */
-typedef struct {
-    PRUint8 md5[16];
-    PRUint8 sha[20];
-} SSL3HashesIndividually;
-
-/* SSL3Hashes contains an SSL hash value. The digest is contained in |u.raw|
- * which, if |hashAlg==ssl_hash_none| is also a SSL3HashesIndividually
- * struct. */
-typedef struct {
-    unsigned int len;
-    SSLHashType hashAlg;
-    union {
-        PRUint8 raw[64];
-        SSL3HashesIndividually s;
-    } u;
-} SSL3Hashes;
-
-typedef struct {
-    union {
-        SSL3Opaque anonymous;
-        SSL3Hashes certified;
-    } u;
-} SSL3ServerKeyExchange;
-
-typedef enum {
-    ct_RSA_sign = 1,
-    ct_DSS_sign = 2,
-    ct_RSA_fixed_DH = 3,
-    ct_DSS_fixed_DH = 4,
-    ct_RSA_ephemeral_DH = 5,
-    ct_DSS_ephemeral_DH = 6,
-    ct_ECDSA_sign = 64,
-    ct_RSA_fixed_ECDH = 65,
-    ct_ECDSA_fixed_ECDH = 66
-
-} SSL3ClientCertificateType;
-
-typedef struct {
-    SSL3Opaque client_version[2];
-    SSL3Opaque random[46];
-} SSL3RSAPreMasterSecret;
-
-typedef SSL3Opaque SSL3MasterSecret[48];
-
-typedef enum {
-    sender_client = 0x434c4e54,
-    sender_server = 0x53525652
-} SSL3Sender;
-
-typedef SSL3HashesIndividually SSL3Finished;
-
-typedef struct {
-    SSL3Opaque verify_data[12];
-} TLSFinished;
-
-/*
- * TLS extension related data structures and constants.
- */
-
-/* SessionTicket extension related data structures. */
-
-/* NewSessionTicket handshake message. */
-typedef struct {
-    PRUint32 received_timestamp;
-    PRUint32 ticket_lifetime_hint;
-    SECItem ticket;
-} NewSessionTicket;
-
-typedef enum {
-    CLIENT_AUTH_ANONYMOUS = 0,
-    CLIENT_AUTH_CERTIFICATE = 1
-} ClientAuthenticationType;
-
-typedef struct {
-    ClientAuthenticationType client_auth_type;
-    union {
-        SSL3Opaque *certificate_list;
-    } identity;
-} ClientIdentity;
-
-#define SESS_TICKET_KEY_NAME_LEN 16
-#define SESS_TICKET_KEY_NAME_PREFIX "NSS!"
-#define SESS_TICKET_KEY_NAME_PREFIX_LEN 4
-#define SESS_TICKET_KEY_VAR_NAME_LEN 12
-
-typedef struct {
-    unsigned char *key_name;
-    unsigned char *iv;
-    SECItem encrypted_state;
-    unsigned char *mac;
-} EncryptedSessionTicket;
-
-#define TLS_EX_SESS_TICKET_MAC_LENGTH 32
-
-#define TLS_STE_NO_SERVER_NAME -1
-
-#endif /* __ssl3proto_h_ */
diff --git a/net/third_party/nss/ssl/sslauth.c b/net/third_party/nss/ssl/sslauth.c
deleted file mode 100644
index e78a513a..0000000
--- a/net/third_party/nss/ssl/sslauth.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "cert.h"
-#include "secitem.h"
-#include "ssl.h"
-#include "sslimpl.h"
-#include "sslproto.h"
-#include "pk11func.h"
-#include "ocsp.h"
-
-/* NEED LOCKS IN HERE.  */
-CERTCertificate *
-SSL_PeerCertificate(PRFileDesc *fd)
-{
-    sslSocket *ss;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate",
-                 SSL_GETPID(), fd));
-        return 0;
-    }
-    if (ss->opt.useSecurity && ss->sec.peerCert) {
-        return CERT_DupCertificate(ss->sec.peerCert);
-    }
-    return 0;
-}
-
-/* NEED LOCKS IN HERE.  */
-CERTCertList *
-SSL_PeerCertificateChain(PRFileDesc *fd)
-{
-    sslSocket *ss;
-    CERTCertList *chain = NULL;
-    CERTCertificate *cert;
-    ssl3CertNode *cur;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificateChain",
-                 SSL_GETPID(), fd));
-        return NULL;
-    }
-    if (!ss->opt.useSecurity || !ss->sec.peerCert) {
-        PORT_SetError(SSL_ERROR_NO_CERTIFICATE);
-        return NULL;
-    }
-    chain = CERT_NewCertList();
-    if (!chain) {
-        return NULL;
-    }
-    cert = CERT_DupCertificate(ss->sec.peerCert);
-    if (CERT_AddCertToListTail(chain, cert) != SECSuccess) {
-        goto loser;
-    }
-    for (cur = ss->ssl3.peerCertChain; cur; cur = cur->next) {
-        cert = CERT_DupCertificate(cur->cert);
-        if (CERT_AddCertToListTail(chain, cert) != SECSuccess) {
-            goto loser;
-        }
-    }
-    return chain;
-
-loser:
-    CERT_DestroyCertList(chain);
-    return NULL;
-}
-
-/* NEED LOCKS IN HERE.  */
-CERTCertificate *
-SSL_LocalCertificate(PRFileDesc *fd)
-{
-    sslSocket *ss;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate",
-                 SSL_GETPID(), fd));
-        return NULL;
-    }
-    if (ss->opt.useSecurity) {
-        if (ss->sec.localCert) {
-            return CERT_DupCertificate(ss->sec.localCert);
-        }
-        if (ss->sec.ci.sid && ss->sec.ci.sid->localCert) {
-            return CERT_DupCertificate(ss->sec.ci.sid->localCert);
-        }
-    }
-    return NULL;
-}
-
-/* NEED LOCKS IN HERE.  */
-SECStatus
-SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1,
-                   char **ip, char **sp)
-{
-    sslSocket *ss;
-    const char *cipherName;
-    PRBool isDes = PR_FALSE;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SecurityStatus",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (cp)
-        *cp = 0;
-    if (kp0)
-        *kp0 = 0;
-    if (kp1)
-        *kp1 = 0;
-    if (ip)
-        *ip = 0;
-    if (sp)
-        *sp = 0;
-    if (op) {
-        *op = SSL_SECURITY_STATUS_OFF;
-    }
-
-    if (ss->opt.useSecurity && ss->enoughFirstHsDone) {
-        if (ss->version < SSL_LIBRARY_VERSION_3_0) {
-            cipherName = ssl_cipherName[ss->sec.cipherType];
-        } else {
-            cipherName = ssl3_cipherName[ss->sec.cipherType];
-        }
-        PORT_Assert(cipherName);
-        if (cipherName) {
-            if (PORT_Strstr(cipherName, "DES"))
-                isDes = PR_TRUE;
-
-            if (cp) {
-                *cp = PORT_Strdup(cipherName);
-            }
-        }
-
-        if (kp0) {
-            *kp0 = ss->sec.keyBits;
-            if (isDes)
-                *kp0 = (*kp0 * 7) / 8;
-        }
-        if (kp1) {
-            *kp1 = ss->sec.secretKeyBits;
-            if (isDes)
-                *kp1 = (*kp1 * 7) / 8;
-        }
-        if (op) {
-            if (ss->sec.keyBits == 0) {
-                *op = SSL_SECURITY_STATUS_OFF;
-            } else if (ss->sec.secretKeyBits < 90) {
-                *op = SSL_SECURITY_STATUS_ON_LOW;
-            } else {
-                *op = SSL_SECURITY_STATUS_ON_HIGH;
-            }
-        }
-
-        if (ip || sp) {
-            CERTCertificate *cert;
-
-            cert = ss->sec.peerCert;
-            if (cert) {
-                if (ip) {
-                    *ip = CERT_NameToAscii(&cert->issuer);
-                }
-                if (sp) {
-                    *sp = CERT_NameToAscii(&cert->subject);
-                }
-            } else {
-                if (ip) {
-                    *ip = PORT_Strdup("no certificate");
-                }
-                if (sp) {
-                    *sp = PORT_Strdup("no certificate");
-                }
-            }
-        }
-    }
-
-    return SECSuccess;
-}
-
-/************************************************************************/
-
-/* NEED LOCKS IN HERE.  */
-SECStatus
-SSL_AuthCertificateHook(PRFileDesc *s, SSLAuthCertificate func, void *arg)
-{
-    sslSocket *ss;
-
-    ss = ssl_FindSocket(s);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in AuthCertificateHook",
-                 SSL_GETPID(), s));
-        return SECFailure;
-    }
-
-    ss->authCertificate = func;
-    ss->authCertificateArg = arg;
-
-    return SECSuccess;
-}
-
-/* NEED LOCKS IN HERE.  */
-SECStatus
-SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func,
-                          void *arg)
-{
-    sslSocket *ss;
-
-    ss = ssl_FindSocket(s);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
-                 SSL_GETPID(), s));
-        return SECFailure;
-    }
-
-    ss->getClientAuthData = func;
-    ss->getClientAuthDataArg = arg;
-    return SECSuccess;
-}
-
-SECStatus
-SSL_SetClientChannelIDCallback(PRFileDesc *fd,
-                               SSLClientChannelIDCallback callback,
-                               void *arg)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetClientChannelIDCallback",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    ss->getChannelID = callback;
-    ss->getChannelIDArg = arg;
-
-    return SECSuccess;
-}
-
-/* NEED LOCKS IN HERE.  */
-SECStatus
-SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg)
-{
-    sslSocket *ss;
-
-    ss = ssl_FindSocket(s);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
-                 SSL_GETPID(), s));
-        return SECFailure;
-    }
-
-    ss->pkcs11PinArg = arg;
-    return SECSuccess;
-}
-
-/* This is the "default" authCert callback function.  It is called when a
- * certificate message is received from the peer and the local application
- * has not registered an authCert callback function.
- */
-SECStatus
-SSL_AuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer)
-{
-    SECStatus rv;
-    CERTCertDBHandle *handle;
-    sslSocket *ss;
-    SECCertUsage certUsage;
-    const char *hostname = NULL;
-    PRTime now = PR_Now();
-    SECItemArray *certStatusArray;
-
-    ss = ssl_FindSocket(fd);
-    PORT_Assert(ss != NULL);
-    if (!ss) {
-        return SECFailure;
-    }
-
-    handle = (CERTCertDBHandle *)arg;
-    certStatusArray = &ss->sec.ci.sid->peerCertStatus;
-
-    if (certStatusArray->len) {
-        PORT_SetError(0);
-        if (CERT_CacheOCSPResponseFromSideChannel(handle, ss->sec.peerCert, now,
-                                                  &certStatusArray->items[0],
-                                                  ss->pkcs11PinArg) !=
-            SECSuccess) {
-            PORT_Assert(PR_GetError() != 0);
-        }
-    }
-
-    /* this may seem backwards, but isn't. */
-    certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;
-
-    rv = CERT_VerifyCert(handle, ss->sec.peerCert, checkSig, certUsage,
-                         now, ss->pkcs11PinArg, NULL);
-
-    if (rv != SECSuccess || isServer)
-        return rv;
-
-    /* cert is OK.  This is the client side of an SSL connection.
-     * Now check the name field in the cert against the desired hostname.
-     * NB: This is our only defense against Man-In-The-Middle (MITM) attacks!
-     */
-    hostname = ss->url;
-    if (hostname && hostname[0])
-        rv = CERT_VerifyCertName(ss->sec.peerCert, hostname);
-    else
-        rv = SECFailure;
-    if (rv != SECSuccess)
-        PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
-
-    return rv;
-}
diff --git a/net/third_party/nss/ssl/sslcon.c b/net/third_party/nss/ssl/sslcon.c
deleted file mode 100644
index 95d27275..0000000
--- a/net/third_party/nss/ssl/sslcon.c
+++ /dev/null
@@ -1,3688 +0,0 @@
-/*
- * SSL v2 handshake functions, and functions common to SSL2 and SSL3.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nssrenam.h"
-#include "cert.h"
-#include "secitem.h"
-#include "sechash.h"
-#include "cryptohi.h" /* for SGN_ funcs */
-#include "keyhi.h"    /* for SECKEY_ high level functions. */
-#include "ssl.h"
-#include "sslimpl.h"
-#include "sslproto.h"
-#include "ssl3prot.h"
-#include "sslerr.h"
-#include "pk11func.h"
-#include "prinit.h"
-#include "prtime.h" /* for PR_Now() */
-
-static PRBool policyWasSet;
-
-#define ssl2_NUM_SUITES_IMPLEMENTED 6
-
-/* This list is sent back to the client when the client-hello message
- * contains no overlapping ciphers, so the client can report what ciphers
- * are supported by the server.  Unlike allCipherSuites (above), this list
- * is sorted by descending preference, not by cipherSuite number.
- */
-/* clang-format off */
-static const PRUint8 implementedCipherSuites[ssl2_NUM_SUITES_IMPLEMENTED * 3] = {
-    SSL_CK_RC4_128_WITH_MD5,                0x00, 0x80,
-    SSL_CK_RC2_128_CBC_WITH_MD5,            0x00, 0x80,
-    SSL_CK_DES_192_EDE3_CBC_WITH_MD5,       0x00, 0xC0,
-    SSL_CK_DES_64_CBC_WITH_MD5,             0x00, 0x40,
-    SSL_CK_RC4_128_EXPORT40_WITH_MD5,       0x00, 0x80,
-    SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5,   0x00, 0x80
-};
-
-
-typedef struct ssl2SpecsStr {
-    PRUint8 nkm; /* do this many hashes to generate key material. */
-    PRUint8 nkd; /* size of readKey and writeKey in bytes. */
-    PRUint8 blockSize;
-    PRUint8 blockShift;
-    CK_MECHANISM_TYPE mechanism;
-    PRUint8 keyLen; /* cipher symkey size in bytes. */
-    PRUint8 pubLen; /* publicly reveal this many bytes of key. */
-    PRUint8 ivLen;  /* length of IV data at *ca.    */
-} ssl2Specs;
-
-static const ssl2Specs ssl_Specs[] = {
-  /* NONE                                 */
-  { 0, 0, 0, 0 },
-  /* SSL_CK_RC4_128_WITH_MD5        */
-  { 2, 16, 1, 0, CKM_RC4,       16,   0, 0 },
-  /* SSL_CK_RC4_128_EXPORT40_WITH_MD5   */
-  { 2, 16, 1, 0, CKM_RC4,       16,  11, 0 },
-  /* SSL_CK_RC2_128_CBC_WITH_MD5        */
-  { 2, 16, 8, 3, CKM_RC2_CBC,   16,   0, 8 },
-  /* SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5   */
-  { 2, 16, 8, 3, CKM_RC2_CBC,   16,  11, 8 },
-  /* SSL_CK_IDEA_128_CBC_WITH_MD5       */
-  { 0, 0, 0, 0 },
-  /* SSL_CK_DES_64_CBC_WITH_MD5     */
-  { 1,  8, 8, 3, CKM_DES_CBC,    8,   0, 8 },
-  /* SSL_CK_DES_192_EDE3_CBC_WITH_MD5   */
-  { 3, 24, 8, 3, CKM_DES3_CBC,  24,   0, 8 },
-};
-/* clang-format on */
-
-#define SET_ERROR_CODE   /* reminder */
-#define TEST_FOR_FAILURE /* reminder */
-
-/*
-** Put a string tag in the library so that we can examine an executable
-** and see what kind of security it supports.
-*/
-const char *ssl_version = "SECURITY_VERSION:"
-                          " +us"
-                          " +export"
-#ifdef TRACE
-                          " +trace"
-#endif
-#ifdef DEBUG
-                          " +debug"
-#endif
-    ;
-
-const char *const ssl_cipherName[] = {
-    "unknown",
-    "RC4",
-    "RC4-Export",
-    "RC2-CBC",
-    "RC2-CBC-Export",
-    "IDEA-CBC",
-    "DES-CBC",
-    "DES-EDE3-CBC",
-    "unknown",
-    "unknown", /* was fortezza, NO LONGER USED */
-};
-
-/* bit-masks, showing which SSLv2 suites are allowed.
- * lsb corresponds to first cipher suite in allCipherSuites[].
- */
-static PRUint16 allowedByPolicy;         /* all off by default */
-static PRUint16 maybeAllowedByPolicy;    /* all off by default */
-static PRUint16 chosenPreference = 0xff; /* all on  by default */
-
-/* bit values for the above two bit masks */
-#define SSL_CB_RC4_128_WITH_MD5 (1 << SSL_CK_RC4_128_WITH_MD5)
-#define SSL_CB_RC4_128_EXPORT40_WITH_MD5 (1 << SSL_CK_RC4_128_EXPORT40_WITH_MD5)
-#define SSL_CB_RC2_128_CBC_WITH_MD5 (1 << SSL_CK_RC2_128_CBC_WITH_MD5)
-#define SSL_CB_RC2_128_CBC_EXPORT40_WITH_MD5 (1 << SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5)
-#define SSL_CB_IDEA_128_CBC_WITH_MD5 (1 << SSL_CK_IDEA_128_CBC_WITH_MD5)
-#define SSL_CB_DES_64_CBC_WITH_MD5 (1 << SSL_CK_DES_64_CBC_WITH_MD5)
-#define SSL_CB_DES_192_EDE3_CBC_WITH_MD5 (1 << SSL_CK_DES_192_EDE3_CBC_WITH_MD5)
-#define SSL_CB_IMPLEMENTED                  \
-    (SSL_CB_RC4_128_WITH_MD5 |              \
-     SSL_CB_RC4_128_EXPORT40_WITH_MD5 |     \
-     SSL_CB_RC2_128_CBC_WITH_MD5 |          \
-     SSL_CB_RC2_128_CBC_EXPORT40_WITH_MD5 | \
-     SSL_CB_DES_64_CBC_WITH_MD5 |           \
-     SSL_CB_DES_192_EDE3_CBC_WITH_MD5)
-
-/* Construct a socket's list of cipher specs from the global default values.
- */
-static SECStatus
-ssl2_ConstructCipherSpecs(sslSocket *ss)
-{
-    PRUint8 *cs = NULL;
-    unsigned int allowed;
-    unsigned int count;
-    int ssl3_count = 0;
-    int final_count;
-    int i;
-    SECStatus rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    count = 0;
-    PORT_Assert(ss != 0);
-    allowed = !ss->opt.enableSSL2 ? 0 : (ss->allowedByPolicy &
-                                         ss->chosenPreference & SSL_CB_IMPLEMENTED);
-    while (allowed) {
-        if (allowed & 1)
-            ++count;
-        allowed >>= 1;
-    }
-
-    /* Call ssl3_config_match_init() once here,
-     * instead of inside ssl3_ConstructV2CipherSpecsHack(),
-     * because the latter gets called twice below,
-     * and then again in ssl2_BeginClientHandshake().
-     */
-    ssl3_config_match_init(ss);
-
-    /* ask SSL3 how many cipher suites it has. */
-    rv = ssl3_ConstructV2CipherSpecsHack(ss, NULL, &ssl3_count);
-    if (rv < 0)
-        return rv;
-    count += ssl3_count;
-
-    /* Allocate memory to hold cipher specs */
-    if (count > 0)
-        cs = (PRUint8 *)PORT_Alloc(count * 3);
-    else
-        PORT_SetError(SSL_ERROR_SSL_DISABLED);
-    if (cs == NULL)
-        return SECFailure;
-
-    if (ss->cipherSpecs != NULL) {
-        PORT_Free(ss->cipherSpecs);
-    }
-    ss->cipherSpecs = cs;
-    ss->sizeCipherSpecs = count * 3;
-
-    /* fill in cipher specs for SSL2 cipher suites */
-    allowed = !ss->opt.enableSSL2 ? 0 : (ss->allowedByPolicy &
-                                         ss->chosenPreference & SSL_CB_IMPLEMENTED);
-    for (i = 0; i < ssl2_NUM_SUITES_IMPLEMENTED * 3; i += 3) {
-        const PRUint8 *hs = implementedCipherSuites + i;
-        int ok = allowed & (1U << hs[0]);
-        if (ok) {
-            cs[0] = hs[0];
-            cs[1] = hs[1];
-            cs[2] = hs[2];
-            cs += 3;
-        }
-    }
-
-    /* now have SSL3 add its suites onto the end */
-    rv = ssl3_ConstructV2CipherSpecsHack(ss, cs, &final_count);
-
-    /* adjust for any difference between first pass and second pass */
-    ss->sizeCipherSpecs -= (ssl3_count - final_count) * 3;
-
-    return rv;
-}
-
-/* This function is called immediately after ssl2_ConstructCipherSpecs()
-** at the beginning of a handshake.  It detects cases where a protocol
-** (e.g. SSL2 or SSL3) is logically enabled, but all its cipher suites
-** for that protocol have been disabled.  If such cases, it clears the
-** enable bit for the protocol.  If no protocols remain enabled, or
-** if no cipher suites are found, it sets the error code and returns
-** SECFailure, otherwise it returns SECSuccess.
-*/
-static SECStatus
-ssl2_CheckConfigSanity(sslSocket *ss)
-{
-    unsigned int allowed;
-    int ssl3CipherCount = 0;
-    SECStatus rv;
-
-    /* count the SSL2 and SSL3 enabled ciphers.
-     * if either is zero, clear the socket's enable for that protocol.
-     */
-    if (!ss->cipherSpecs)
-        goto disabled;
-
-    allowed = ss->allowedByPolicy & ss->chosenPreference;
-    if (!allowed)
-        ss->opt.enableSSL2 = PR_FALSE; /* not really enabled if no ciphers */
-
-    /* ssl3_config_match_init was called in ssl2_ConstructCipherSpecs(). */
-    /* Ask how many ssl3 CipherSuites were enabled. */
-    rv = ssl3_ConstructV2CipherSpecsHack(ss, NULL, &ssl3CipherCount);
-    if (rv != SECSuccess || ssl3CipherCount <= 0) {
-        /* SSL3/TLS not really enabled if no ciphers */
-        ss->vrange.min = SSL_LIBRARY_VERSION_NONE;
-        ss->vrange.max = SSL_LIBRARY_VERSION_NONE;
-    }
-
-    if (!ss->opt.enableSSL2 && SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
-        SSL_DBG(("%d: SSL[%d]: Can't handshake! all versions disabled.",
-                 SSL_GETPID(), ss->fd));
-    disabled:
-        PORT_SetError(SSL_ERROR_SSL_DISABLED);
-        return SECFailure;
-    }
-    return SECSuccess;
-}
-
-/*
- * Since this is a global (not per-socket) setting, we cannot use the
- * HandshakeLock to protect this.  Probably want a global lock.
- */
-SECStatus
-ssl2_SetPolicy(PRInt32 which, PRInt32 policy)
-{
-    PRUint32 bitMask;
-    SECStatus rv = SECSuccess;
-
-    which &= 0x000f;
-    bitMask = 1 << which;
-
-    if (!(bitMask & SSL_CB_IMPLEMENTED)) {
-        PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
-        return SECFailure;
-    }
-
-    if (policy == SSL_ALLOWED) {
-        allowedByPolicy |= bitMask;
-        maybeAllowedByPolicy |= bitMask;
-    } else if (policy == SSL_RESTRICTED) {
-        allowedByPolicy &= ~bitMask;
-        maybeAllowedByPolicy |= bitMask;
-    } else {
-        allowedByPolicy &= ~bitMask;
-        maybeAllowedByPolicy &= ~bitMask;
-    }
-    allowedByPolicy &= SSL_CB_IMPLEMENTED;
-    maybeAllowedByPolicy &= SSL_CB_IMPLEMENTED;
-
-    policyWasSet = PR_TRUE;
-    return rv;
-}
-
-SECStatus
-ssl2_GetPolicy(PRInt32 which, PRInt32 *oPolicy)
-{
-    PRUint32 bitMask;
-    PRInt32 policy;
-
-    which &= 0x000f;
-    bitMask = 1 << which;
-
-    /* Caller assures oPolicy is not null. */
-    if (!(bitMask & SSL_CB_IMPLEMENTED)) {
-        PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
-        *oPolicy = SSL_NOT_ALLOWED;
-        return SECFailure;
-    }
-
-    if (maybeAllowedByPolicy & bitMask) {
-        policy = (allowedByPolicy & bitMask) ? SSL_ALLOWED : SSL_RESTRICTED;
-    } else {
-        policy = SSL_NOT_ALLOWED;
-    }
-
-    *oPolicy = policy;
-    return SECSuccess;
-}
-
-/*
- * Since this is a global (not per-socket) setting, we cannot use the
- * HandshakeLock to protect this.  Probably want a global lock.
- * Called from SSL_CipherPrefSetDefault in sslsock.c
- * These changes have no effect on any sslSockets already created.
- */
-SECStatus
-ssl2_CipherPrefSetDefault(PRInt32 which, PRBool enabled)
-{
-    PRUint32 bitMask;
-
-    which &= 0x000f;
-    bitMask = 1 << which;
-
-    if (!(bitMask & SSL_CB_IMPLEMENTED)) {
-        PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
-        return SECFailure;
-    }
-
-    if (enabled)
-        chosenPreference |= bitMask;
-    else
-        chosenPreference &= ~bitMask;
-    chosenPreference &= SSL_CB_IMPLEMENTED;
-
-    return SECSuccess;
-}
-
-SECStatus
-ssl2_CipherPrefGetDefault(PRInt32 which, PRBool *enabled)
-{
-    PRBool rv = PR_FALSE;
-    PRUint32 bitMask;
-
-    which &= 0x000f;
-    bitMask = 1 << which;
-
-    if (!(bitMask & SSL_CB_IMPLEMENTED)) {
-        PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
-        *enabled = PR_FALSE;
-        return SECFailure;
-    }
-
-    rv = (PRBool)((chosenPreference & bitMask) != 0);
-    *enabled = rv;
-    return SECSuccess;
-}
-
-SECStatus
-ssl2_CipherPrefSet(sslSocket *ss, PRInt32 which, PRBool enabled)
-{
-    PRUint32 bitMask;
-
-    which &= 0x000f;
-    bitMask = 1 << which;
-
-    if (!(bitMask & SSL_CB_IMPLEMENTED)) {
-        PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
-        return SECFailure;
-    }
-
-    if (enabled)
-        ss->chosenPreference |= bitMask;
-    else
-        ss->chosenPreference &= ~bitMask;
-    ss->chosenPreference &= SSL_CB_IMPLEMENTED;
-
-    return SECSuccess;
-}
-
-SECStatus
-ssl2_CipherPrefGet(sslSocket *ss, PRInt32 which, PRBool *enabled)
-{
-    PRBool rv = PR_FALSE;
-    PRUint32 bitMask;
-
-    which &= 0x000f;
-    bitMask = 1 << which;
-
-    if (!(bitMask & SSL_CB_IMPLEMENTED)) {
-        PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
-        *enabled = PR_FALSE;
-        return SECFailure;
-    }
-
-    rv = (PRBool)((ss->chosenPreference & bitMask) != 0);
-    *enabled = rv;
-    return SECSuccess;
-}
-
-/* copy global default policy into socket. */
-void
-ssl2_InitSocketPolicy(sslSocket *ss)
-{
-    ss->allowedByPolicy = allowedByPolicy;
-    ss->maybeAllowedByPolicy = maybeAllowedByPolicy;
-    ss->chosenPreference = chosenPreference;
-}
-
-/************************************************************************/
-
-/* Called from ssl2_CreateSessionCypher(), which already holds handshake lock.
- */
-static SECStatus
-ssl2_CreateMAC(sslSecurityInfo *sec, SECItem *readKey, SECItem *writeKey,
-               int cipherChoice)
-{
-    switch (cipherChoice) {
-        case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:
-        case SSL_CK_RC2_128_CBC_WITH_MD5:
-        case SSL_CK_RC4_128_EXPORT40_WITH_MD5:
-        case SSL_CK_RC4_128_WITH_MD5:
-        case SSL_CK_DES_64_CBC_WITH_MD5:
-        case SSL_CK_DES_192_EDE3_CBC_WITH_MD5:
-            sec->hash = HASH_GetHashObject(HASH_AlgMD5);
-            if (SECITEM_CopyItem(0, &sec->sendSecret, writeKey) ||
-                SECITEM_CopyItem(0, &sec->rcvSecret, readKey)) {
-                return SECFailure;
-            }
-            break;
-
-        default:
-            PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
-            return SECFailure;
-    }
-    sec->hashcx = (*sec->hash->create)();
-    if (sec->hashcx == NULL)
-        return SECFailure;
-    return SECSuccess;
-}
-
-/************************************************************************
- * All the Send functions below must acquire and release the socket's
- * xmitBufLock.
- */
-
-/* Called from all the Send* functions below. */
-static SECStatus
-ssl2_GetSendBuffer(sslSocket *ss, unsigned int len)
-{
-    SECStatus rv = SECSuccess;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    if (len < 128) {
-        len = 128;
-    }
-    if (len > ss->sec.ci.sendBuf.space) {
-        rv = sslBuffer_Grow(&ss->sec.ci.sendBuf, len);
-        if (rv != SECSuccess) {
-            SSL_DBG(("%d: SSL[%d]: ssl2_GetSendBuffer failed, tried to get %d bytes",
-                     SSL_GETPID(), ss->fd, len));
-            rv = SECFailure;
-        }
-    }
-    return rv;
-}
-
-/* Called from:
- * ssl2_ClientSetupSessionCypher()  <- ssl2_HandleServerHelloMessage()
- * ssl2_HandleRequestCertificate()  <- ssl2_HandleMessage()
-                                    <- ssl_Do1stHandshake()
- * ssl2_HandleMessage()             <- ssl_Do1stHandshake()
- * ssl2_HandleServerHelloMessage()  <- ssl_Do1stHandshake()
-                                    after ssl2_BeginClientHandshake()
- * ssl2_HandleClientHelloMessage()  <- ssl_Do1stHandshake()
-                                    after ssl2_BeginServerHandshake()
- *
- * Acquires and releases the socket's xmitBufLock.
- */
-int
-ssl2_SendErrorMessage(sslSocket *ss, int error)
-{
-    int rv;
-    PRUint8 msg[SSL_HL_ERROR_HBYTES];
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    msg[0] = SSL_MT_ERROR;
-    msg[1] = MSB(error);
-    msg[2] = LSB(error);
-
-    ssl_GetXmitBufLock(ss); /***************************************/
-
-    SSL_TRC(3, ("%d: SSL[%d]: sending error %d", SSL_GETPID(), ss->fd, error));
-
-    ss->handshakeBegun = 1;
-    rv = (*ss->sec.send)(ss, msg, sizeof(msg), 0);
-    if (rv >= 0) {
-        rv = SECSuccess;
-    }
-    ssl_ReleaseXmitBufLock(ss); /***************************************/
-    return rv;
-}
-
-/* Called from ssl2_TryToFinish().
- * Acquires and releases the socket's xmitBufLock.
- */
-static SECStatus
-ssl2_SendClientFinishedMessage(sslSocket *ss)
-{
-    SECStatus rv = SECSuccess;
-    int sent;
-    PRUint8 msg[1 + SSL_CONNECTIONID_BYTES];
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    ssl_GetXmitBufLock(ss); /***************************************/
-
-    if (ss->sec.ci.sentFinished == 0) {
-        ss->sec.ci.sentFinished = 1;
-
-        SSL_TRC(3, ("%d: SSL[%d]: sending client-finished",
-                    SSL_GETPID(), ss->fd));
-
-        msg[0] = SSL_MT_CLIENT_FINISHED;
-        PORT_Memcpy(msg + 1, ss->sec.ci.connectionID,
-                    sizeof(ss->sec.ci.connectionID));
-
-        DUMP_MSG(29, (ss, msg, 1 + sizeof(ss->sec.ci.connectionID)));
-        sent = (*ss->sec.send)(ss, msg, 1 + sizeof(ss->sec.ci.connectionID), 0);
-        rv = (sent >= 0) ? SECSuccess : (SECStatus)sent;
-    }
-    ssl_ReleaseXmitBufLock(ss); /***************************************/
-    return rv;
-}
-
-/* Called from
- * ssl2_HandleClientSessionKeyMessage() <- ssl2_HandleClientHelloMessage()
- * ssl2_HandleClientHelloMessage()      <- ssl_Do1stHandshake()
-                                        after ssl2_BeginServerHandshake()
- * Acquires and releases the socket's xmitBufLock.
- */
-static SECStatus
-ssl2_SendServerVerifyMessage(sslSocket *ss)
-{
-    PRUint8 *msg;
-    int sendLen;
-    int sent;
-    SECStatus rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    ssl_GetXmitBufLock(ss); /***************************************/
-
-    sendLen = 1 + SSL_CHALLENGE_BYTES;
-    rv = ssl2_GetSendBuffer(ss, sendLen);
-    if (rv != SECSuccess) {
-        goto done;
-    }
-
-    msg = ss->sec.ci.sendBuf.buf;
-    msg[0] = SSL_MT_SERVER_VERIFY;
-    PORT_Memcpy(msg + 1, ss->sec.ci.clientChallenge, SSL_CHALLENGE_BYTES);
-
-    DUMP_MSG(29, (ss, msg, sendLen));
-    sent = (*ss->sec.send)(ss, msg, sendLen, 0);
-
-    rv = (sent >= 0) ? SECSuccess : (SECStatus)sent;
-
-done:
-    ssl_ReleaseXmitBufLock(ss); /***************************************/
-    return rv;
-}
-
-/* Called from ssl2_TryToFinish().
- * Acquires and releases the socket's xmitBufLock.
- */
-static SECStatus
-ssl2_SendServerFinishedMessage(sslSocket *ss)
-{
-    sslSessionID *sid;
-    PRUint8 *msg;
-    int sendLen, sent;
-    SECStatus rv = SECSuccess;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    ssl_GetXmitBufLock(ss); /***************************************/
-
-    if (ss->sec.ci.sentFinished == 0) {
-        ss->sec.ci.sentFinished = 1;
-        PORT_Assert(ss->sec.ci.sid != 0);
-        sid = ss->sec.ci.sid;
-
-        SSL_TRC(3, ("%d: SSL[%d]: sending server-finished",
-                    SSL_GETPID(), ss->fd));
-
-        sendLen = 1 + sizeof(sid->u.ssl2.sessionID);
-        rv = ssl2_GetSendBuffer(ss, sendLen);
-        if (rv != SECSuccess) {
-            goto done;
-        }
-
-        msg = ss->sec.ci.sendBuf.buf;
-        msg[0] = SSL_MT_SERVER_FINISHED;
-        PORT_Memcpy(msg + 1, sid->u.ssl2.sessionID,
-                    sizeof(sid->u.ssl2.sessionID));
-
-        DUMP_MSG(29, (ss, msg, sendLen));
-        sent = (*ss->sec.send)(ss, msg, sendLen, 0);
-
-        if (sent < 0) {
-            /* If send failed, it is now a bogus  session-id */
-            if (ss->sec.uncache)
-                (*ss->sec.uncache)(sid);
-            rv = (SECStatus)sent;
-        } else if (!ss->opt.noCache) {
-            if (sid->cached == never_cached) {
-                (*ss->sec.cache)(sid);
-            }
-            rv = SECSuccess;
-        }
-        ssl_FreeSID(sid);
-        ss->sec.ci.sid = 0;
-    }
-done:
-    ssl_ReleaseXmitBufLock(ss); /***************************************/
-    return rv;
-}
-
-/* Called from ssl2_ClientSetupSessionCypher() <- ssl2_HandleServerHelloMessage()
- *                                             after ssl2_BeginClientHandshake()
- * Acquires and releases the socket's xmitBufLock.
- */
-static SECStatus
-ssl2_SendSessionKeyMessage(sslSocket *ss, int cipher, int keySize,
-                           PRUint8 *ca, int caLen,
-                           PRUint8 *ck, int ckLen,
-                           PRUint8 *ek, int ekLen)
-{
-    PRUint8 *msg;
-    int sendLen;
-    int sent;
-    SECStatus rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    ssl_GetXmitBufLock(ss); /***************************************/
-
-    sendLen = SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen + ekLen + caLen;
-    rv = ssl2_GetSendBuffer(ss, sendLen);
-    if (rv != SECSuccess)
-        goto done;
-
-    SSL_TRC(3, ("%d: SSL[%d]: sending client-session-key",
-                SSL_GETPID(), ss->fd));
-
-    msg = ss->sec.ci.sendBuf.buf;
-    msg[0] = SSL_MT_CLIENT_MASTER_KEY;
-    msg[1] = cipher;
-    msg[2] = MSB(keySize);
-    msg[3] = LSB(keySize);
-    msg[4] = MSB(ckLen);
-    msg[5] = LSB(ckLen);
-    msg[6] = MSB(ekLen);
-    msg[7] = LSB(ekLen);
-    msg[8] = MSB(caLen);
-    msg[9] = LSB(caLen);
-    PORT_Memcpy(msg + SSL_HL_CLIENT_MASTER_KEY_HBYTES, ck, ckLen);
-    PORT_Memcpy(msg + SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen, ek, ekLen);
-    PORT_Memcpy(msg + SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen + ekLen, ca, caLen);
-
-    DUMP_MSG(29, (ss, msg, sendLen));
-    sent = (*ss->sec.send)(ss, msg, sendLen, 0);
-    rv = (sent >= 0) ? SECSuccess : (SECStatus)sent;
-done:
-    ssl_ReleaseXmitBufLock(ss); /***************************************/
-    return rv;
-}
-
-/* Called from ssl2_TriggerNextMessage() <- ssl2_HandleMessage()
- * Acquires and releases the socket's xmitBufLock.
- */
-static SECStatus
-ssl2_SendCertificateRequestMessage(sslSocket *ss)
-{
-    PRUint8 *msg;
-    int sent;
-    int sendLen;
-    SECStatus rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    ssl_GetXmitBufLock(ss); /***************************************/
-
-    sendLen = SSL_HL_REQUEST_CERTIFICATE_HBYTES + SSL_CHALLENGE_BYTES;
-    rv = ssl2_GetSendBuffer(ss, sendLen);
-    if (rv != SECSuccess)
-        goto done;
-
-    SSL_TRC(3, ("%d: SSL[%d]: sending certificate request",
-                SSL_GETPID(), ss->fd));
-
-    /* Generate random challenge for client to encrypt */
-    PK11_GenerateRandom(ss->sec.ci.serverChallenge, SSL_CHALLENGE_BYTES);
-
-    msg = ss->sec.ci.sendBuf.buf;
-    msg[0] = SSL_MT_REQUEST_CERTIFICATE;
-    msg[1] = SSL_AT_MD5_WITH_RSA_ENCRYPTION;
-    PORT_Memcpy(msg + SSL_HL_REQUEST_CERTIFICATE_HBYTES,
-                ss->sec.ci.serverChallenge, SSL_CHALLENGE_BYTES);
-
-    DUMP_MSG(29, (ss, msg, sendLen));
-    sent = (*ss->sec.send)(ss, msg, sendLen, 0);
-    rv = (sent >= 0) ? SECSuccess : (SECStatus)sent;
-done:
-    ssl_ReleaseXmitBufLock(ss); /***************************************/
-    return rv;
-}
-
-/* Called from ssl2_HandleRequestCertificate() <- ssl2_HandleMessage()
- * Acquires and releases the socket's xmitBufLock.
- */
-static int
-ssl2_SendCertificateResponseMessage(sslSocket *ss, SECItem *cert,
-                                    SECItem *encCode)
-{
-    PRUint8 *msg;
-    int rv, sendLen;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    ssl_GetXmitBufLock(ss); /***************************************/
-
-    sendLen = SSL_HL_CLIENT_CERTIFICATE_HBYTES + encCode->len + cert->len;
-    rv = ssl2_GetSendBuffer(ss, sendLen);
-    if (rv)
-        goto done;
-
-    SSL_TRC(3, ("%d: SSL[%d]: sending certificate response",
-                SSL_GETPID(), ss->fd));
-
-    msg = ss->sec.ci.sendBuf.buf;
-    msg[0] = SSL_MT_CLIENT_CERTIFICATE;
-    msg[1] = SSL_CT_X509_CERTIFICATE;
-    msg[2] = MSB(cert->len);
-    msg[3] = LSB(cert->len);
-    msg[4] = MSB(encCode->len);
-    msg[5] = LSB(encCode->len);
-    PORT_Memcpy(msg + SSL_HL_CLIENT_CERTIFICATE_HBYTES, cert->data, cert->len);
-    PORT_Memcpy(msg + SSL_HL_CLIENT_CERTIFICATE_HBYTES + cert->len,
-                encCode->data, encCode->len);
-
-    DUMP_MSG(29, (ss, msg, sendLen));
-    rv = (*ss->sec.send)(ss, msg, sendLen, 0);
-    if (rv >= 0) {
-        rv = SECSuccess;
-    }
-done:
-    ssl_ReleaseXmitBufLock(ss); /***************************************/
-    return rv;
-}
-
-/********************************************************************
-**  Send functions above this line must aquire & release the socket's
-**  xmitBufLock.
-** All the ssl2_Send functions below this line are called vis ss->sec.send
-**  and require that the caller hold the xmitBufLock.
-*/
-
-/*
-** Called from ssl2_SendStream, ssl2_SendBlock, but not from ssl2_SendClear.
-*/
-static SECStatus
-ssl2_CalcMAC(PRUint8 *result,
-             sslSecurityInfo *sec,
-             const PRUint8 *data,
-             unsigned int dataLen,
-             unsigned int paddingLen)
-{
-    const PRUint8 *secret = sec->sendSecret.data;
-    unsigned int secretLen = sec->sendSecret.len;
-    unsigned long sequenceNumber = sec->sendSequence;
-    unsigned int nout;
-    PRUint8 seq[4];
-    PRUint8 padding[32]; /* XXX max blocksize? */
-
-    if (!sec->hash || !sec->hash->length)
-        return SECSuccess;
-    if (!sec->hashcx)
-        return SECFailure;
-
-    /* Reset hash function */
-    (*sec->hash->begin)(sec->hashcx);
-
-    /* Feed hash the data */
-    (*sec->hash->update)(sec->hashcx, secret, secretLen);
-    (*sec->hash->update)(sec->hashcx, data, dataLen);
-    PORT_Memset(padding, paddingLen, paddingLen);
-    (*sec->hash->update)(sec->hashcx, padding, paddingLen);
-
-    seq[0] = (PRUint8)(sequenceNumber >> 24);
-    seq[1] = (PRUint8)(sequenceNumber >> 16);
-    seq[2] = (PRUint8)(sequenceNumber >> 8);
-    seq[3] = (PRUint8)(sequenceNumber);
-
-    PRINT_BUF(60, (0, "calc-mac secret:", secret, secretLen));
-    PRINT_BUF(60, (0, "calc-mac data:", data, dataLen));
-    PRINT_BUF(60, (0, "calc-mac padding:", padding, paddingLen));
-    PRINT_BUF(60, (0, "calc-mac seq:", seq, 4));
-
-    (*sec->hash->update)(sec->hashcx, seq, 4);
-
-    /* Get result */
-    (*sec->hash->end)(sec->hashcx, result, &nout, sec->hash->length);
-
-    return SECSuccess;
-}
-
-/*
-** Maximum transmission amounts. These are tiny bit smaller than they
-** need to be (they account for the MAC length plus some padding),
-** assuming the MAC is 16 bytes long and the padding is a max of 7 bytes
-** long. This gives an additional 9 bytes of slop to work within.
-*/
-#define MAX_STREAM_CYPHER_LEN 0x7fe0
-#define MAX_BLOCK_CYPHER_LEN 0x3fe0
-
-/*
-** Send some data in the clear.
-** Package up data with the length header and send it.
-**
-** Return count of bytes successfully written, or negative number (failure).
-*/
-static PRInt32
-ssl2_SendClear(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags)
-{
-    PRUint8 *out;
-    int rv;
-    unsigned int amount;
-    int count = 0;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes in the clear",
-                 SSL_GETPID(), ss->fd, len));
-    PRINT_BUF(50, (ss, "clear data:", (PRUint8 *)in, len));
-
-    while (len) {
-        amount = PR_MIN(len, MAX_STREAM_CYPHER_LEN);
-        if (amount + 2 > ss->sec.writeBuf.space) {
-            rv = sslBuffer_Grow(&ss->sec.writeBuf, amount + 2);
-            if (rv != SECSuccess) {
-                count = rv;
-                break;
-            }
-        }
-        out = ss->sec.writeBuf.buf;
-
-        /*
-        ** Construct message.
-        */
-        out[0] = 0x80 | MSB(amount);
-        out[1] = LSB(amount);
-        PORT_Memcpy(&out[2], in, amount);
-
-        /* Now send the data */
-        rv = ssl_DefSend(ss, out, amount + 2, flags & ~ssl_SEND_FLAG_MASK);
-        if (rv < 0) {
-            if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) {
-                rv = 0;
-            } else {
-                /* Return short write if some data already went out... */
-                if (count == 0)
-                    count = rv;
-                break;
-            }
-        }
-
-        if ((unsigned)rv < (amount + 2)) {
-            /* Short write.  Save the data and return. */
-            if (ssl_SaveWriteData(ss, out + rv, amount + 2 - rv) ==
-                SECFailure) {
-                count = SECFailure;
-            } else {
-                count += amount;
-                ss->sec.sendSequence++;
-            }
-            break;
-        }
-
-        ss->sec.sendSequence++;
-        in += amount;
-        count += amount;
-        len -= amount;
-    }
-
-    return count;
-}
-
-/*
-** Send some data, when using a stream cipher. Stream ciphers have a
-** block size of 1. Package up the data with the length header
-** and send it.
-*/
-static PRInt32
-ssl2_SendStream(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags)
-{
-    PRUint8 *out;
-    int rv;
-    int count = 0;
-
-    int amount;
-    PRUint8 macLen;
-    int nout;
-    unsigned int buflen;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes using stream cipher",
-                 SSL_GETPID(), ss->fd, len));
-    PRINT_BUF(50, (ss, "clear data:", (PRUint8 *)in, len));
-
-    while (len) {
-        ssl_GetSpecReadLock(ss); /*************************************/
-
-        macLen = ss->sec.hash->length;
-        amount = PR_MIN(len, MAX_STREAM_CYPHER_LEN);
-        buflen = amount + 2 + macLen;
-        if (buflen > ss->sec.writeBuf.space) {
-            rv = sslBuffer_Grow(&ss->sec.writeBuf, buflen);
-            if (rv != SECSuccess) {
-                goto loser;
-            }
-        }
-        out = ss->sec.writeBuf.buf;
-        nout = amount + macLen;
-        out[0] = 0x80 | MSB(nout);
-        out[1] = LSB(nout);
-
-        /* Calculate MAC */
-        rv = ssl2_CalcMAC(out + 2, /* put MAC here */
-                          &ss->sec,
-                          in, amount, /* input addr & length */
-                          0);         /* no padding */
-        if (rv != SECSuccess)
-            goto loser;
-
-        /* Encrypt MAC */
-        rv = (*ss->sec.enc)(ss->sec.writecx, out + 2, &nout, macLen, out + 2, macLen);
-        if (rv)
-            goto loser;
-
-        /* Encrypt data from caller */
-        rv = (*ss->sec.enc)(ss->sec.writecx, out + 2 + macLen, &nout, amount, in, amount);
-        if (rv)
-            goto loser;
-
-        ssl_ReleaseSpecReadLock(ss); /*************************************/
-
-        PRINT_BUF(50, (ss, "encrypted data:", out, buflen));
-
-        rv = ssl_DefSend(ss, out, buflen, flags & ~ssl_SEND_FLAG_MASK);
-        if (rv < 0) {
-            if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) {
-                SSL_TRC(50, ("%d: SSL[%d]: send stream would block, "
-                             "saving data",
-                             SSL_GETPID(), ss->fd));
-                rv = 0;
-            } else {
-                SSL_TRC(10, ("%d: SSL[%d]: send stream error %d",
-                             SSL_GETPID(), ss->fd, PORT_GetError()));
-                /* Return short write if some data already went out... */
-                if (count == 0)
-                    count = rv;
-                goto done;
-            }
-        }
-
-        if ((unsigned)rv < buflen) {
-            /* Short write.  Save the data and return. */
-            if (ssl_SaveWriteData(ss, out + rv, buflen - rv) == SECFailure) {
-                count = SECFailure;
-            } else {
-                count += amount;
-                ss->sec.sendSequence++;
-            }
-            goto done;
-        }
-
-        ss->sec.sendSequence++;
-        in += amount;
-        count += amount;
-        len -= amount;
-    }
-
-done:
-    return count;
-
-loser:
-    ssl_ReleaseSpecReadLock(ss);
-    return SECFailure;
-}
-
-/*
-** Send some data, when using a block cipher. Package up the data with
-** the length header and send it.
-*/
-/* XXX assumes blocksize is > 7 */
-static PRInt32
-ssl2_SendBlock(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags)
-{
-    PRUint8 *out;  /* begining of output buffer.    */
-    PRUint8 *op;   /* next output byte goes here.   */
-    int rv;        /* value from funcs we called.   */
-    int count = 0; /* this function's return value. */
-
-    unsigned int hlen;    /* output record hdr len, 2 or 3 */
-    unsigned int macLen;  /* MAC is this many bytes long.  */
-    int amount;           /* of plaintext to go in record. */
-    unsigned int padding; /* add this many padding byte.   */
-    int nout;             /* ciphertext size after header. */
-    unsigned int buflen;  /* size of generated record.     */
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes using block cipher",
-                 SSL_GETPID(), ss->fd, len));
-    PRINT_BUF(50, (ss, "clear data:", in, len));
-
-    while (len) {
-        ssl_GetSpecReadLock(ss); /*************************************/
-
-        macLen = ss->sec.hash->length;
-        /* Figure out how much to send, including mac and padding */
-        amount = PR_MIN(len, MAX_BLOCK_CYPHER_LEN);
-        nout = amount + macLen;
-        padding = nout & (ss->sec.blockSize - 1);
-        if (padding) {
-            hlen = 3;
-            padding = ss->sec.blockSize - padding;
-            nout += padding;
-        } else {
-            hlen = 2;
-        }
-        buflen = hlen + nout;
-        if (buflen > ss->sec.writeBuf.space) {
-            rv = sslBuffer_Grow(&ss->sec.writeBuf, buflen);
-            if (rv != SECSuccess) {
-                goto loser;
-            }
-        }
-        out = ss->sec.writeBuf.buf;
-
-        /* Construct header */
-        op = out;
-        if (padding) {
-            *op++ = MSB(nout);
-            *op++ = LSB(nout);
-            *op++ = padding;
-        } else {
-            *op++ = 0x80 | MSB(nout);
-            *op++ = LSB(nout);
-        }
-
-        /* Calculate MAC */
-        rv = ssl2_CalcMAC(op, /* MAC goes here. */
-                          &ss->sec,
-                          in, amount, /* intput addr, len */
-                          padding);
-        if (rv != SECSuccess)
-            goto loser;
-        op += macLen;
-
-        /* Copy in the input data */
-        /* XXX could eliminate the copy by folding it into the encryption */
-        PORT_Memcpy(op, in, amount);
-        op += amount;
-        if (padding) {
-            PORT_Memset(op, padding, padding);
-            op += padding;
-        }
-
-        /* Encrypt result */
-        rv = (*ss->sec.enc)(ss->sec.writecx, out + hlen, &nout, buflen - hlen,
-                            out + hlen, op - (out + hlen));
-        if (rv)
-            goto loser;
-
-        ssl_ReleaseSpecReadLock(ss); /*************************************/
-
-        PRINT_BUF(50, (ss, "final xmit data:", out, op - out));
-
-        rv = ssl_DefSend(ss, out, op - out, flags & ~ssl_SEND_FLAG_MASK);
-        if (rv < 0) {
-            if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) {
-                rv = 0;
-            } else {
-                SSL_TRC(10, ("%d: SSL[%d]: send block error %d",
-                             SSL_GETPID(), ss->fd, PORT_GetError()));
-                /* Return short write if some data already went out... */
-                if (count == 0)
-                    count = rv;
-                goto done;
-            }
-        }
-
-        if (rv < (op - out)) {
-            /* Short write.  Save the data and return. */
-            if (ssl_SaveWriteData(ss, out + rv, op - out - rv) == SECFailure) {
-                count = SECFailure;
-            } else {
-                count += amount;
-                ss->sec.sendSequence++;
-            }
-            goto done;
-        }
-
-        ss->sec.sendSequence++;
-        in += amount;
-        count += amount;
-        len -= amount;
-    }
-
-done:
-    return count;
-
-loser:
-    ssl_ReleaseSpecReadLock(ss);
-    return SECFailure;
-}
-
-/*
-** Called from: ssl2_HandleServerHelloMessage,
-**              ssl2_HandleClientSessionKeyMessage,
-**              ssl2_HandleClientHelloMessage,
-**
-*/
-static void
-ssl2_UseEncryptedSendFunc(sslSocket *ss)
-{
-    ssl_GetXmitBufLock(ss);
-    PORT_Assert(ss->sec.hashcx != 0);
-
-    ss->gs.encrypted = 1;
-    ss->sec.send = (ss->sec.blockSize > 1) ? ssl2_SendBlock : ssl2_SendStream;
-    ssl_ReleaseXmitBufLock(ss);
-}
-
-/* Called while initializing socket in ssl_CreateSecurityInfo().
-** This function allows us to keep the name of ssl2_SendClear static.
-*/
-void
-ssl2_UseClearSendFunc(sslSocket *ss)
-{
-    ss->sec.send = ssl2_SendClear;
-}
-
-/************************************************************************
-**          END of Send functions.                          *
-*************************************************************************/
-
-/***********************************************************************
- * For SSL3, this gathers in and handles records/messages until either
- *  the handshake is complete or application data is available.
- *
- * For SSL2, this gathers in only the next SSLV2 record.
- *
- * Called from ssl_Do1stHandshake() via function pointer ss->handshake.
- * Caller must hold handshake lock.
- * This function acquires and releases the RecvBufLock.
- *
- * returns SECSuccess for success.
- * returns SECWouldBlock when that value is returned by ssl2_GatherRecord() or
- *  ssl3_GatherCompleteHandshake().
- * returns SECFailure on all other errors.
- *
- * The gather functions called by ssl_GatherRecord1stHandshake are expected
- *  to return values interpreted as follows:
- *  1 : the function completed without error.
- *  0 : the function read EOF.
- * -1 : read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error.
- * -2 : the function wants ssl_GatherRecord1stHandshake to be called again
- *  immediately, by ssl_Do1stHandshake.
- *
- * This code is similar to, and easily confused with, DoRecv() in sslsecur.c
- *
- * This function is called from ssl_Do1stHandshake().
- * The following functions put ssl_GatherRecord1stHandshake into ss->handshake:
- *  ssl2_HandleMessage
- *  ssl2_HandleVerifyMessage
- *  ssl2_HandleServerHelloMessage
- *  ssl2_BeginClientHandshake
- *  ssl2_HandleClientSessionKeyMessage
- *  ssl3_RestartHandshakeAfterCertReq
- *  ssl3_RestartHandshakeAfterServerCert
- *  ssl2_HandleClientHelloMessage
- *  ssl2_BeginServerHandshake
- */
-SECStatus
-ssl_GatherRecord1stHandshake(sslSocket *ss)
-{
-    int rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    ssl_GetRecvBufLock(ss);
-
-    /* The special case DTLS logic is needed here because the SSL/TLS
-     * version wants to auto-detect SSL2 vs. SSL3 on the initial handshake
-     * (ss->version == 0) but with DTLS it gets confused, so we force the
-     * SSL3 version.
-     */
-    if ((ss->version >= SSL_LIBRARY_VERSION_3_0) || IS_DTLS(ss)) {
-        /* Wait for handshake to complete, or application data to arrive.  */
-        rv = ssl3_GatherCompleteHandshake(ss, 0);
-    } else {
-        /* See if we have a complete record */
-        rv = ssl2_GatherRecord(ss, 0);
-    }
-    SSL_TRC(10, ("%d: SSL[%d]: handshake gathering, rv=%d",
-                 SSL_GETPID(), ss->fd, rv));
-
-    ssl_ReleaseRecvBufLock(ss);
-
-    if (rv <= 0) {
-        if (rv == SECWouldBlock) {
-            /* Progress is blocked waiting for callback completion.  */
-            SSL_TRC(10, ("%d: SSL[%d]: handshake blocked (need %d)",
-                         SSL_GETPID(), ss->fd, ss->gs.remainder));
-            return SECWouldBlock;
-        }
-        if (rv == 0) {
-            /* EOF. Loser  */
-            PORT_SetError(PR_END_OF_FILE_ERROR);
-        }
-        return SECFailure; /* rv is < 0 here. */
-    }
-
-    SSL_TRC(10, ("%d: SSL[%d]: got handshake record of %d bytes",
-                 SSL_GETPID(), ss->fd, ss->gs.recordLen));
-
-    ss->handshake = 0; /* makes ssl_Do1stHandshake call ss->nextHandshake.*/
-    return SECSuccess;
-}
-
-/************************************************************************/
-
-/* Called from ssl2_ServerSetupSessionCypher()
- *             ssl2_ClientSetupSessionCypher()
- */
-static SECStatus
-ssl2_FillInSID(sslSessionID *sid,
-               int cipher,
-               PRUint8 *keyData,
-               int keyLen,
-               PRUint8 *ca,
-               int caLen,
-               int keyBits,
-               int secretKeyBits,
-               SSLSignType authAlgorithm,
-               PRUint32 authKeyBits,
-               SSLKEAType keaType,
-               PRUint32 keaKeyBits)
-{
-    PORT_Assert(sid->references == 1);
-    PORT_Assert(sid->cached == never_cached);
-    PORT_Assert(sid->u.ssl2.masterKey.data == 0);
-    PORT_Assert(sid->u.ssl2.cipherArg.data == 0);
-
-    sid->version = SSL_LIBRARY_VERSION_2;
-
-    sid->u.ssl2.cipherType = cipher;
-    sid->u.ssl2.masterKey.data = (PRUint8 *)PORT_Alloc(keyLen);
-    if (!sid->u.ssl2.masterKey.data) {
-        return SECFailure;
-    }
-    PORT_Memcpy(sid->u.ssl2.masterKey.data, keyData, keyLen);
-    sid->u.ssl2.masterKey.len = keyLen;
-    sid->u.ssl2.keyBits = keyBits;
-    sid->u.ssl2.secretKeyBits = secretKeyBits;
-    sid->authAlgorithm = authAlgorithm;
-    sid->authKeyBits = authKeyBits;
-    sid->keaType = keaType;
-    sid->keaKeyBits = keaKeyBits;
-    sid->lastAccessTime = sid->creationTime = ssl_Time();
-    sid->expirationTime = sid->creationTime + ssl_sid_timeout;
-
-    if (caLen) {
-        sid->u.ssl2.cipherArg.data = (PRUint8 *)PORT_Alloc(caLen);
-        if (!sid->u.ssl2.cipherArg.data) {
-            return SECFailure;
-        }
-        sid->u.ssl2.cipherArg.len = caLen;
-        PORT_Memcpy(sid->u.ssl2.cipherArg.data, ca, caLen);
-    }
-    return SECSuccess;
-}
-
-/*
-** Construct session keys given the masterKey (tied to the session-id),
-** the client's challenge and the server's nonce.
-**
-** Called from ssl2_CreateSessionCypher() <-
-*/
-static SECStatus
-ssl2_ProduceKeys(sslSocket *ss,
-                 SECItem *readKey,
-                 SECItem *writeKey,
-                 SECItem *masterKey,
-                 PRUint8 *challenge,
-                 PRUint8 *nonce,
-                 int cipherType)
-{
-    PK11Context *cx = 0;
-    unsigned nkm = 0; /* number of hashes to generate key mat. */
-    unsigned nkd = 0; /* size of readKey and writeKey. */
-    unsigned part;
-    unsigned i;
-    unsigned off;
-    SECStatus rv;
-    PRUint8 countChar;
-    PRUint8 km[3 * 16]; /* buffer for key material. */
-
-    readKey->data = 0;
-    writeKey->data = 0;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    rv = SECSuccess;
-    cx = PK11_CreateDigestContext(SEC_OID_MD5);
-    if (cx == NULL) {
-        ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
-        return SECFailure;
-    }
-
-    nkm = ssl_Specs[cipherType].nkm;
-    nkd = ssl_Specs[cipherType].nkd;
-
-    readKey->data = (PRUint8 *)PORT_Alloc(nkd);
-    if (!readKey->data)
-        goto loser;
-    readKey->len = nkd;
-
-    writeKey->data = (PRUint8 *)PORT_Alloc(nkd);
-    if (!writeKey->data)
-        goto loser;
-    writeKey->len = nkd;
-
-    /* Produce key material */
-    countChar = '0';
-    for (i = 0, off = 0; i < nkm; i++, off += 16) {
-        rv = PK11_DigestBegin(cx);
-        rv |= PK11_DigestOp(cx, masterKey->data, masterKey->len);
-        rv |= PK11_DigestOp(cx, &countChar, 1);
-        rv |= PK11_DigestOp(cx, challenge, SSL_CHALLENGE_BYTES);
-        rv |= PK11_DigestOp(cx, nonce, SSL_CONNECTIONID_BYTES);
-        rv |= PK11_DigestFinal(cx, km + off, &part, MD5_LENGTH);
-        if (rv != SECSuccess) {
-            ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
-            rv = SECFailure;
-            goto loser;
-        }
-        countChar++;
-    }
-
-    /* Produce keys */
-    PORT_Memcpy(readKey->data, km, nkd);
-    PORT_Memcpy(writeKey->data, km + nkd, nkd);
-
-loser:
-    PK11_DestroyContext(cx, PR_TRUE);
-    return rv;
-}
-
-/* Called from ssl2_ServerSetupSessionCypher()
-**                  <- ssl2_HandleClientSessionKeyMessage()
-**                          <- ssl2_HandleClientHelloMessage()
-** and from    ssl2_ClientSetupSessionCypher()
-**                  <- ssl2_HandleServerHelloMessage()
-*/
-static SECStatus
-ssl2_CreateSessionCypher(sslSocket *ss, sslSessionID *sid, PRBool isClient)
-{
-    SECItem *rk = NULL;
-    SECItem *wk = NULL;
-    SECItem *param;
-    SECStatus rv;
-    int cipherType = sid->u.ssl2.cipherType;
-    PK11SlotInfo *slot = NULL;
-    CK_MECHANISM_TYPE mechanism;
-    SECItem readKey;
-    SECItem writeKey;
-
-    void *readcx = 0;
-    void *writecx = 0;
-    readKey.data = 0;
-    writeKey.data = 0;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-    if (ss->sec.ci.sid == 0)
-        goto sec_loser; /* don't crash if asserts are off */
-
-    /* Trying to cut down on all these switch statements that should be tables.
-     * So, test cipherType once, here, and then use tables below.
-     */
-    switch (cipherType) {
-        case SSL_CK_RC4_128_EXPORT40_WITH_MD5:
-        case SSL_CK_RC4_128_WITH_MD5:
-        case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:
-        case SSL_CK_RC2_128_CBC_WITH_MD5:
-        case SSL_CK_DES_64_CBC_WITH_MD5:
-        case SSL_CK_DES_192_EDE3_CBC_WITH_MD5:
-            break;
-
-        default:
-            SSL_DBG(("%d: SSL[%d]: ssl2_CreateSessionCypher: unknown cipher=%d",
-                     SSL_GETPID(), ss->fd, cipherType));
-            PORT_SetError(isClient ? SSL_ERROR_BAD_SERVER : SSL_ERROR_BAD_CLIENT);
-            goto sec_loser;
-    }
-
-    rk = isClient ? &readKey : &writeKey;
-    wk = isClient ? &writeKey : &readKey;
-
-    /* Produce the keys for this session */
-    rv = ssl2_ProduceKeys(ss, &readKey, &writeKey, &sid->u.ssl2.masterKey,
-                          ss->sec.ci.clientChallenge, ss->sec.ci.connectionID,
-                          cipherType);
-    if (rv != SECSuccess)
-        goto loser;
-    PRINT_BUF(7, (ss, "Session read-key: ", rk->data, rk->len));
-    PRINT_BUF(7, (ss, "Session write-key: ", wk->data, wk->len));
-
-    PORT_Memcpy(ss->sec.ci.readKey, readKey.data, readKey.len);
-    PORT_Memcpy(ss->sec.ci.writeKey, writeKey.data, writeKey.len);
-    ss->sec.ci.keySize = readKey.len;
-
-    /* Setup the MAC */
-    rv = ssl2_CreateMAC(&ss->sec, rk, wk, cipherType);
-    if (rv != SECSuccess)
-        goto loser;
-
-    /* First create the session key object */
-    SSL_TRC(3, ("%d: SSL[%d]: using %s", SSL_GETPID(), ss->fd,
-                ssl_cipherName[cipherType]));
-
-    mechanism = ssl_Specs[cipherType].mechanism;
-
-    /* set destructer before we call loser... */
-    ss->sec.destroy = (void (*)(void *, PRBool))PK11_DestroyContext;
-    slot = PK11_GetBestSlot(mechanism, ss->pkcs11PinArg);
-    if (slot == NULL)
-        goto loser;
-
-    param = PK11_ParamFromIV(mechanism, &sid->u.ssl2.cipherArg);
-    if (param == NULL)
-        goto loser;
-    readcx = PK11_CreateContextByRawKey(slot, mechanism, PK11_OriginUnwrap,
-                                        CKA_DECRYPT, rk, param,
-                                        ss->pkcs11PinArg);
-    SECITEM_FreeItem(param, PR_TRUE);
-    if (readcx == NULL)
-        goto loser;
-
-    /* build the client context */
-    param = PK11_ParamFromIV(mechanism, &sid->u.ssl2.cipherArg);
-    if (param == NULL)
-        goto loser;
-    writecx = PK11_CreateContextByRawKey(slot, mechanism, PK11_OriginUnwrap,
-                                         CKA_ENCRYPT, wk, param,
-                                         ss->pkcs11PinArg);
-    SECITEM_FreeItem(param, PR_TRUE);
-    if (writecx == NULL)
-        goto loser;
-    PK11_FreeSlot(slot);
-
-    rv = SECSuccess;
-    ss->sec.enc = (SSLCipher)PK11_CipherOp;
-    ss->sec.dec = (SSLCipher)PK11_CipherOp;
-    ss->sec.readcx = (void *)readcx;
-    ss->sec.writecx = (void *)writecx;
-    ss->sec.blockSize = ssl_Specs[cipherType].blockSize;
-    ss->sec.blockShift = ssl_Specs[cipherType].blockShift;
-    ss->sec.cipherType = sid->u.ssl2.cipherType;
-    ss->sec.keyBits = sid->u.ssl2.keyBits;
-    ss->sec.secretKeyBits = sid->u.ssl2.secretKeyBits;
-    goto done;
-
-loser:
-    if (ss->sec.destroy) {
-        if (readcx)
-            (*ss->sec.destroy)(readcx, PR_TRUE);
-        if (writecx)
-            (*ss->sec.destroy)(writecx, PR_TRUE);
-    }
-    ss->sec.destroy = NULL;
-    if (slot)
-        PK11_FreeSlot(slot);
-
-sec_loser:
-    rv = SECFailure;
-
-done:
-    if (rk) {
-        SECITEM_ZfreeItem(rk, PR_FALSE);
-    }
-    if (wk) {
-        SECITEM_ZfreeItem(wk, PR_FALSE);
-    }
-    return rv;
-}
-
-/*
-** Setup the server ciphers given information from a CLIENT-MASTER-KEY
-** message.
-**  "ss"      pointer to the ssl-socket object
-**  "cipher"  the cipher type to use
-**  "keyBits" the size of the final cipher key
-**  "ck"      the clear-key data
-**  "ckLen"   the number of bytes of clear-key data
-**  "ek"      the encrypted-key data
-**  "ekLen"   the number of bytes of encrypted-key data
-**  "ca"      the cipher-arg data
-**  "caLen"   the number of bytes of cipher-arg data
-**
-** The MASTER-KEY is constructed by first decrypting the encrypted-key
-** data. This produces the SECRET-KEY-DATA. The MASTER-KEY is composed by
-** concatenating the clear-key data with the SECRET-KEY-DATA. This code
-** checks to make sure that the client didn't send us an improper amount
-** of SECRET-KEY-DATA (it restricts the length of that data to match the
-** spec).
-**
-** Called from ssl2_HandleClientSessionKeyMessage().
-*/
-static SECStatus
-ssl2_ServerSetupSessionCypher(sslSocket *ss, int cipher, unsigned int keyBits,
-                              PRUint8 *ck, unsigned int ckLen,
-                              PRUint8 *ek, unsigned int ekLen,
-                              PRUint8 *ca, unsigned int caLen)
-{
-    PRUint8 *dk = NULL; /* decrypted master key */
-    sslSessionID *sid;
-    sslServerCerts *sc = ss->serverCerts + kt_rsa;
-    PRUint8 *kbuf = 0;  /* buffer for RSA decrypted data. */
-    unsigned int ddLen; /* length of RSA decrypted data in kbuf */
-    unsigned int keySize;
-    unsigned int dkLen; /* decrypted key length in bytes */
-    int modulusLen;
-    SECStatus rv;
-    PRUint16 allowed; /* cipher kinds enabled and allowed by policy */
-    PRUint8 mkbuf[SSL_MAX_MASTER_KEY_BYTES];
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert((sc->SERVERKEY != 0));
-    PORT_Assert((ss->sec.ci.sid != 0));
-    sid = ss->sec.ci.sid;
-
-    /* Trying to cut down on all these switch statements that should be tables.
-     * So, test cipherType once, here, and then use tables below.
-     */
-    switch (cipher) {
-        case SSL_CK_RC4_128_EXPORT40_WITH_MD5:
-        case SSL_CK_RC4_128_WITH_MD5:
-        case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:
-        case SSL_CK_RC2_128_CBC_WITH_MD5:
-        case SSL_CK_DES_64_CBC_WITH_MD5:
-        case SSL_CK_DES_192_EDE3_CBC_WITH_MD5:
-            break;
-
-        default:
-            SSL_DBG(("%d: SSL[%d]: ssl2_ServerSetupSessionCypher: unknown cipher=%d",
-                     SSL_GETPID(), ss->fd, cipher));
-            PORT_SetError(SSL_ERROR_BAD_CLIENT);
-            goto loser;
-    }
-
-    allowed = ss->allowedByPolicy & ss->chosenPreference & SSL_CB_IMPLEMENTED;
-    if (!(allowed & (1 << cipher))) {
-        /* client chose a kind we don't allow! */
-        SSL_DBG(("%d: SSL[%d]: disallowed cipher=%d",
-                 SSL_GETPID(), ss->fd, cipher));
-        PORT_SetError(SSL_ERROR_BAD_CLIENT);
-        goto loser;
-    }
-
-    keySize = ssl_Specs[cipher].keyLen;
-    if (keyBits != keySize * BPB) {
-        SSL_DBG(("%d: SSL[%d]: invalid master secret key length=%d (bits)!",
-                 SSL_GETPID(), ss->fd, keyBits));
-        PORT_SetError(SSL_ERROR_BAD_CLIENT);
-        goto loser;
-    }
-
-    if (ckLen != ssl_Specs[cipher].pubLen) {
-        SSL_DBG(("%d: SSL[%d]: invalid clear key length, ckLen=%d (bytes)!",
-                 SSL_GETPID(), ss->fd, ckLen));
-        PORT_SetError(SSL_ERROR_BAD_CLIENT);
-        goto loser;
-    }
-
-    if (caLen != ssl_Specs[cipher].ivLen) {
-        SSL_DBG(("%d: SSL[%d]: invalid key args length, caLen=%d (bytes)!",
-                 SSL_GETPID(), ss->fd, caLen));
-        PORT_SetError(SSL_ERROR_BAD_CLIENT);
-        goto loser;
-    }
-
-    modulusLen = PK11_GetPrivateModulusLen(sc->SERVERKEY);
-    if (modulusLen < 0) {
-        /* XXX If the key is bad, then PK11_PubDecryptRaw will fail below. */
-        modulusLen = ekLen;
-    }
-    if (ekLen > (unsigned int)modulusLen || ekLen + ckLen < keySize) {
-        SSL_DBG(("%d: SSL[%d]: invalid encrypted key length, ekLen=%d (bytes)!",
-                 SSL_GETPID(), ss->fd, ekLen));
-        PORT_SetError(SSL_ERROR_BAD_CLIENT);
-        goto loser;
-    }
-
-    /* allocate the buffer to hold the decrypted portion of the key. */
-    kbuf = (PRUint8 *)PORT_Alloc(modulusLen);
-    if (!kbuf) {
-        goto loser;
-    }
-    dkLen = keySize - ckLen;
-    dk = kbuf + modulusLen - dkLen;
-
-    /* Decrypt encrypted half of the key.
-    ** NOTE: PK11_PubDecryptRaw will barf on a non-RSA key. This is
-    ** desired behavior here.
-    */
-    rv = PK11_PubDecryptRaw(sc->SERVERKEY, kbuf, &ddLen, modulusLen, ek, ekLen);
-    if (rv != SECSuccess)
-        goto hide_loser;
-
-    /* Is the length of the decrypted data (ddLen) the expected value? */
-    if (modulusLen != ddLen)
-        goto hide_loser;
-
-    /* Cheaply verify that PKCS#1 was used to format the encryption block */
-    if ((kbuf[0] != 0x00) || (kbuf[1] != 0x02) || (dk[-1] != 0x00)) {
-        SSL_DBG(("%d: SSL[%d]: strange encryption block",
-                 SSL_GETPID(), ss->fd));
-        PORT_SetError(SSL_ERROR_BAD_CLIENT);
-        goto hide_loser;
-    }
-
-    /* Make sure we're not subject to a version rollback attack. */
-    if (!SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
-        static const PRUint8 threes[8] = { 0x03, 0x03, 0x03, 0x03,
-                                           0x03, 0x03, 0x03, 0x03 };
-
-        if (PORT_Memcmp(dk - 8 - 1, threes, 8) == 0) {
-            PORT_SetError(SSL_ERROR_BAD_CLIENT);
-            goto hide_loser;
-        }
-    }
-    if (0) {
-    hide_loser:
-        /* Defense against the Bleichenbacher attack.
-         * Provide the client with NO CLUES that the decrypted master key
-         * was erroneous.  Don't send any error messages.
-         * Instead, Generate a completely bogus master key .
-         */
-        PK11_GenerateRandom(dk, dkLen);
-    }
-
-    /*
-    ** Construct master key out of the pieces.
-    */
-    if (ckLen) {
-        PORT_Memcpy(mkbuf, ck, ckLen);
-    }
-    PORT_Memcpy(mkbuf + ckLen, dk, dkLen);
-
-    /* Fill in session-id */
-    rv = ssl2_FillInSID(sid, cipher, mkbuf, keySize, ca, caLen,
-                        keyBits, keyBits - (ckLen << 3),
-                        ss->sec.authAlgorithm, ss->sec.authKeyBits,
-                        ss->sec.keaType, ss->sec.keaKeyBits);
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-
-    /* Create session ciphers */
-    rv = ssl2_CreateSessionCypher(ss, sid, PR_FALSE);
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-
-    SSL_TRC(1, ("%d: SSL[%d]: server, using %s cipher, clear=%d total=%d",
-                SSL_GETPID(), ss->fd, ssl_cipherName[cipher],
-                ckLen << 3, keySize << 3));
-    rv = SECSuccess;
-    goto done;
-
-loser:
-    rv = SECFailure;
-
-done:
-    PORT_Free(kbuf);
-    return rv;
-}
-
-/************************************************************************/
-
-/*
-** Rewrite the incoming cipher specs, comparing to list of specs we support,
-** (ss->cipherSpecs) and eliminating anything we don't support
-**
-*  Note: Our list may contain SSL v3 ciphers.
-*  We MUST NOT match on any of those.
-*  Fortunately, this is easy to detect because SSLv3 ciphers have zero
-*  in the first byte, and none of the SSLv2 ciphers do.
-*
-*  Called from ssl2_HandleClientHelloMessage().
-*  Returns the number of bytes of "qualified cipher specs",
-*  which is typically a multiple of 3, but will be zero if there are none.
-*/
-static int
-ssl2_QualifyCypherSpecs(sslSocket *ss,
-                        PRUint8 *cs, /* cipher specs in client hello msg. */
-                        int csLen)
-{
-    PRUint8 *ms;
-    PRUint8 *hs;
-    PRUint8 *qs;
-    int mc;
-    int hc;
-    PRUint8 qualifiedSpecs[ssl2_NUM_SUITES_IMPLEMENTED * 3];
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-
-    if (!ss->cipherSpecs) {
-        SECStatus rv = ssl2_ConstructCipherSpecs(ss);
-        if (rv != SECSuccess || !ss->cipherSpecs)
-            return 0;
-    }
-
-    PRINT_BUF(10, (ss, "specs from client:", cs, csLen));
-    qs = qualifiedSpecs;
-    ms = ss->cipherSpecs;
-    for (mc = ss->sizeCipherSpecs; mc > 0; mc -= 3, ms += 3) {
-        if (ms[0] == 0)
-            continue;
-        for (hs = cs, hc = csLen; hc > 0; hs += 3, hc -= 3) {
-            if ((hs[0] == ms[0]) &&
-                (hs[1] == ms[1]) &&
-                (hs[2] == ms[2])) {
-                /* Copy this cipher spec into the "keep" section */
-                qs[0] = hs[0];
-                qs[1] = hs[1];
-                qs[2] = hs[2];
-                qs += 3;
-                break;
-            }
-        }
-    }
-    hc = qs - qualifiedSpecs;
-    PRINT_BUF(10, (ss, "qualified specs from client:", qualifiedSpecs, hc));
-    PORT_Memcpy(cs, qualifiedSpecs, hc);
-    return hc;
-}
-
-/*
-** Pick the best cipher we can find, given the array of server cipher
-** specs.  Returns cipher number (e.g. SSL_CK_*), or -1 for no overlap.
-** If successful, stores the master key size (bytes) in *pKeyLen.
-**
-** This is correct only for the client side, but presently
-** this function is only called from
-**  ssl2_ClientSetupSessionCypher() <- ssl2_HandleServerHelloMessage()
-**
-** Note that most servers only return a single cipher suite in their
-** ServerHello messages.  So, the code below for finding the "best" cipher
-** suite usually has only one choice.  The client and server should send
-** their cipher suite lists sorted in descending order by preference.
-*/
-static int
-ssl2_ChooseSessionCypher(sslSocket *ss,
-                         int hc,       /* number of cs's in hs. */
-                         PRUint8 *hs,  /* server hello's cipher suites. */
-                         int *pKeyLen) /* out: sym key size in bytes. */
-{
-    PRUint8 *ms;
-    unsigned int i;
-    int bestKeySize;
-    int bestRealKeySize;
-    int bestCypher;
-    int keySize;
-    int realKeySize;
-    PRUint8 *ohs = hs;
-    const PRUint8 *preferred;
-    static const PRUint8 noneSuch[3] = { 0, 0, 0 };
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-
-    if (!ss->cipherSpecs) {
-        SECStatus rv = ssl2_ConstructCipherSpecs(ss);
-        if (rv != SECSuccess || !ss->cipherSpecs)
-            goto loser;
-    }
-
-    if (!ss->preferredCipher) {
-        unsigned int allowed = ss->allowedByPolicy & ss->chosenPreference &
-                               SSL_CB_IMPLEMENTED;
-        if (allowed) {
-            preferred = implementedCipherSuites;
-            for (i = ssl2_NUM_SUITES_IMPLEMENTED; i > 0; --i) {
-                if (0 != (allowed & (1U << preferred[0]))) {
-                    ss->preferredCipher = preferred;
-                    break;
-                }
-                preferred += 3;
-            }
-        }
-    }
-    preferred = ss->preferredCipher ? ss->preferredCipher : noneSuch;
-    /*
-    ** Scan list of ciphers received from peer and look for a match in
-    ** our list.
-    *  Note: Our list may contain SSL v3 ciphers.
-    *  We MUST NOT match on any of those.
-    *  Fortunately, this is easy to detect because SSLv3 ciphers have zero
-    *  in the first byte, and none of the SSLv2 ciphers do.
-    */
-    bestKeySize = bestRealKeySize = 0;
-    bestCypher = -1;
-    while (--hc >= 0) {
-        for (i = 0, ms = ss->cipherSpecs; i < ss->sizeCipherSpecs; i += 3, ms += 3) {
-            if ((hs[0] == preferred[0]) &&
-                (hs[1] == preferred[1]) &&
-                (hs[2] == preferred[2]) &&
-                hs[0] != 0) {
-                /* Pick this cipher immediately! */
-                *pKeyLen = (((hs[1] << 8) | hs[2]) + 7) >> 3;
-                return hs[0];
-            }
-            if ((hs[0] == ms[0]) && (hs[1] == ms[1]) && (hs[2] == ms[2]) &&
-                hs[0] != 0) {
-                /* Found a match */
-
-                /* Use secret keySize to determine which cipher is best */
-                realKeySize = (hs[1] << 8) | hs[2];
-                switch (hs[0]) {
-                    case SSL_CK_RC4_128_EXPORT40_WITH_MD5:
-                    case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:
-                        keySize = 40;
-                        break;
-                    default:
-                        keySize = realKeySize;
-                        break;
-                }
-                if (keySize > bestKeySize) {
-                    bestCypher = hs[0];
-                    bestKeySize = keySize;
-                    bestRealKeySize = realKeySize;
-                }
-            }
-        }
-        hs += 3;
-    }
-    if (bestCypher < 0) {
-        /*
-        ** No overlap between server and client. Re-examine server list
-        ** to see what kind of ciphers it does support so that we can set
-        ** the error code appropriately.
-        */
-        if ((ohs[0] == SSL_CK_RC4_128_WITH_MD5) ||
-            (ohs[0] == SSL_CK_RC2_128_CBC_WITH_MD5)) {
-            PORT_SetError(SSL_ERROR_US_ONLY_SERVER);
-        } else if ((ohs[0] == SSL_CK_RC4_128_EXPORT40_WITH_MD5) ||
-                   (ohs[0] == SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5)) {
-            PORT_SetError(SSL_ERROR_EXPORT_ONLY_SERVER);
-        } else {
-            PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
-        }
-        SSL_DBG(("%d: SSL[%d]: no cipher overlap", SSL_GETPID(), ss->fd));
-        goto loser;
-    }
-    *pKeyLen = (bestRealKeySize + 7) >> 3;
-    return bestCypher;
-
-loser:
-    return -1;
-}
-
-static SECStatus
-ssl2_ClientHandleServerCert(sslSocket *ss, PRUint8 *certData, int certLen)
-{
-    CERTCertificate *cert = NULL;
-    SECItem certItem;
-
-    certItem.data = certData;
-    certItem.len = certLen;
-
-    /* decode the certificate */
-    cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL,
-                                   PR_FALSE, PR_TRUE);
-
-    if (cert == NULL) {
-        SSL_DBG(("%d: SSL[%d]: decode of server certificate fails",
-                 SSL_GETPID(), ss->fd));
-        PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
-        return SECFailure;
-    }
-
-#ifdef TRACE
-    {
-        if (ssl_trace >= 1) {
-            char *issuer;
-            char *subject;
-            issuer = CERT_NameToAscii(&cert->issuer);
-            subject = CERT_NameToAscii(&cert->subject);
-            SSL_TRC(1, ("%d: server certificate issuer: '%s'",
-                        SSL_GETPID(), issuer ? issuer : "OOPS"));
-            SSL_TRC(1, ("%d: server name: '%s'",
-                        SSL_GETPID(), subject ? subject : "OOPS"));
-            PORT_Free(issuer);
-            PORT_Free(subject);
-        }
-    }
-#endif
-
-    ss->sec.peerCert = cert;
-    return SECSuccess;
-}
-
-/*
- * Format one block of data for public/private key encryption using
- * the rules defined in PKCS #1. SSL2 does this itself to handle the
- * rollback detection.
- */
-#define RSA_BLOCK_MIN_PAD_LEN 8
-#define RSA_BLOCK_FIRST_OCTET 0x00
-#define RSA_BLOCK_AFTER_PAD_OCTET 0x00
-#define RSA_BLOCK_PUBLIC_OCTET 0x02
-unsigned char *
-ssl_FormatSSL2Block(unsigned modulusLen, SECItem *data)
-{
-    unsigned char *block;
-    unsigned char *bp;
-    int padLen;
-    SECStatus rv;
-    int i;
-
-    if (modulusLen < data->len + (3 + RSA_BLOCK_MIN_PAD_LEN)) {
-        PORT_SetError(SEC_ERROR_BAD_KEY);
-        return NULL;
-    }
-    block = (unsigned char *)PORT_Alloc(modulusLen);
-    if (block == NULL)
-        return NULL;
-
-    bp = block;
-
-    /*
-     * All RSA blocks start with two octets:
-     *  0x00 || BlockType
-     */
-    *bp++ = RSA_BLOCK_FIRST_OCTET;
-    *bp++ = RSA_BLOCK_PUBLIC_OCTET;
-
-    /*
-     * 0x00 || BT || Pad || 0x00 || ActualData
-     *   1      1   padLen    1      data->len
-     * Pad is all non-zero random bytes.
-     */
-    padLen = modulusLen - data->len - 3;
-    PORT_Assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
-    rv = PK11_GenerateRandom(bp, padLen);
-    if (rv == SECFailure)
-        goto loser;
-    /* replace all the 'zero' bytes */
-    for (i = 0; i < padLen; i++) {
-        while (bp[i] == RSA_BLOCK_AFTER_PAD_OCTET) {
-            rv = PK11_GenerateRandom(bp + i, 1);
-            if (rv == SECFailure)
-                goto loser;
-        }
-    }
-    bp += padLen;
-    *bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
-    PORT_Memcpy(bp, data->data, data->len);
-
-    return block;
-loser:
-    if (block)
-        PORT_Free(block);
-    return NULL;
-}
-
-/*
-** Given the server's public key and cipher specs, generate a session key
-** that is ready to use for encrypting/decrypting the byte stream. At
-** the same time, generate the SSL_MT_CLIENT_MASTER_KEY message and
-** send it to the server.
-**
-** Called from ssl2_HandleServerHelloMessage()
-*/
-static SECStatus
-ssl2_ClientSetupSessionCypher(sslSocket *ss, PRUint8 *cs, int csLen)
-{
-    sslSessionID *sid;
-    PRUint8 *ca; /* points to iv data, or NULL if none. */
-    PRUint8 *ekbuf = 0;
-    CERTCertificate *cert = 0;
-    SECKEYPublicKey *serverKey = 0;
-    unsigned modulusLen = 0;
-    SECStatus rv;
-    int cipher;
-    int keyLen; /* cipher symkey size in bytes. */
-    int ckLen;  /* publicly reveal this many bytes of key. */
-    int caLen;  /* length of IV data at *ca.    */
-    int nc;
-
-    unsigned char *eblock; /* holds unencrypted PKCS#1 formatted key. */
-    SECItem rek;           /* holds portion of symkey to be encrypted. */
-
-    PRUint8 keyData[SSL_MAX_MASTER_KEY_BYTES];
-    PRUint8 iv[8];
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    eblock = NULL;
-
-    sid = ss->sec.ci.sid;
-    PORT_Assert(sid != 0);
-
-    cert = ss->sec.peerCert;
-
-    serverKey = CERT_ExtractPublicKey(cert);
-    if (!serverKey) {
-        SSL_DBG(("%d: SSL[%d]: extract public key failed: error=%d",
-                 SSL_GETPID(), ss->fd, PORT_GetError()));
-        PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
-        rv = SECFailure;
-        goto loser2;
-    }
-
-    ss->sec.authAlgorithm = ssl_sign_rsa;
-    ss->sec.keaType = ssl_kea_rsa;
-    ss->sec.keaKeyBits =
-        ss->sec.authKeyBits = SECKEY_PublicKeyStrengthInBits(serverKey);
-
-    /* Choose a compatible cipher with the server */
-    nc = csLen / 3;
-    cipher = ssl2_ChooseSessionCypher(ss, nc, cs, &keyLen);
-    if (cipher < 0) {
-        /* ssl2_ChooseSessionCypher has set error code. */
-        ssl2_SendErrorMessage(ss, SSL_PE_NO_CYPHERS);
-        goto loser;
-    }
-
-    /* Generate the random keys */
-    PK11_GenerateRandom(keyData, sizeof(keyData));
-
-    /*
-    ** Next, carve up the keys into clear and encrypted portions. The
-    ** clear data is taken from the start of keyData and the encrypted
-    ** portion from the remainder. Note that each of these portions is
-    ** carved in half, one half for the read-key and one for the
-    ** write-key.
-    */
-    ca = 0;
-
-    /* We know that cipher is a legit value here, because
-     * ssl2_ChooseSessionCypher doesn't return bogus values.
-     */
-    ckLen = ssl_Specs[cipher].pubLen; /* cleartext key length. */
-    caLen = ssl_Specs[cipher].ivLen;  /* IV length.     */
-    if (caLen) {
-        PORT_Assert(sizeof iv >= caLen);
-        PK11_GenerateRandom(iv, caLen);
-        ca = iv;
-    }
-
-    /* Fill in session-id */
-    rv = ssl2_FillInSID(sid, cipher, keyData, keyLen,
-                        ca, caLen, keyLen << 3, (keyLen - ckLen) << 3,
-                        ss->sec.authAlgorithm, ss->sec.authKeyBits,
-                        ss->sec.keaType, ss->sec.keaKeyBits);
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-
-    SSL_TRC(1, ("%d: SSL[%d]: client, using %s cipher, clear=%d total=%d",
-                SSL_GETPID(), ss->fd, ssl_cipherName[cipher],
-                ckLen << 3, keyLen << 3));
-
-    /* Now setup read and write ciphers */
-    rv = ssl2_CreateSessionCypher(ss, sid, PR_TRUE);
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-
-    /*
-    ** Fill in the encryption buffer with some random bytes. Then
-    ** copy in the portion of the session key we are encrypting.
-    */
-    modulusLen = SECKEY_PublicKeyStrength(serverKey);
-    rek.data = keyData + ckLen;
-    rek.len = keyLen - ckLen;
-    eblock = ssl_FormatSSL2Block(modulusLen, &rek);
-    if (eblock == NULL)
-        goto loser;
-
-    /* Set up the padding for version 2 rollback detection. */
-    /* XXX We should really use defines here */
-    if (!SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
-        PORT_Assert((modulusLen - rek.len) > 12);
-        PORT_Memset(eblock + modulusLen - rek.len - 8 - 1, 0x03, 8);
-    }
-    ekbuf = (PRUint8 *)PORT_Alloc(modulusLen);
-    if (!ekbuf)
-        goto loser;
-    PRINT_BUF(10, (ss, "master key encryption block:",
-                   eblock, modulusLen));
-
-    /* Encrypt ekitem */
-    rv = PK11_PubEncryptRaw(serverKey, ekbuf, eblock, modulusLen,
-                            ss->pkcs11PinArg);
-    if (rv)
-        goto loser;
-
-    /*  Now we have everything ready to send */
-    rv = ssl2_SendSessionKeyMessage(ss, cipher, keyLen << 3, ca, caLen,
-                                    keyData, ckLen, ekbuf, modulusLen);
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-    rv = SECSuccess;
-    goto done;
-
-loser:
-    rv = SECFailure;
-
-loser2:
-done:
-    PORT_Memset(keyData, 0, sizeof(keyData));
-    PORT_ZFree(ekbuf, modulusLen);
-    PORT_ZFree(eblock, modulusLen);
-    SECKEY_DestroyPublicKey(serverKey);
-    return rv;
-}
-
-/************************************************************************/
-
-/*
- * Called from ssl2_HandleMessage in response to SSL_MT_SERVER_FINISHED message.
- * Caller holds recvBufLock and handshakeLock
- */
-static void
-ssl2_ClientRegSessionID(sslSocket *ss, PRUint8 *s)
-{
-    sslSessionID *sid = ss->sec.ci.sid;
-
-    /* Record entry in nonce cache */
-    if (sid->peerCert == NULL) {
-        PORT_Memcpy(sid->u.ssl2.sessionID, s, sizeof(sid->u.ssl2.sessionID));
-        sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
-    }
-    if (!ss->opt.noCache && sid->cached == never_cached)
-        (*ss->sec.cache)(sid);
-}
-
-/* Called from ssl2_HandleMessage() */
-static SECStatus
-ssl2_TriggerNextMessage(sslSocket *ss)
-{
-    SECStatus rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    if ((ss->sec.ci.requiredElements & CIS_HAVE_CERTIFICATE) &&
-        !(ss->sec.ci.sentElements & CIS_HAVE_CERTIFICATE)) {
-        ss->sec.ci.sentElements |= CIS_HAVE_CERTIFICATE;
-        rv = ssl2_SendCertificateRequestMessage(ss);
-        return rv;
-    }
-    return SECSuccess;
-}
-
-/* See if it's time to send our finished message, or if the handshakes are
-** complete.  Send finished message if appropriate.
-** Returns SECSuccess unless anything goes wrong.
-**
-** Called from ssl2_HandleMessage,
-**             ssl2_HandleVerifyMessage
-**             ssl2_HandleServerHelloMessage
-**             ssl2_HandleClientSessionKeyMessage
-*/
-static SECStatus
-ssl2_TryToFinish(sslSocket *ss)
-{
-    SECStatus rv;
-    char e, ef;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    e = ss->sec.ci.elements;
-    ef = e | CIS_HAVE_FINISHED;
-    if ((ef & ss->sec.ci.requiredElements) == ss->sec.ci.requiredElements) {
-        if (ss->sec.isServer) {
-            /* Send server finished message if we already didn't */
-            rv = ssl2_SendServerFinishedMessage(ss);
-        } else {
-            /* Send client finished message if we already didn't */
-            rv = ssl2_SendClientFinishedMessage(ss);
-        }
-        if (rv != SECSuccess) {
-            return rv;
-        }
-        if ((e & ss->sec.ci.requiredElements) == ss->sec.ci.requiredElements) {
-            /* Totally finished */
-            ss->handshake = 0;
-            return SECSuccess;
-        }
-    }
-    return SECSuccess;
-}
-
-/*
-** Called from ssl2_HandleRequestCertificate
-*/
-static SECStatus
-ssl2_SignResponse(sslSocket *ss,
-                  SECKEYPrivateKey *key,
-                  SECItem *response)
-{
-    SGNContext *sgn = NULL;
-    PRUint8 *challenge;
-    unsigned int len;
-    SECStatus rv = SECFailure;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    challenge = ss->sec.ci.serverChallenge;
-    len = ss->sec.ci.serverChallengeLen;
-
-    /* Sign the expected data... */
-    sgn = SGN_NewContext(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, key);
-    if (!sgn)
-        goto done;
-    rv = SGN_Begin(sgn);
-    if (rv != SECSuccess)
-        goto done;
-    rv = SGN_Update(sgn, ss->sec.ci.readKey, ss->sec.ci.keySize);
-    if (rv != SECSuccess)
-        goto done;
-    rv = SGN_Update(sgn, ss->sec.ci.writeKey, ss->sec.ci.keySize);
-    if (rv != SECSuccess)
-        goto done;
-    rv = SGN_Update(sgn, challenge, len);
-    if (rv != SECSuccess)
-        goto done;
-    rv = SGN_Update(sgn, ss->sec.peerCert->derCert.data,
-                    ss->sec.peerCert->derCert.len);
-    if (rv != SECSuccess)
-        goto done;
-    rv = SGN_End(sgn, response);
-    if (rv != SECSuccess)
-        goto done;
-
-done:
-    SGN_DestroyContext(sgn, PR_TRUE);
-    return rv == SECSuccess ? SECSuccess : SECFailure;
-}
-
-/*
-** Try to handle a request-certificate message. Get client's certificate
-** and private key and sign a message for the server to see.
-** Caller must hold handshakeLock
-**
-** Called from ssl2_HandleMessage().
-*/
-static int
-ssl2_HandleRequestCertificate(sslSocket *ss)
-{
-    CERTCertificate *cert = NULL; /* app-selected client cert. */
-    SECKEYPrivateKey *key = NULL; /* priv key for cert. */
-    SECStatus rv;
-    SECItem response;
-    int ret = 0;
-    PRUint8 authType;
-
-    /*
-     * These things all need to be initialized before we can "goto loser".
-     */
-    response.data = NULL;
-
-    /* get challenge info from connectionInfo */
-    authType = ss->sec.ci.authType;
-
-    if (authType != SSL_AT_MD5_WITH_RSA_ENCRYPTION) {
-        SSL_TRC(7, ("%d: SSL[%d]: unsupported auth type 0x%x", SSL_GETPID(),
-                    ss->fd, authType));
-        goto no_cert_error;
-    }
-
-    /* Get certificate and private-key from client */
-    if (!ss->getClientAuthData) {
-        SSL_TRC(7, ("%d: SSL[%d]: client doesn't support client-auth",
-                    SSL_GETPID(), ss->fd));
-        goto no_cert_error;
-    }
-    ret = (*ss->getClientAuthData)(ss->getClientAuthDataArg, ss->fd,
-                                   NULL, &cert, &key);
-    if (ret == SECWouldBlock) {
-        PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
-        ret = -1;
-        goto loser;
-    }
-
-    if (ret) {
-        goto no_cert_error;
-    }
-
-    /* check what the callback function returned */
-    if ((!cert) || (!key)) {
-        /* we are missing either the key or cert */
-        if (cert) {
-            /* got a cert, but no key - free it */
-            CERT_DestroyCertificate(cert);
-            cert = NULL;
-        }
-        if (key) {
-            /* got a key, but no cert - free it */
-            SECKEY_DestroyPrivateKey(key);
-            key = NULL;
-        }
-        goto no_cert_error;
-    }
-
-    rv = ssl2_SignResponse(ss, key, &response);
-    if (rv != SECSuccess) {
-        ret = -1;
-        goto loser;
-    }
-
-    /* Send response message */
-    ret = ssl2_SendCertificateResponseMessage(ss, &cert->derCert, &response);
-
-    /* Now, remember the cert we sent. But first, forget any previous one. */
-    if (ss->sec.localCert) {
-        CERT_DestroyCertificate(ss->sec.localCert);
-    }
-    ss->sec.localCert = CERT_DupCertificate(cert);
-    PORT_Assert(!ss->sec.ci.sid->localCert);
-    if (ss->sec.ci.sid->localCert) {
-        CERT_DestroyCertificate(ss->sec.ci.sid->localCert);
-    }
-    ss->sec.ci.sid->localCert = cert;
-    cert = NULL;
-
-    goto done;
-
-no_cert_error:
-    SSL_TRC(7, ("%d: SSL[%d]: no certificate (ret=%d)", SSL_GETPID(),
-                ss->fd, ret));
-    ret = ssl2_SendErrorMessage(ss, SSL_PE_NO_CERTIFICATE);
-
-loser:
-done:
-    if (cert) {
-        CERT_DestroyCertificate(cert);
-    }
-    if (key) {
-        SECKEY_DestroyPrivateKey(key);
-    }
-    if (response.data) {
-        PORT_Free(response.data);
-    }
-
-    return ret;
-}
-
-/*
-** Called from ssl2_HandleMessage for SSL_MT_CLIENT_CERTIFICATE message.
-** Caller must hold HandshakeLock and RecvBufLock, since cd and response
-** are contained in the gathered input data.
-*/
-static SECStatus
-ssl2_HandleClientCertificate(sslSocket *ss,
-                             PRUint8 certType, /* XXX unused */
-                             PRUint8 *cd,
-                             unsigned int cdLen,
-                             PRUint8 *response,
-                             unsigned int responseLen)
-{
-    CERTCertificate *cert = NULL;
-    SECKEYPublicKey *pubKey = NULL;
-    VFYContext *vfy = NULL;
-    SECItem *derCert;
-    SECStatus rv = SECFailure;
-    SECItem certItem;
-    SECItem rep;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-
-    /* Extract the certificate */
-    certItem.data = cd;
-    certItem.len = cdLen;
-
-    cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL,
-                                   PR_FALSE, PR_TRUE);
-    if (cert == NULL) {
-        goto loser;
-    }
-
-    /* save the certificate, since the auth routine will need it */
-    ss->sec.peerCert = cert;
-
-    /* Extract the public key */
-    pubKey = CERT_ExtractPublicKey(cert);
-    if (!pubKey)
-        goto loser;
-
-    /* Verify the response data... */
-    rep.data = response;
-    rep.len = responseLen;
-    /* SSL 2.0 only supports RSA certs, so we don't have to worry about
-     * DSA here. */
-    vfy = VFY_CreateContext(pubKey, &rep, SEC_OID_PKCS1_RSA_ENCRYPTION,
-                            ss->pkcs11PinArg);
-    if (!vfy)
-        goto loser;
-    rv = VFY_Begin(vfy);
-    if (rv)
-        goto loser;
-
-    rv = VFY_Update(vfy, ss->sec.ci.readKey, ss->sec.ci.keySize);
-    if (rv)
-        goto loser;
-    rv = VFY_Update(vfy, ss->sec.ci.writeKey, ss->sec.ci.keySize);
-    if (rv)
-        goto loser;
-    rv = VFY_Update(vfy, ss->sec.ci.serverChallenge, SSL_CHALLENGE_BYTES);
-    if (rv)
-        goto loser;
-
-    derCert = &ss->serverCerts[kt_rsa].serverCert->derCert;
-    rv = VFY_Update(vfy, derCert->data, derCert->len);
-    if (rv)
-        goto loser;
-    rv = VFY_End(vfy);
-    if (rv)
-        goto loser;
-
-    /* Now ask the server application if it likes the certificate... */
-    rv = (SECStatus)(*ss->authCertificate)(ss->authCertificateArg,
-                                           ss->fd, PR_TRUE, PR_TRUE);
-    /* Hey, it liked it. */
-    if (SECSuccess == rv)
-        goto done;
-
-loser:
-    ss->sec.peerCert = NULL;
-    CERT_DestroyCertificate(cert);
-
-done:
-    VFY_DestroyContext(vfy, PR_TRUE);
-    SECKEY_DestroyPublicKey(pubKey);
-    return rv;
-}
-
-/*
-** Handle remaining messages between client/server. Process finished
-** messages from either side and any authentication requests.
-** This should only be called for SSLv2 handshake messages,
-** not for application data records.
-** Caller must hold handshake lock.
-**
-** Called from ssl_Do1stHandshake().
-**
-*/
-static SECStatus
-ssl2_HandleMessage(sslSocket *ss)
-{
-    PRUint8 *data;
-    PRUint8 *cid;
-    unsigned len, certType, certLen, responseLen;
-    int rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    ssl_GetRecvBufLock(ss);
-
-    data = ss->gs.buf.buf + ss->gs.recordOffset;
-
-    if (ss->gs.recordLen < 1) {
-        goto bad_peer;
-    }
-    SSL_TRC(3, ("%d: SSL[%d]: received %d message",
-                SSL_GETPID(), ss->fd, data[0]));
-    DUMP_MSG(29, (ss, data, ss->gs.recordLen));
-
-    switch (data[0]) {
-        case SSL_MT_CLIENT_FINISHED:
-            if (ss->sec.ci.elements & CIS_HAVE_FINISHED) {
-                SSL_DBG(("%d: SSL[%d]: dup client-finished message",
-                         SSL_GETPID(), ss->fd));
-                goto bad_peer;
-            }
-
-            /* See if nonce matches */
-            len = ss->gs.recordLen - 1;
-            cid = data + 1;
-            if ((len != sizeof(ss->sec.ci.connectionID)) ||
-                (PORT_Memcmp(ss->sec.ci.connectionID, cid, len) != 0)) {
-                SSL_DBG(("%d: SSL[%d]: bad connection-id", SSL_GETPID(), ss->fd));
-                PRINT_BUF(5, (ss, "sent connection-id",
-                              ss->sec.ci.connectionID,
-                              sizeof(ss->sec.ci.connectionID)));
-                PRINT_BUF(5, (ss, "rcvd connection-id", cid, len));
-                goto bad_peer;
-            }
-
-            SSL_TRC(5, ("%d: SSL[%d]: got client finished, waiting for 0x%d",
-                        SSL_GETPID(), ss->fd,
-                        ss->sec.ci.requiredElements ^ ss->sec.ci.elements));
-            ss->sec.ci.elements |= CIS_HAVE_FINISHED;
-            break;
-
-        case SSL_MT_SERVER_FINISHED:
-            if (ss->sec.ci.elements & CIS_HAVE_FINISHED) {
-                SSL_DBG(("%d: SSL[%d]: dup server-finished message",
-                         SSL_GETPID(), ss->fd));
-                goto bad_peer;
-            }
-
-            if (ss->gs.recordLen - 1 != SSL2_SESSIONID_BYTES) {
-                SSL_DBG(("%d: SSL[%d]: bad server-finished message, len=%d",
-                         SSL_GETPID(), ss->fd, ss->gs.recordLen));
-                goto bad_peer;
-            }
-            ssl2_ClientRegSessionID(ss, data + 1);
-            SSL_TRC(5, ("%d: SSL[%d]: got server finished, waiting for 0x%d",
-                        SSL_GETPID(), ss->fd,
-                        ss->sec.ci.requiredElements ^ ss->sec.ci.elements));
-            ss->sec.ci.elements |= CIS_HAVE_FINISHED;
-            break;
-
-        case SSL_MT_REQUEST_CERTIFICATE:
-            len = ss->gs.recordLen - 2;
-            if ((len < SSL_MIN_CHALLENGE_BYTES) ||
-                (len > SSL_MAX_CHALLENGE_BYTES)) {
-                /* Bad challenge */
-                SSL_DBG(("%d: SSL[%d]: bad cert request message: code len=%d",
-                         SSL_GETPID(), ss->fd, len));
-                goto bad_peer;
-            }
-
-            /* save auth request info */
-            ss->sec.ci.authType = data[1];
-            ss->sec.ci.serverChallengeLen = len;
-            PORT_Memcpy(ss->sec.ci.serverChallenge, data + 2, len);
-
-            rv = ssl2_HandleRequestCertificate(ss);
-            if (rv == SECWouldBlock) {
-                SSL_TRC(3, ("%d: SSL[%d]: async cert request",
-                            SSL_GETPID(), ss->fd));
-                /* someone is handling this asynchronously */
-                ssl_ReleaseRecvBufLock(ss);
-                return SECWouldBlock;
-            }
-            if (rv) {
-                SET_ERROR_CODE
-                goto loser;
-            }
-            break;
-
-        case SSL_MT_CLIENT_CERTIFICATE:
-            if (!ss->authCertificate) {
-                /* Server asked for authentication and can't handle it */
-                PORT_SetError(SSL_ERROR_BAD_SERVER);
-                goto loser;
-            }
-            if (ss->gs.recordLen < SSL_HL_CLIENT_CERTIFICATE_HBYTES) {
-                SET_ERROR_CODE
-                goto loser;
-            }
-            certType = data[1];
-            certLen = (data[2] << 8) | data[3];
-            responseLen = (data[4] << 8) | data[5];
-            if (certType != SSL_CT_X509_CERTIFICATE) {
-                PORT_SetError(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
-                goto loser;
-            }
-            if (certLen + responseLen + SSL_HL_CLIENT_CERTIFICATE_HBYTES >
-                ss->gs.recordLen) {
-                /* prevent overflow crash. */
-                rv = SECFailure;
-            } else
-                rv = ssl2_HandleClientCertificate(ss, data[1],
-                                                  data + SSL_HL_CLIENT_CERTIFICATE_HBYTES,
-                                                  certLen,
-                                                  data + SSL_HL_CLIENT_CERTIFICATE_HBYTES + certLen,
-                                                  responseLen);
-            if (rv) {
-                (void)ssl2_SendErrorMessage(ss, SSL_PE_BAD_CERTIFICATE);
-                SET_ERROR_CODE
-                goto loser;
-            }
-            ss->sec.ci.elements |= CIS_HAVE_CERTIFICATE;
-            break;
-
-        case SSL_MT_ERROR:
-            rv = (data[1] << 8) | data[2];
-            SSL_TRC(2, ("%d: SSL[%d]: got error message, error=0x%x",
-                        SSL_GETPID(), ss->fd, rv));
-
-            /* Convert protocol error number into API error number */
-            switch (rv) {
-                case SSL_PE_NO_CYPHERS:
-                    rv = SSL_ERROR_NO_CYPHER_OVERLAP;
-                    break;
-                case SSL_PE_NO_CERTIFICATE:
-                    rv = SSL_ERROR_NO_CERTIFICATE;
-                    break;
-                case SSL_PE_BAD_CERTIFICATE:
-                    rv = SSL_ERROR_BAD_CERTIFICATE;
-                    break;
-                case SSL_PE_UNSUPPORTED_CERTIFICATE_TYPE:
-                    rv = SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE;
-                    break;
-                default:
-                    goto bad_peer;
-            }
-            /* XXX make certificate-request optionally fail... */
-            PORT_SetError(rv);
-            goto loser;
-
-        default:
-            SSL_DBG(("%d: SSL[%d]: unknown message %d",
-                     SSL_GETPID(), ss->fd, data[0]));
-            goto loser;
-    }
-
-    SSL_TRC(3, ("%d: SSL[%d]: handled %d message, required=0x%x got=0x%x",
-                SSL_GETPID(), ss->fd, data[0],
-                ss->sec.ci.requiredElements, ss->sec.ci.elements));
-
-    rv = ssl2_TryToFinish(ss);
-    if (rv != SECSuccess)
-        goto loser;
-
-    ss->gs.recordLen = 0;
-    ssl_ReleaseRecvBufLock(ss);
-
-    if (ss->handshake == 0) {
-        return SECSuccess;
-    }
-
-    ss->handshake = ssl_GatherRecord1stHandshake;
-    ss->nextHandshake = ssl2_HandleMessage;
-    return ssl2_TriggerNextMessage(ss);
-
-bad_peer:
-    PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT : SSL_ERROR_BAD_SERVER);
-/* FALL THROUGH */
-
-loser:
-    ssl_ReleaseRecvBufLock(ss);
-    return SECFailure;
-}
-
-/************************************************************************/
-
-/* Called from ssl_Do1stHandshake, after ssl2_HandleServerHelloMessage.
-*/
-static SECStatus
-ssl2_HandleVerifyMessage(sslSocket *ss)
-{
-    PRUint8 *data;
-    SECStatus rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-    ssl_GetRecvBufLock(ss);
-
-    data = ss->gs.buf.buf + ss->gs.recordOffset;
-    DUMP_MSG(29, (ss, data, ss->gs.recordLen));
-    if ((ss->gs.recordLen != 1 + SSL_CHALLENGE_BYTES) ||
-        (data[0] != SSL_MT_SERVER_VERIFY) ||
-        NSS_SecureMemcmp(data + 1, ss->sec.ci.clientChallenge,
-                         SSL_CHALLENGE_BYTES)) {
-        /* Bad server */
-        PORT_SetError(SSL_ERROR_BAD_SERVER);
-        goto loser;
-    }
-    ss->sec.ci.elements |= CIS_HAVE_VERIFY;
-
-    SSL_TRC(5, ("%d: SSL[%d]: got server-verify, required=0x%d got=0x%x",
-                SSL_GETPID(), ss->fd, ss->sec.ci.requiredElements,
-                ss->sec.ci.elements));
-
-    rv = ssl2_TryToFinish(ss);
-    if (rv)
-        goto loser;
-
-    ss->gs.recordLen = 0;
-    ssl_ReleaseRecvBufLock(ss);
-
-    if (ss->handshake == 0) {
-        return SECSuccess;
-    }
-    ss->handshake = ssl_GatherRecord1stHandshake;
-    ss->nextHandshake = ssl2_HandleMessage;
-    return SECSuccess;
-
-loser:
-    ssl_ReleaseRecvBufLock(ss);
-    return SECFailure;
-}
-
-/* Not static because ssl2_GatherData() tests ss->nextHandshake for this value.
- * ICK!
- * Called from ssl_Do1stHandshake after ssl2_BeginClientHandshake()
- */
-SECStatus
-ssl2_HandleServerHelloMessage(sslSocket *ss)
-{
-    sslSessionID *sid;
-    PRUint8 *cert;
-    PRUint8 *cs;
-    PRUint8 *data;
-    SECStatus rv;
-    unsigned int needed, sidHit, certLen, csLen, cidLen, certType, err;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    if (!ss->opt.enableSSL2) {
-        PORT_SetError(SSL_ERROR_SSL2_DISABLED);
-        return SECFailure;
-    }
-
-    ssl_GetRecvBufLock(ss);
-
-    PORT_Assert(ss->sec.ci.sid != 0);
-    sid = ss->sec.ci.sid;
-
-    data = ss->gs.buf.buf + ss->gs.recordOffset;
-    DUMP_MSG(29, (ss, data, ss->gs.recordLen));
-
-    /* Make sure first message has some data and is the server hello message */
-    if ((ss->gs.recordLen < SSL_HL_SERVER_HELLO_HBYTES) ||
-        (data[0] != SSL_MT_SERVER_HELLO)) {
-        if ((data[0] == SSL_MT_ERROR) && (ss->gs.recordLen == 3)) {
-            err = (data[1] << 8) | data[2];
-            if (err == SSL_PE_NO_CYPHERS) {
-                PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
-                goto loser;
-            }
-        }
-        goto bad_server;
-    }
-
-    sidHit = data[1];
-    certType = data[2];
-    ss->version = (data[3] << 8) | data[4];
-    certLen = (data[5] << 8) | data[6];
-    csLen = (data[7] << 8) | data[8];
-    cidLen = (data[9] << 8) | data[10];
-    cert = data + SSL_HL_SERVER_HELLO_HBYTES;
-    cs = cert + certLen;
-
-    SSL_TRC(5,
-            ("%d: SSL[%d]: server-hello, hit=%d vers=%x certLen=%d csLen=%d cidLen=%d",
-             SSL_GETPID(), ss->fd, sidHit, ss->version, certLen,
-             csLen, cidLen));
-    if (ss->version != SSL_LIBRARY_VERSION_2) {
-        if (ss->version < SSL_LIBRARY_VERSION_2) {
-            SSL_TRC(3, ("%d: SSL[%d]: demoting self (%x) to server version (%x)",
-                        SSL_GETPID(), ss->fd, SSL_LIBRARY_VERSION_2,
-                        ss->version));
-        } else {
-            SSL_TRC(1, ("%d: SSL[%d]: server version is %x (we are %x)",
-                        SSL_GETPID(), ss->fd, ss->version, SSL_LIBRARY_VERSION_2));
-            /* server claims to be newer but does not follow protocol */
-            PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
-            goto loser;
-        }
-    }
-
-    if ((SSL_HL_SERVER_HELLO_HBYTES + certLen + csLen + cidLen >
-         ss->gs.recordLen) ||
-        (csLen % 3) != 0
-        /* || cidLen < SSL_CONNECTIONID_BYTES || cidLen > 32  */
-        ) {
-        goto bad_server;
-    }
-
-    /* Save connection-id.
-    ** This code only saves the first 16 byte of the connectionID.
-    ** If the connectionID is shorter than 16 bytes, it is zero-padded.
-    */
-    if (cidLen < sizeof ss->sec.ci.connectionID)
-        memset(ss->sec.ci.connectionID, 0, sizeof ss->sec.ci.connectionID);
-    cidLen = PR_MIN(cidLen, sizeof ss->sec.ci.connectionID);
-    PORT_Memcpy(ss->sec.ci.connectionID, cs + csLen, cidLen);
-
-    /* See if session-id hit */
-    needed = CIS_HAVE_MASTER_KEY | CIS_HAVE_FINISHED | CIS_HAVE_VERIFY;
-    if (sidHit) {
-        if (certLen || csLen) {
-            /* Uh oh - bogus server */
-            SSL_DBG(("%d: SSL[%d]: client, huh? hit=%d certLen=%d csLen=%d",
-                     SSL_GETPID(), ss->fd, sidHit, certLen, csLen));
-            goto bad_server;
-        }
-
-        /* Total winner. */
-        SSL_TRC(1, ("%d: SSL[%d]: client, using nonce for peer=0x%08x "
-                    "port=0x%04x",
-                    SSL_GETPID(), ss->fd, ss->sec.ci.peer, ss->sec.ci.port));
-        ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
-        ss->sec.authAlgorithm = sid->authAlgorithm;
-        ss->sec.authKeyBits = sid->authKeyBits;
-        ss->sec.keaType = sid->keaType;
-        ss->sec.keaKeyBits = sid->keaKeyBits;
-        rv = ssl2_CreateSessionCypher(ss, sid, PR_TRUE);
-        if (rv != SECSuccess) {
-            goto loser;
-        }
-    } else {
-        if (certType != SSL_CT_X509_CERTIFICATE) {
-            PORT_SetError(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
-            goto loser;
-        }
-        if (csLen == 0) {
-            PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
-            SSL_DBG(("%d: SSL[%d]: no cipher overlap",
-                     SSL_GETPID(), ss->fd));
-            goto loser;
-        }
-        if (certLen == 0) {
-            SSL_DBG(("%d: SSL[%d]: client, huh? certLen=%d csLen=%d",
-                     SSL_GETPID(), ss->fd, certLen, csLen));
-            goto bad_server;
-        }
-
-        if (sid->cached != never_cached) {
-            /* Forget our session-id - server didn't like it */
-            SSL_TRC(7, ("%d: SSL[%d]: server forgot me, uncaching session-id",
-                        SSL_GETPID(), ss->fd));
-            if (ss->sec.uncache)
-                (*ss->sec.uncache)(sid);
-            ssl_FreeSID(sid);
-            ss->sec.ci.sid = sid = PORT_ZNew(sslSessionID);
-            if (!sid) {
-                goto loser;
-            }
-            sid->references = 1;
-            sid->addr = ss->sec.ci.peer;
-            sid->port = ss->sec.ci.port;
-        }
-
-        /* decode the server's certificate */
-        rv = ssl2_ClientHandleServerCert(ss, cert, certLen);
-        if (rv != SECSuccess) {
-            if (PORT_GetError() == SSL_ERROR_BAD_CERTIFICATE) {
-                (void)ssl2_SendErrorMessage(ss, SSL_PE_BAD_CERTIFICATE);
-            }
-            goto loser;
-        }
-
-        /* Setup new session cipher */
-        rv = ssl2_ClientSetupSessionCypher(ss, cs, csLen);
-        if (rv != SECSuccess) {
-            if (PORT_GetError() == SSL_ERROR_BAD_CERTIFICATE) {
-                (void)ssl2_SendErrorMessage(ss, SSL_PE_BAD_CERTIFICATE);
-            }
-            goto loser;
-        }
-    }
-
-    /* Build up final list of required elements */
-    ss->sec.ci.elements = CIS_HAVE_MASTER_KEY;
-    ss->sec.ci.requiredElements = needed;
-
-    if (!sidHit) {
-        /* verify the server's certificate. if sidHit, don't check signatures */
-        rv = (*ss->authCertificate)(ss->authCertificateArg, ss->fd,
-                                    (PRBool)(!sidHit), PR_FALSE);
-        if (rv) {
-            if (ss->handleBadCert) {
-                rv = (*ss->handleBadCert)(ss->badCertArg, ss->fd);
-                if (rv) {
-                    if (rv == SECWouldBlock) {
-                        SSL_DBG(("%d: SSL[%d]: SSL2 bad cert handler returned "
-                                 "SECWouldBlock",
-                                 SSL_GETPID(), ss->fd));
-                        PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
-                        rv = SECFailure;
-                    } else {
-                        /* cert is bad */
-                        SSL_DBG(("%d: SSL[%d]: server certificate is no good: error=%d",
-                                 SSL_GETPID(), ss->fd, PORT_GetError()));
-                    }
-                    goto loser;
-                }
-                /* cert is good */
-            } else {
-                SSL_DBG(("%d: SSL[%d]: server certificate is no good: error=%d",
-                         SSL_GETPID(), ss->fd, PORT_GetError()));
-                goto loser;
-            }
-        }
-    }
-    /*
-    ** At this point we have a completed session key and our session
-    ** cipher is setup and ready to go. Switch to encrypted write routine
-    ** as all future message data is to be encrypted.
-    */
-    ssl2_UseEncryptedSendFunc(ss);
-
-    rv = ssl2_TryToFinish(ss);
-    if (rv != SECSuccess)
-        goto loser;
-
-    ss->gs.recordLen = 0;
-
-    ssl_ReleaseRecvBufLock(ss);
-
-    if (ss->handshake == 0) {
-        return SECSuccess;
-    }
-
-    SSL_TRC(5, ("%d: SSL[%d]: got server-hello, required=0x%d got=0x%x",
-                SSL_GETPID(), ss->fd, ss->sec.ci.requiredElements,
-                ss->sec.ci.elements));
-    ss->handshake = ssl_GatherRecord1stHandshake;
-    ss->nextHandshake = ssl2_HandleVerifyMessage;
-    return SECSuccess;
-
-bad_server:
-    PORT_SetError(SSL_ERROR_BAD_SERVER);
-/* FALL THROUGH */
-
-loser:
-    ssl_ReleaseRecvBufLock(ss);
-    return SECFailure;
-}
-
-/* Sends out the initial client Hello message on the connection.
- * Acquires and releases the socket's xmitBufLock.
- */
-SECStatus
-ssl2_BeginClientHandshake(sslSocket *ss)
-{
-    sslSessionID *sid;
-    PRUint8 *msg;
-    PRUint8 *cp;
-    PRUint8 *localCipherSpecs = NULL;
-    unsigned int localCipherSize;
-    unsigned int i;
-    int sendLen, sidLen = 0;
-    SECStatus rv;
-    TLSExtensionData *xtnData;
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    ss->sec.isServer = 0;
-    ss->sec.sendSequence = 0;
-    ss->sec.rcvSequence = 0;
-    ssl_ChooseSessionIDProcs(&ss->sec);
-
-    if (!ss->cipherSpecs) {
-        rv = ssl2_ConstructCipherSpecs(ss);
-        if (rv != SECSuccess)
-            goto loser;
-    }
-
-    /* count the SSL2 and SSL3 enabled ciphers.
-     * if either is zero, clear the socket's enable for that protocol.
-     */
-    rv = ssl2_CheckConfigSanity(ss);
-    if (rv != SECSuccess)
-        goto loser;
-
-    /* Get peer name of server */
-    rv = ssl_GetPeerInfo(ss);
-    if (rv < 0) {
-#ifdef HPUX11
-        /*
-         * On some HP-UX B.11.00 systems, getpeername() occasionally
-         * fails with ENOTCONN after a successful completion of
-         * non-blocking connect.  I found that if we do a write()
-         * and then retry getpeername(), it will work.
-         */
-        if (PR_GetError() == PR_NOT_CONNECTED_ERROR) {
-            char dummy;
-            (void)PR_Write(ss->fd->lower, &dummy, 0);
-            rv = ssl_GetPeerInfo(ss);
-            if (rv < 0) {
-                goto loser;
-            }
-        }
-#else
-        goto loser;
-#endif
-    }
-
-    SSL_TRC(3, ("%d: SSL[%d]: sending client-hello", SSL_GETPID(), ss->fd));
-
-    /* Try to find server in our session-id cache */
-    if (ss->opt.noCache) {
-        sid = NULL;
-    } else {
-        sid = ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID,
-                            ss->url);
-    }
-    while (sid) { /* this isn't really a loop */
-        PRBool sidVersionEnabled =
-            (!SSL3_ALL_VERSIONS_DISABLED(&ss->vrange) &&
-             sid->version >= ss->vrange.min &&
-             sid->version <= ss->vrange.max) ||
-            (sid->version < SSL_LIBRARY_VERSION_3_0 && ss->opt.enableSSL2);
-
-        /* if we're not doing this SID's protocol any more, drop it. */
-        if (!sidVersionEnabled) {
-            if (ss->sec.uncache)
-                ss->sec.uncache(sid);
-            ssl_FreeSID(sid);
-            sid = NULL;
-            break;
-        }
-        if (sid->version < SSL_LIBRARY_VERSION_3_0) {
-            /* If the cipher in this sid is not enabled, drop it. */
-            for (i = 0; i < ss->sizeCipherSpecs; i += 3) {
-                if (ss->cipherSpecs[i] == sid->u.ssl2.cipherType)
-                    break;
-            }
-            if (i >= ss->sizeCipherSpecs) {
-                if (ss->sec.uncache)
-                    ss->sec.uncache(sid);
-                ssl_FreeSID(sid);
-                sid = NULL;
-                break;
-            }
-        }
-        sidLen = sizeof(sid->u.ssl2.sessionID);
-        PRINT_BUF(4, (ss, "client, found session-id:", sid->u.ssl2.sessionID,
-                      sidLen));
-        ss->version = sid->version;
-        PORT_Assert(!ss->sec.localCert);
-        if (ss->sec.localCert) {
-            CERT_DestroyCertificate(ss->sec.localCert);
-        }
-        ss->sec.localCert = CERT_DupCertificate(sid->localCert);
-        break; /* this isn't really a loop */
-    }
-    if (!sid) {
-        sidLen = 0;
-        sid = PORT_ZNew(sslSessionID);
-        if (!sid) {
-            goto loser;
-        }
-        sid->references = 1;
-        sid->cached = never_cached;
-        sid->addr = ss->sec.ci.peer;
-        sid->port = ss->sec.ci.port;
-        if (ss->peerID != NULL) {
-            sid->peerID = PORT_Strdup(ss->peerID);
-        }
-        if (ss->url != NULL) {
-            sid->urlSvrName = PORT_Strdup(ss->url);
-        }
-    }
-    ss->sec.ci.sid = sid;
-
-    PORT_Assert(sid != NULL);
-
-    if ((sid->version >= SSL_LIBRARY_VERSION_3_0 || !ss->opt.v2CompatibleHello) &&
-        !SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
-        ss->gs.state = GS_INIT;
-        ss->handshake = ssl_GatherRecord1stHandshake;
-
-        /* ssl3_SendClientHello will override this if it succeeds. */
-        ss->version = SSL_LIBRARY_VERSION_3_0;
-
-        ssl_GetSSL3HandshakeLock(ss);
-        ssl_GetXmitBufLock(ss);
-        rv = ssl3_SendClientHello(ss, PR_FALSE);
-        ssl_ReleaseXmitBufLock(ss);
-        ssl_ReleaseSSL3HandshakeLock(ss);
-
-        return rv;
-    }
-#ifndef NSS_DISABLE_ECC
-    /* ensure we don't neogtiate ECC cipher suites with SSL2 hello */
-    ssl3_DisableECCSuites(ss, NULL); /* disable all ECC suites */
-    if (ss->cipherSpecs != NULL) {
-        PORT_Free(ss->cipherSpecs);
-        ss->cipherSpecs = NULL;
-        ss->sizeCipherSpecs = 0;
-    }
-#endif /* NSS_DISABLE_ECC */
-
-    if (!ss->cipherSpecs) {
-        rv = ssl2_ConstructCipherSpecs(ss);
-        if (rv < 0) {
-            return rv;
-        }
-    }
-    localCipherSpecs = ss->cipherSpecs;
-    localCipherSize = ss->sizeCipherSpecs;
-
-    /* Add 3 for SCSV */
-    sendLen = SSL_HL_CLIENT_HELLO_HBYTES + localCipherSize + 3 + sidLen +
-              SSL_CHALLENGE_BYTES;
-
-    /* Generate challenge bytes for server */
-    PK11_GenerateRandom(ss->sec.ci.clientChallenge, SSL_CHALLENGE_BYTES);
-
-    ssl_GetXmitBufLock(ss); /***************************************/
-
-    rv = ssl2_GetSendBuffer(ss, sendLen);
-    if (rv)
-        goto unlock_loser;
-
-    /* Construct client-hello message */
-    cp = msg = ss->sec.ci.sendBuf.buf;
-    msg[0] = SSL_MT_CLIENT_HELLO;
-    ss->clientHelloVersion = SSL3_ALL_VERSIONS_DISABLED(&ss->vrange) ? SSL_LIBRARY_VERSION_2
-                                                                     : ss->vrange.max;
-
-    msg[1] = MSB(ss->clientHelloVersion);
-    msg[2] = LSB(ss->clientHelloVersion);
-    /* Add 3 for SCSV */
-    msg[3] = MSB(localCipherSize + 3);
-    msg[4] = LSB(localCipherSize + 3);
-    msg[5] = MSB(sidLen);
-    msg[6] = LSB(sidLen);
-    msg[7] = MSB(SSL_CHALLENGE_BYTES);
-    msg[8] = LSB(SSL_CHALLENGE_BYTES);
-    cp += SSL_HL_CLIENT_HELLO_HBYTES;
-    PORT_Memcpy(cp, localCipherSpecs, localCipherSize);
-    cp += localCipherSize;
-    /*
-     * Add SCSV.  SSL 2.0 cipher suites are listed before SSL 3.0 cipher
-     * suites in localCipherSpecs for compatibility with SSL 2.0 servers.
-     * Since SCSV looks like an SSL 3.0 cipher suite, we can't add it at
-     * the beginning.
-     */
-    cp[0] = 0x00;
-    cp[1] = 0x00;
-    cp[2] = 0xff;
-    cp += 3;
-    if (sidLen) {
-        PORT_Memcpy(cp, sid->u.ssl2.sessionID, sidLen);
-        cp += sidLen;
-    }
-    PORT_Memcpy(cp, ss->sec.ci.clientChallenge, SSL_CHALLENGE_BYTES);
-
-    /* Send it to the server */
-    DUMP_MSG(29, (ss, msg, sendLen));
-    ss->handshakeBegun = 1;
-    rv = (*ss->sec.send)(ss, msg, sendLen, 0);
-
-    ssl_ReleaseXmitBufLock(ss); /***************************************/
-
-    if (rv < 0) {
-        goto loser;
-    }
-
-    rv = ssl3_StartHandshakeHash(ss, msg, sendLen);
-    if (rv < 0) {
-        goto loser;
-    }
-
-    /*
-     * Since we sent the SCSV, pretend we sent empty RI extension.  We need
-     * to record the extension has been advertised after ssl3_InitState has
-     * been called, which ssl3_StartHandshakeHash took care for us above.
-     */
-    xtnData = &ss->xtnData;
-    xtnData->advertised[xtnData->numAdvertised++] = ssl_renegotiation_info_xtn;
-
-    /* Setup to receive servers hello message */
-    ssl_GetRecvBufLock(ss);
-    ss->gs.recordLen = 0;
-    ssl_ReleaseRecvBufLock(ss);
-
-    ss->handshake = ssl_GatherRecord1stHandshake;
-    ss->nextHandshake = ssl2_HandleServerHelloMessage;
-    return SECSuccess;
-
-unlock_loser:
-    ssl_ReleaseXmitBufLock(ss);
-loser:
-    return SECFailure;
-}
-
-/************************************************************************/
-
-/* Handle the CLIENT-MASTER-KEY message.
-** Acquires and releases RecvBufLock.
-** Called from ssl2_HandleClientHelloMessage().
-*/
-static SECStatus
-ssl2_HandleClientSessionKeyMessage(sslSocket *ss)
-{
-    PRUint8 *data;
-    unsigned int caLen;
-    unsigned int ckLen;
-    unsigned int ekLen;
-    unsigned int keyBits;
-    int cipher;
-    SECStatus rv;
-
-    ssl_GetRecvBufLock(ss);
-
-    data = ss->gs.buf.buf + ss->gs.recordOffset;
-    DUMP_MSG(29, (ss, data, ss->gs.recordLen));
-
-    if ((ss->gs.recordLen < SSL_HL_CLIENT_MASTER_KEY_HBYTES) ||
-        (data[0] != SSL_MT_CLIENT_MASTER_KEY)) {
-        goto bad_client;
-    }
-    cipher = data[1];
-    keyBits = (data[2] << 8) | data[3];
-    ckLen = (data[4] << 8) | data[5];
-    ekLen = (data[6] << 8) | data[7];
-    caLen = (data[8] << 8) | data[9];
-
-    SSL_TRC(5, ("%d: SSL[%d]: session-key, cipher=%d keyBits=%d ckLen=%d ekLen=%d caLen=%d",
-                SSL_GETPID(), ss->fd, cipher, keyBits, ckLen, ekLen, caLen));
-
-    if (ss->gs.recordLen <
-        SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen + ekLen + caLen) {
-        SSL_DBG(("%d: SSL[%d]: protocol size mismatch dataLen=%d",
-                 SSL_GETPID(), ss->fd, ss->gs.recordLen));
-        goto bad_client;
-    }
-
-    /* Use info from client to setup session key */
-    rv = ssl2_ServerSetupSessionCypher(ss, cipher, keyBits,
-                                       data + SSL_HL_CLIENT_MASTER_KEY_HBYTES,
-                                       ckLen,
-                                       data + SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen,
-                                       ekLen,
-                                       data + SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen + ekLen,
-                                       caLen);
-    ss->gs.recordLen = 0; /* we're done with this record. */
-
-    ssl_ReleaseRecvBufLock(ss);
-
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-    ss->sec.ci.elements |= CIS_HAVE_MASTER_KEY;
-    ssl2_UseEncryptedSendFunc(ss);
-
-    /* Send server verify message now that keys are established */
-    rv = ssl2_SendServerVerifyMessage(ss);
-    if (rv != SECSuccess)
-        goto loser;
-
-    rv = ssl2_TryToFinish(ss);
-    if (rv != SECSuccess)
-        goto loser;
-    if (ss->handshake == 0) {
-        return SECSuccess;
-    }
-
-    SSL_TRC(5, ("%d: SSL[%d]: server: waiting for elements=0x%d",
-                SSL_GETPID(), ss->fd,
-                ss->sec.ci.requiredElements ^ ss->sec.ci.elements));
-    ss->handshake = ssl_GatherRecord1stHandshake;
-    ss->nextHandshake = ssl2_HandleMessage;
-
-    return ssl2_TriggerNextMessage(ss);
-
-bad_client:
-    ssl_ReleaseRecvBufLock(ss);
-    PORT_SetError(SSL_ERROR_BAD_CLIENT);
-/* FALLTHROUGH */
-
-loser:
-    return SECFailure;
-}
-
-/*
-** Handle the initial hello message from the client
-**
-** not static because ssl2_GatherData() tests ss->nextHandshake for this value.
-*/
-SECStatus
-ssl2_HandleClientHelloMessage(sslSocket *ss)
-{
-    sslSessionID *sid;
-    sslServerCerts *sc;
-    CERTCertificate *serverCert;
-    PRUint8 *msg;
-    PRUint8 *data;
-    PRUint8 *cs;
-    PRUint8 *sd;
-    PRUint8 *cert = NULL;
-    PRUint8 *challenge;
-    unsigned int challengeLen;
-    SECStatus rv;
-    int csLen;
-    int sendLen;
-    int sdLen;
-    int certLen;
-    int pid;
-    int sent;
-    int gotXmitBufLock = 0;
-#if defined(SOLARIS) && defined(i386)
-    volatile PRUint8 hit;
-#else
-    int hit;
-#endif
-    PRUint8 csImpl[sizeof implementedCipherSuites];
-
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    sc = ss->serverCerts + kt_rsa;
-    serverCert = sc->serverCert;
-
-    ssl_GetRecvBufLock(ss);
-
-    data = ss->gs.buf.buf + ss->gs.recordOffset;
-    DUMP_MSG(29, (ss, data, ss->gs.recordLen));
-
-    /* Make sure first message has some data and is the client hello message */
-    if ((ss->gs.recordLen < SSL_HL_CLIENT_HELLO_HBYTES) ||
-        (data[0] != SSL_MT_CLIENT_HELLO)) {
-        goto bad_client;
-    }
-
-    /* Get peer name of client */
-    rv = ssl_GetPeerInfo(ss);
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-
-    /* Examine version information */
-    /*
-     * See if this might be a V2 client hello asking to use the V3 protocol
-     */
-    if ((data[0] == SSL_MT_CLIENT_HELLO) &&
-        (data[1] >= MSB(SSL_LIBRARY_VERSION_3_0)) &&
-        !SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
-        rv = ssl3_HandleV2ClientHello(ss, data, ss->gs.recordLen);
-        if (rv != SECFailure) { /* Success */
-            ss->handshake = NULL;
-            ss->nextHandshake = ssl_GatherRecord1stHandshake;
-            ss->securityHandshake = NULL;
-            ss->gs.state = GS_INIT;
-
-            /* ssl3_HandleV3ClientHello has set ss->version,
-            ** and has gotten us a brand new sid.
-            */
-            ss->sec.ci.sid->version = ss->version;
-        }
-        ssl_ReleaseRecvBufLock(ss);
-        return rv;
-    }
-    /* Previously, there was a test here to see if SSL2 was enabled.
-    ** If not, an error code was set, and SECFailure was returned,
-    ** without sending any error code to the other end of the connection.
-    ** That test has been removed.  If SSL2 has been disabled, there
-    ** should be no SSL2 ciphers enabled, and consequently, the code
-    ** below should send the ssl2 error message SSL_PE_NO_CYPHERS.
-    ** We now believe this is the correct thing to do, even when SSL2
-    ** has been explicitly disabled by the application.
-    */
-
-    /* Extract info from message */
-    ss->version = (data[1] << 8) | data[2];
-
-    /* If some client thinks ssl v2 is 2.0 instead of 0.2, we'll allow it.  */
-    if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
-        ss->version = SSL_LIBRARY_VERSION_2;
-    }
-
-    csLen = (data[3] << 8) | data[4];
-    sdLen = (data[5] << 8) | data[6];
-    challengeLen = (data[7] << 8) | data[8];
-    cs = data + SSL_HL_CLIENT_HELLO_HBYTES;
-    sd = cs + csLen;
-    challenge = sd + sdLen;
-    PRINT_BUF(7, (ss, "server, client session-id value:", sd, sdLen));
-
-    if (!csLen || (csLen % 3) != 0 ||
-        (sdLen != 0 && sdLen != SSL2_SESSIONID_BYTES) ||
-        challengeLen < SSL_MIN_CHALLENGE_BYTES ||
-        challengeLen > SSL_MAX_CHALLENGE_BYTES ||
-        (unsigned)ss->gs.recordLen !=
-            SSL_HL_CLIENT_HELLO_HBYTES + csLen + sdLen + challengeLen) {
-        SSL_DBG(("%d: SSL[%d]: bad client hello message, len=%d should=%d",
-                 SSL_GETPID(), ss->fd, ss->gs.recordLen,
-                 SSL_HL_CLIENT_HELLO_HBYTES + csLen + sdLen + challengeLen));
-        goto bad_client;
-    }
-
-    SSL_TRC(3, ("%d: SSL[%d]: client version is %x",
-                SSL_GETPID(), ss->fd, ss->version));
-    if (ss->version != SSL_LIBRARY_VERSION_2) {
-        if (ss->version > SSL_LIBRARY_VERSION_2) {
-            /*
-            ** Newer client than us. Things are ok because new clients
-            ** are required to be backwards compatible with old servers.
-            ** Change version number to our version number so that client
-            ** knows whats up.
-            */
-            ss->version = SSL_LIBRARY_VERSION_2;
-        } else {
-            SSL_TRC(1, ("%d: SSL[%d]: client version is %x (we are %x)",
-                        SSL_GETPID(), ss->fd, ss->version, SSL_LIBRARY_VERSION_2));
-            PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
-            goto loser;
-        }
-    }
-
-    /* Qualify cipher specs before returning them to client */
-    csLen = ssl2_QualifyCypherSpecs(ss, cs, csLen);
-    if (csLen == 0) {
-        /* no overlap, send client our list of supported SSL v2 ciphers. */
-        cs = csImpl;
-        csLen = sizeof implementedCipherSuites;
-        PORT_Memcpy(cs, implementedCipherSuites, csLen);
-        csLen = ssl2_QualifyCypherSpecs(ss, cs, csLen);
-        if (csLen == 0) {
-            /* We don't support any SSL v2 ciphers! */
-            ssl2_SendErrorMessage(ss, SSL_PE_NO_CYPHERS);
-            PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
-            goto loser;
-        }
-        /* Since this handhsake is going to fail, don't cache it. */
-        ss->opt.noCache = 1;
-    }
-
-    /* Squirrel away the challenge for later */
-    PORT_Memcpy(ss->sec.ci.clientChallenge, challenge, challengeLen);
-
-    /* Examine message and see if session-id is good */
-    ss->sec.ci.elements = 0;
-    if (sdLen > 0 && !ss->opt.noCache) {
-        SSL_TRC(7, ("%d: SSL[%d]: server, lookup client session-id for 0x%08x%08x%08x%08x",
-                    SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0],
-                    ss->sec.ci.peer.pr_s6_addr32[1],
-                    ss->sec.ci.peer.pr_s6_addr32[2],
-                    ss->sec.ci.peer.pr_s6_addr32[3]));
-        sid = (*ssl_sid_lookup)(&ss->sec.ci.peer, sd, sdLen, ss->dbHandle);
-    } else {
-        sid = NULL;
-    }
-    if (sid) {
-        /* Got a good session-id. Short cut! */
-        SSL_TRC(1, ("%d: SSL[%d]: server, using session-id for 0x%08x (age=%d)",
-                    SSL_GETPID(), ss->fd, ss->sec.ci.peer,
-                    ssl_Time() - sid->creationTime));
-        PRINT_BUF(1, (ss, "session-id value:", sd, sdLen));
-        ss->sec.ci.sid = sid;
-        ss->sec.ci.elements = CIS_HAVE_MASTER_KEY;
-        hit = 1;
-        certLen = 0;
-        csLen = 0;
-
-        ss->sec.authAlgorithm = sid->authAlgorithm;
-        ss->sec.authKeyBits = sid->authKeyBits;
-        ss->sec.keaType = sid->keaType;
-        ss->sec.keaKeyBits = sid->keaKeyBits;
-
-        rv = ssl2_CreateSessionCypher(ss, sid, PR_FALSE);
-        if (rv != SECSuccess) {
-            goto loser;
-        }
-    } else {
-        SECItem *derCert = &serverCert->derCert;
-
-        SSL_TRC(7, ("%d: SSL[%d]: server, lookup nonce missed",
-                    SSL_GETPID(), ss->fd));
-        if (!serverCert) {
-            SET_ERROR_CODE
-            goto loser;
-        }
-        hit = 0;
-        sid = PORT_ZNew(sslSessionID);
-        if (!sid) {
-            goto loser;
-        }
-        sid->references = 1;
-        sid->addr = ss->sec.ci.peer;
-        sid->port = ss->sec.ci.port;
-
-        /* Invent a session-id */
-        ss->sec.ci.sid = sid;
-        PK11_GenerateRandom(sid->u.ssl2.sessionID + 2, SSL2_SESSIONID_BYTES - 2);
-
-        pid = SSL_GETPID();
-        sid->u.ssl2.sessionID[0] = MSB(pid);
-        sid->u.ssl2.sessionID[1] = LSB(pid);
-        cert = derCert->data;
-        certLen = derCert->len;
-
-        /* pretend that server sids remember the local cert. */
-        PORT_Assert(!sid->localCert);
-        if (sid->localCert) {
-            CERT_DestroyCertificate(sid->localCert);
-        }
-        sid->localCert = CERT_DupCertificate(serverCert);
-
-        ss->sec.authAlgorithm = ssl_sign_rsa;
-        ss->sec.keaType = ssl_kea_rsa;
-        ss->sec.keaKeyBits =
-            ss->sec.authKeyBits = ss->serverCerts[kt_rsa].serverKeyBits;
-    }
-
-    /* server sids don't remember the local cert, so whether we found
-    ** a sid or not, just "remember" we used the rsa server cert.
-    */
-    if (ss->sec.localCert) {
-        CERT_DestroyCertificate(ss->sec.localCert);
-    }
-    ss->sec.localCert = CERT_DupCertificate(serverCert);
-
-    /* Build up final list of required elements */
-    ss->sec.ci.requiredElements = CIS_HAVE_MASTER_KEY | CIS_HAVE_FINISHED;
-    if (ss->opt.requestCertificate) {
-        ss->sec.ci.requiredElements |= CIS_HAVE_CERTIFICATE;
-    }
-    ss->sec.ci.sentElements = 0;
-
-    /* Send hello message back to client */
-    sendLen = SSL_HL_SERVER_HELLO_HBYTES + certLen + csLen +
-              SSL_CONNECTIONID_BYTES;
-
-    ssl_GetXmitBufLock(ss);
-    gotXmitBufLock = 1;
-    rv = ssl2_GetSendBuffer(ss, sendLen);
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-
-    SSL_TRC(3, ("%d: SSL[%d]: sending server-hello (%d)",
-                SSL_GETPID(), ss->fd, sendLen));
-
-    msg = ss->sec.ci.sendBuf.buf;
-    msg[0] = SSL_MT_SERVER_HELLO;
-    msg[1] = hit;
-    msg[2] = SSL_CT_X509_CERTIFICATE;
-    msg[3] = MSB(ss->version);
-    msg[4] = LSB(ss->version);
-    msg[5] = MSB(certLen);
-    msg[6] = LSB(certLen);
-    msg[7] = MSB(csLen);
-    msg[8] = LSB(csLen);
-    msg[9] = MSB(SSL_CONNECTIONID_BYTES);
-    msg[10] = LSB(SSL_CONNECTIONID_BYTES);
-    if (certLen) {
-        PORT_Memcpy(msg + SSL_HL_SERVER_HELLO_HBYTES, cert, certLen);
-    }
-    if (csLen) {
-        PORT_Memcpy(msg + SSL_HL_SERVER_HELLO_HBYTES + certLen, cs, csLen);
-    }
-    PORT_Memcpy(msg + SSL_HL_SERVER_HELLO_HBYTES + certLen + csLen,
-                ss->sec.ci.connectionID, SSL_CONNECTIONID_BYTES);
-
-    DUMP_MSG(29, (ss, msg, sendLen));
-
-    ss->handshakeBegun = 1;
-    sent = (*ss->sec.send)(ss, msg, sendLen, 0);
-    if (sent < 0) {
-        goto loser;
-    }
-    ssl_ReleaseXmitBufLock(ss);
-    gotXmitBufLock = 0;
-
-    ss->gs.recordLen = 0;
-    ss->handshake = ssl_GatherRecord1stHandshake;
-    if (hit) {
-        /* Old SID Session key is good. Go encrypted */
-        ssl2_UseEncryptedSendFunc(ss);
-
-        /* Send server verify message now that keys are established */
-        rv = ssl2_SendServerVerifyMessage(ss);
-        if (rv != SECSuccess)
-            goto loser;
-
-        ss->nextHandshake = ssl2_HandleMessage;
-        ssl_ReleaseRecvBufLock(ss);
-        rv = ssl2_TriggerNextMessage(ss);
-        return rv;
-    }
-    ss->nextHandshake = ssl2_HandleClientSessionKeyMessage;
-    ssl_ReleaseRecvBufLock(ss);
-    return SECSuccess;
-
-bad_client:
-    PORT_SetError(SSL_ERROR_BAD_CLIENT);
-/* FALLTHROUGH */
-
-loser:
-    if (gotXmitBufLock) {
-        ssl_ReleaseXmitBufLock(ss);
-        gotXmitBufLock = 0;
-    }
-    SSL_TRC(10, ("%d: SSL[%d]: server, wait for client-hello lossage",
-                 SSL_GETPID(), ss->fd));
-    ssl_ReleaseRecvBufLock(ss);
-    return SECFailure;
-}
-
-SECStatus
-ssl2_BeginServerHandshake(sslSocket *ss)
-{
-    SECStatus rv;
-    sslServerCerts *rsaAuth = ss->serverCerts + kt_rsa;
-
-    ss->sec.isServer = 1;
-    ssl_ChooseSessionIDProcs(&ss->sec);
-    ss->sec.sendSequence = 0;
-    ss->sec.rcvSequence = 0;
-
-    /* don't turn on SSL2 if we don't have an RSA key and cert */
-    if (!rsaAuth->serverKeyPair || !rsaAuth->SERVERKEY ||
-        !rsaAuth->serverCert) {
-        ss->opt.enableSSL2 = PR_FALSE;
-    }
-
-    if (!ss->cipherSpecs) {
-        rv = ssl2_ConstructCipherSpecs(ss);
-        if (rv != SECSuccess)
-            goto loser;
-    }
-
-    /* count the SSL2 and SSL3 enabled ciphers.
-     * if either is zero, clear the socket's enable for that protocol.
-     */
-    rv = ssl2_CheckConfigSanity(ss);
-    if (rv != SECSuccess)
-        goto loser;
-
-    /*
-    ** Generate connection-id. Always do this, even if things fail
-    ** immediately. This way the random number generator is always
-    ** rolling around, every time we get a connection.
-    */
-    PK11_GenerateRandom(ss->sec.ci.connectionID,
-                        sizeof(ss->sec.ci.connectionID));
-
-    ss->gs.recordLen = 0;
-    ss->handshake = ssl_GatherRecord1stHandshake;
-    ss->nextHandshake = ssl2_HandleClientHelloMessage;
-    return SECSuccess;
-
-loser:
-    return SECFailure;
-}
-
-/* This function doesn't really belong in this file.
-** It's here to keep AIX compilers from optimizing it away,
-** and not including it in the DSO.
-*/
-
-#include "nss.h"
-extern const char __nss_ssl_version[];
-
-PRBool
-NSSSSL_VersionCheck(const char *importedVersion)
-{
-#define NSS_VERSION_VARIABLE __nss_ssl_version
-#include "verref.h"
-
-    /*
-     * This is the secret handshake algorithm.
-     *
-     * This release has a simple version compatibility
-     * check algorithm.  This release is not backward
-     * compatible with previous major releases.  It is
-     * not compatible with future major, minor, or
-     * patch releases.
-     */
-    return NSS_VersionCheck(importedVersion);
-}
-
-const char *
-NSSSSL_GetVersion(void)
-{
-    return NSS_VERSION;
-}
diff --git a/net/third_party/nss/ssl/ssldef.c b/net/third_party/nss/ssl/ssldef.c
deleted file mode 100644
index 77a744cc..0000000
--- a/net/third_party/nss/ssl/ssldef.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * "Default" SSLSocket methods, used by sockets that do neither SSL nor socks.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "cert.h"
-#include "ssl.h"
-#include "sslimpl.h"
-
-#if defined(WIN32)
-#define MAP_ERROR(from, to) \
-    if (err == from) {      \
-        PORT_SetError(to);  \
-    }
-#define DEFINE_ERROR PRErrorCode err = PR_GetError();
-#else
-#define MAP_ERROR(from, to)
-#define DEFINE_ERROR
-#endif
-
-int
-ssl_DefConnect(sslSocket *ss, const PRNetAddr *sa)
-{
-    PRFileDesc *lower = ss->fd->lower;
-    int rv;
-
-    rv = lower->methods->connect(lower, sa, ss->cTimeout);
-    return rv;
-}
-
-int
-ssl_DefBind(sslSocket *ss, const PRNetAddr *addr)
-{
-    PRFileDesc *lower = ss->fd->lower;
-    int rv;
-
-    rv = lower->methods->bind(lower, addr);
-    return rv;
-}
-
-int
-ssl_DefListen(sslSocket *ss, int backlog)
-{
-    PRFileDesc *lower = ss->fd->lower;
-    int rv;
-
-    rv = lower->methods->listen(lower, backlog);
-    return rv;
-}
-
-int
-ssl_DefShutdown(sslSocket *ss, int how)
-{
-    PRFileDesc *lower = ss->fd->lower;
-    int rv;
-
-    rv = lower->methods->shutdown(lower, how);
-    return rv;
-}
-
-int
-ssl_DefRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
-{
-    PRFileDesc *lower = ss->fd->lower;
-    int rv;
-
-    rv = lower->methods->recv(lower, (void *)buf, len, flags, ss->rTimeout);
-    if (rv < 0) {
-        DEFINE_ERROR
-        MAP_ERROR(PR_SOCKET_SHUTDOWN_ERROR, PR_CONNECT_RESET_ERROR)
-    } else if (rv > len) {
-        PORT_Assert(rv <= len);
-        PORT_SetError(PR_BUFFER_OVERFLOW_ERROR);
-        rv = SECFailure;
-    }
-    return rv;
-}
-
-/* Default (unencrypted) send.
- * For blocking sockets, always returns len or SECFailure, no short writes.
- * For non-blocking sockets:
- *   Returns positive count if any data was written, else returns SECFailure.
- *   Short writes may occur.  Does not return SECWouldBlock.
- */
-int
-ssl_DefSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
-{
-    PRFileDesc *lower = ss->fd->lower;
-    int sent = 0;
-
-#if NSS_DISABLE_NAGLE_DELAYS
-    /* Although this is overkill, we disable Nagle delays completely for
-    ** SSL sockets.
-    */
-    if (ss->opt.useSecurity && !ss->delayDisabled) {
-        ssl_EnableNagleDelay(ss, PR_FALSE); /* ignore error */
-        ss->delayDisabled = 1;
-    }
-#endif
-    do {
-        int rv = lower->methods->send(lower, (const void *)(buf + sent),
-                                      len - sent, flags, ss->wTimeout);
-        if (rv < 0) {
-            PRErrorCode err = PR_GetError();
-            if (err == PR_WOULD_BLOCK_ERROR) {
-                ss->lastWriteBlocked = 1;
-                return sent ? sent : SECFailure;
-            }
-            ss->lastWriteBlocked = 0;
-            MAP_ERROR(PR_CONNECT_ABORTED_ERROR, PR_CONNECT_RESET_ERROR)
-            /* Loser */
-            return rv;
-        }
-        sent += rv;
-
-        if (IS_DTLS(ss) && (len > sent)) {
-            /* We got a partial write so just return it */
-            return sent;
-        }
-    } while (len > sent);
-    ss->lastWriteBlocked = 0;
-    return sent;
-}
-
-int
-ssl_DefRead(sslSocket *ss, unsigned char *buf, int len)
-{
-    PRFileDesc *lower = ss->fd->lower;
-    int rv;
-
-    rv = lower->methods->read(lower, (void *)buf, len);
-    if (rv < 0) {
-        DEFINE_ERROR
-        MAP_ERROR(PR_SOCKET_SHUTDOWN_ERROR, PR_CONNECT_RESET_ERROR)
-    }
-    return rv;
-}
-
-int
-ssl_DefWrite(sslSocket *ss, const unsigned char *buf, int len)
-{
-    PRFileDesc *lower = ss->fd->lower;
-    int sent = 0;
-
-    do {
-        int rv = lower->methods->write(lower, (const void *)(buf + sent),
-                                       len - sent);
-        if (rv < 0) {
-            PRErrorCode err = PR_GetError();
-            if (err == PR_WOULD_BLOCK_ERROR) {
-                ss->lastWriteBlocked = 1;
-                return sent ? sent : SECFailure;
-            }
-            ss->lastWriteBlocked = 0;
-            MAP_ERROR(PR_CONNECT_ABORTED_ERROR, PR_CONNECT_RESET_ERROR)
-            /* Loser */
-            return rv;
-        }
-        sent += rv;
-    } while (len > sent);
-    ss->lastWriteBlocked = 0;
-    return sent;
-}
-
-int
-ssl_DefGetpeername(sslSocket *ss, PRNetAddr *name)
-{
-    PRFileDesc *lower = ss->fd->lower;
-    int rv;
-
-    rv = lower->methods->getpeername(lower, name);
-    return rv;
-}
-
-int
-ssl_DefGetsockname(sslSocket *ss, PRNetAddr *name)
-{
-    PRFileDesc *lower = ss->fd->lower;
-    int rv;
-
-    rv = lower->methods->getsockname(lower, name);
-    return rv;
-}
-
-int
-ssl_DefClose(sslSocket *ss)
-{
-    PRFileDesc *fd;
-    PRFileDesc *popped;
-    int rv;
-
-    fd = ss->fd;
-
-    /* First, remove the SSL layer PRFileDesc from the socket's stack,
-    ** then invoke the SSL layer's PRFileDesc destructor.
-    ** This must happen before the next layer down is closed.
-    */
-    PORT_Assert(fd->higher == NULL);
-    if (fd->higher) {
-        PORT_SetError(PR_BAD_DESCRIPTOR_ERROR);
-        return SECFailure;
-    }
-    ss->fd = NULL;
-
-    /* PR_PopIOLayer will swap the contents of the top two PRFileDescs on
-    ** the stack, and then remove the second one.  This way, the address
-    ** of the PRFileDesc on the top of the stack doesn't change.
-    */
-    popped = PR_PopIOLayer(fd, PR_TOP_IO_LAYER);
-    popped->dtor(popped);
-
-    /* fd is now the PRFileDesc for the next layer down.
-    ** Now close the underlying socket.
-    */
-    rv = fd->methods->close(fd);
-
-    ssl_FreeSocket(ss);
-
-    SSL_TRC(5, ("%d: SSL[%d]: closing, rv=%d errno=%d",
-                SSL_GETPID(), fd, rv, PORT_GetError()));
-    return rv;
-}
diff --git a/net/third_party/nss/ssl/sslenum.c b/net/third_party/nss/ssl/sslenum.c
deleted file mode 100644
index d362b74..0000000
--- a/net/third_party/nss/ssl/sslenum.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Table enumerating all implemented cipher suites
- * Part of public API.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "ssl.h"
-#include "sslproto.h"
-
-/*
- * The ordering of cipher suites in this table must match the ordering in
- * the cipherSuites table in ssl3con.c.
- *
- * If new ECC cipher suites are added, also update the ssl3CipherSuite arrays
- * in ssl3ecc.c.
- *
- * Finally, update the ssl_V3_SUITES_IMPLEMENTED macro in sslimpl.h.
- *
- * The ordering is as follows:
- *    * No-encryption cipher suites last
- *    * Export/weak/obsolete cipher suites before no-encryption cipher suites
- *    * Order by key exchange algorithm: ECDHE, then DHE, then ECDH, RSA.
- *    * Within key agreement sections, order by symmetric encryption algorithm:
- *      AES-128, then Camellia-128, then AES-256, then Camellia-256, then SEED,
- *      then FIPS-3DES, then 3DES, then RC4. AES is commonly accepted as a
- *      strong cipher internationally, and is often hardware-accelerated.
- *      Camellia also has wide international support across standards
- *      organizations. SEED is only recommended by the Korean government. 3DES
- *      only provides 112 bits of security. RC4 is now deprecated or forbidden
- *      by many standards organizations.
- *    * Within symmetric algorithm sections, order by message authentication
- *      algorithm: GCM, then HMAC-SHA1, then HMAC-SHA256, then HMAC-MD5.
- *    * Within message authentication algorithm sections, order by asymmetric
- *      signature algorithm: ECDSA, then RSA, then DSS.
- *
- * Exception: Because some servers ignore the high-order byte of the cipher
- * suite ID, we must be careful about adding cipher suites with IDs larger
- * than 0x00ff; see bug 946147. For these broken servers, the first four cipher
- * suites, with the MSB zeroed, look like:
- *      TLS_KRB5_EXPORT_WITH_RC4_40_MD5 { 0x00,0x2B }
- *      TLS_RSA_WITH_AES_128_CBC_SHA { 0x00,0x2F }
- *      TLS_RSA_WITH_3DES_EDE_CBC_SHA { 0x00,0x0A }
- *      TLS_RSA_WITH_DES_CBC_SHA { 0x00,0x09 }
- * The broken server only supports the third and fourth ones and will select
- * the third one.
- */
-const PRUint16 SSL_ImplementedCiphers[] = {
-#ifndef NSS_DISABLE_ECC
-    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
-    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-    TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
-    TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-    /* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA must appear before
-     * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA to work around bug 946147.
-     */
-    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
-    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
-    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
-    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
-    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
-    TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
-    TLS_ECDHE_RSA_WITH_RC4_128_SHA,
-#endif /* NSS_DISABLE_ECC */
-
-    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
-    TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-    TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,
-    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
-    TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
-    TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
-    TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
-    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
-    TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
-    TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
-    TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
-    TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
-    TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
-    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
-    TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
-    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
-    TLS_DHE_DSS_WITH_RC4_128_SHA,
-
-#ifndef NSS_DISABLE_ECC
-    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
-    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
-    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
-    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
-    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
-    TLS_ECDH_RSA_WITH_RC4_128_SHA,
-#endif /* NSS_DISABLE_ECC */
-
-    TLS_RSA_WITH_AES_128_GCM_SHA256,
-    TLS_RSA_WITH_AES_128_CBC_SHA,
-    TLS_RSA_WITH_AES_128_CBC_SHA256,
-    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
-    TLS_RSA_WITH_AES_256_CBC_SHA,
-    TLS_RSA_WITH_AES_256_CBC_SHA256,
-    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
-    TLS_RSA_WITH_SEED_CBC_SHA,
-    SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,
-    TLS_RSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_RSA_WITH_RC4_128_SHA,
-    TLS_RSA_WITH_RC4_128_MD5,
-
-    /* 56-bit DES "domestic" cipher suites */
-    TLS_DHE_RSA_WITH_DES_CBC_SHA,
-    TLS_DHE_DSS_WITH_DES_CBC_SHA,
-    SSL_RSA_FIPS_WITH_DES_CBC_SHA,
-    TLS_RSA_WITH_DES_CBC_SHA,
-
-    /* export ciphersuites with 1024-bit public key exchange keys */
-    TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,
-    TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,
-
-    /* export ciphersuites with 512-bit public key exchange keys */
-    TLS_RSA_EXPORT_WITH_RC4_40_MD5,
-    TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
-
-/* ciphersuites with no encryption */
-#ifndef NSS_DISABLE_ECC
-    TLS_ECDHE_ECDSA_WITH_NULL_SHA,
-    TLS_ECDHE_RSA_WITH_NULL_SHA,
-    TLS_ECDH_RSA_WITH_NULL_SHA,
-    TLS_ECDH_ECDSA_WITH_NULL_SHA,
-#endif /* NSS_DISABLE_ECC */
-    TLS_RSA_WITH_NULL_SHA,
-    TLS_RSA_WITH_NULL_SHA256,
-    TLS_RSA_WITH_NULL_MD5,
-
-    /* SSL2 cipher suites. */
-    SSL_EN_RC4_128_WITH_MD5,
-    SSL_EN_RC2_128_CBC_WITH_MD5,
-    SSL_EN_DES_192_EDE3_CBC_WITH_MD5, /* actually 112, not 192 */
-    SSL_EN_DES_64_CBC_WITH_MD5,
-    SSL_EN_RC4_128_EXPORT40_WITH_MD5,
-    SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5,
-
-    0
-
-};
-
-const PRUint16 SSL_NumImplementedCiphers =
-    (sizeof SSL_ImplementedCiphers) / (sizeof SSL_ImplementedCiphers[0]) - 1;
-
-const PRUint16*
-SSL_GetImplementedCiphers(void)
-{
-    return SSL_ImplementedCiphers;
-}
-
-PRUint16
-SSL_GetNumImplementedCiphers(void)
-{
-    return SSL_NumImplementedCiphers;
-}
diff --git a/net/third_party/nss/ssl/sslerr.c b/net/third_party/nss/ssl/sslerr.c
deleted file mode 100644
index edb9412..0000000
--- a/net/third_party/nss/ssl/sslerr.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Function to set error code only when meaningful error has not already
- * been set.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "prerror.h"
-#include "secerr.h"
-#include "sslerr.h"
-#include "seccomon.h"
-
-/* look at the current value of PR_GetError, and evaluate it to see
- * if it is meaningful or meaningless (out of context).
- * If it is meaningless, replace it with the hiLevelError.
- * Returns the chosen error value.
- */
-int
-ssl_MapLowLevelError(int hiLevelError)
-{
-    int oldErr = PORT_GetError();
-
-    switch (oldErr) {
-
-        case 0:
-        case PR_IO_ERROR:
-        case SEC_ERROR_IO:
-        case SEC_ERROR_BAD_DATA:
-        case SEC_ERROR_LIBRARY_FAILURE:
-        case SEC_ERROR_EXTENSION_NOT_FOUND:
-        case SSL_ERROR_BAD_CLIENT:
-        case SSL_ERROR_BAD_SERVER:
-        case SSL_ERROR_SESSION_NOT_FOUND:
-            PORT_SetError(hiLevelError);
-            return hiLevelError;
-
-        default: /* leave the majority of error codes alone. */
-            return oldErr;
-    }
-}
diff --git a/net/third_party/nss/ssl/sslerr.h b/net/third_party/nss/ssl/sslerr.h
deleted file mode 100644
index 299951c..0000000
--- a/net/third_party/nss/ssl/sslerr.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Enumeration of all SSL-specific error codes.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#ifndef __SSL_ERR_H_
-#define __SSL_ERR_H_
-
-/* clang-format off */
-
-#define SSL_ERROR_BASE                          (-0x3000)
-#define SSL_ERROR_LIMIT                         (SSL_ERROR_BASE + 1000)
-
-#define IS_SSL_ERROR(code) \
-    (((code) >= SSL_ERROR_BASE) && ((code) < SSL_ERROR_LIMIT))
-
-#ifndef NO_SECURITY_ERROR_ENUM
-typedef enum {
-    SSL_ERROR_EXPORT_ONLY_SERVER            = (SSL_ERROR_BASE +  0),
-    SSL_ERROR_US_ONLY_SERVER                = (SSL_ERROR_BASE +  1),
-    SSL_ERROR_NO_CYPHER_OVERLAP             = (SSL_ERROR_BASE +  2),
-    /*
-     * Received an alert reporting what we did wrong.  (more alerts below)
-     */
-    SSL_ERROR_NO_CERTIFICATE /*_ALERT */    = (SSL_ERROR_BASE +  3),
-    SSL_ERROR_BAD_CERTIFICATE               = (SSL_ERROR_BASE +  4),
-    SSL_ERROR_UNUSED_5                      = (SSL_ERROR_BASE +  5),
-                                            /* error 5 is obsolete */
-    SSL_ERROR_BAD_CLIENT                    = (SSL_ERROR_BASE +  6),
-    SSL_ERROR_BAD_SERVER                    = (SSL_ERROR_BASE +  7),
-    SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE  = (SSL_ERROR_BASE +  8),
-    SSL_ERROR_UNSUPPORTED_VERSION           = (SSL_ERROR_BASE +  9),
-    SSL_ERROR_UNUSED_10                     = (SSL_ERROR_BASE + 10),
-                                            /* error 10 is obsolete */
-    SSL_ERROR_WRONG_CERTIFICATE             = (SSL_ERROR_BASE + 11),
-    SSL_ERROR_BAD_CERT_DOMAIN               = (SSL_ERROR_BASE + 12),
-    SSL_ERROR_POST_WARNING                  = (SSL_ERROR_BASE + 13),
-    SSL_ERROR_SSL2_DISABLED                 = (SSL_ERROR_BASE + 14),
-    SSL_ERROR_BAD_MAC_READ                  = (SSL_ERROR_BASE + 15),
-    /*
-     * Received an alert reporting what we did wrong.
-     * (two more alerts above, and many more below)
-     */
-    SSL_ERROR_BAD_MAC_ALERT                 = (SSL_ERROR_BASE + 16),
-    SSL_ERROR_BAD_CERT_ALERT                = (SSL_ERROR_BASE + 17),
-    SSL_ERROR_REVOKED_CERT_ALERT            = (SSL_ERROR_BASE + 18),
-    SSL_ERROR_EXPIRED_CERT_ALERT            = (SSL_ERROR_BASE + 19),
-
-    SSL_ERROR_SSL_DISABLED                  = (SSL_ERROR_BASE + 20),
-    SSL_ERROR_FORTEZZA_PQG                  = (SSL_ERROR_BASE + 21),
-    SSL_ERROR_UNKNOWN_CIPHER_SUITE          = (SSL_ERROR_BASE + 22),
-    SSL_ERROR_NO_CIPHERS_SUPPORTED          = (SSL_ERROR_BASE + 23),
-    SSL_ERROR_BAD_BLOCK_PADDING             = (SSL_ERROR_BASE + 24),
-    SSL_ERROR_RX_RECORD_TOO_LONG            = (SSL_ERROR_BASE + 25),
-    SSL_ERROR_TX_RECORD_TOO_LONG            = (SSL_ERROR_BASE + 26),
-    /*
-     * Received a malformed (too long or short) SSL handshake.
-     */
-    SSL_ERROR_RX_MALFORMED_HELLO_REQUEST    = (SSL_ERROR_BASE + 27),
-    SSL_ERROR_RX_MALFORMED_CLIENT_HELLO     = (SSL_ERROR_BASE + 28),
-    SSL_ERROR_RX_MALFORMED_SERVER_HELLO     = (SSL_ERROR_BASE + 29),
-    SSL_ERROR_RX_MALFORMED_CERTIFICATE      = (SSL_ERROR_BASE + 30),
-    SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH  = (SSL_ERROR_BASE + 31),
-    SSL_ERROR_RX_MALFORMED_CERT_REQUEST     = (SSL_ERROR_BASE + 32),
-    SSL_ERROR_RX_MALFORMED_HELLO_DONE       = (SSL_ERROR_BASE + 33),
-    SSL_ERROR_RX_MALFORMED_CERT_VERIFY      = (SSL_ERROR_BASE + 34),
-    SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH  = (SSL_ERROR_BASE + 35),
-    SSL_ERROR_RX_MALFORMED_FINISHED         = (SSL_ERROR_BASE + 36),
-    /*
-     * Received a malformed (too long or short) SSL record.
-     */
-    SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER    = (SSL_ERROR_BASE + 37),
-    SSL_ERROR_RX_MALFORMED_ALERT            = (SSL_ERROR_BASE + 38),
-    SSL_ERROR_RX_MALFORMED_HANDSHAKE        = (SSL_ERROR_BASE + 39),
-    SSL_ERROR_RX_MALFORMED_APPLICATION_DATA = (SSL_ERROR_BASE + 40),
-    /*
-     * Received an SSL handshake that was inappropriate for the state we're in.
-     * E.g. Server received message from server, or wrong state in state machine.
-     */
-    SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST   = (SSL_ERROR_BASE + 41),
-    SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO    = (SSL_ERROR_BASE + 42),
-    SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO    = (SSL_ERROR_BASE + 43),
-    SSL_ERROR_RX_UNEXPECTED_CERTIFICATE     = (SSL_ERROR_BASE + 44),
-    SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH = (SSL_ERROR_BASE + 45),
-    SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST    = (SSL_ERROR_BASE + 46),
-    SSL_ERROR_RX_UNEXPECTED_HELLO_DONE      = (SSL_ERROR_BASE + 47),
-    SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY     = (SSL_ERROR_BASE + 48),
-    SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH = (SSL_ERROR_BASE + 49),
-    SSL_ERROR_RX_UNEXPECTED_FINISHED        = (SSL_ERROR_BASE + 50),
-    /*
-     * Received an SSL record that was inappropriate for the state we're in.
-     */
-    SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER   = (SSL_ERROR_BASE + 51),
-    SSL_ERROR_RX_UNEXPECTED_ALERT           = (SSL_ERROR_BASE + 52),
-    SSL_ERROR_RX_UNEXPECTED_HANDSHAKE       = (SSL_ERROR_BASE + 53),
-    SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA = (SSL_ERROR_BASE + 54),
-    /*
-     * Received record/message with unknown discriminant.
-     */
-    SSL_ERROR_RX_UNKNOWN_RECORD_TYPE        = (SSL_ERROR_BASE + 55),
-    SSL_ERROR_RX_UNKNOWN_HANDSHAKE          = (SSL_ERROR_BASE + 56),
-    SSL_ERROR_RX_UNKNOWN_ALERT              = (SSL_ERROR_BASE + 57),
-    /*
-     * Received an alert reporting what we did wrong.  (more alerts above)
-     */
-    SSL_ERROR_CLOSE_NOTIFY_ALERT            = (SSL_ERROR_BASE + 58),
-    SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT    = (SSL_ERROR_BASE + 59),
-    SSL_ERROR_DECOMPRESSION_FAILURE_ALERT   = (SSL_ERROR_BASE + 60),
-    SSL_ERROR_HANDSHAKE_FAILURE_ALERT       = (SSL_ERROR_BASE + 61),
-    SSL_ERROR_ILLEGAL_PARAMETER_ALERT       = (SSL_ERROR_BASE + 62),
-    SSL_ERROR_UNSUPPORTED_CERT_ALERT        = (SSL_ERROR_BASE + 63),
-    SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT     = (SSL_ERROR_BASE + 64),
-
-    SSL_ERROR_GENERATE_RANDOM_FAILURE       = (SSL_ERROR_BASE + 65),
-    SSL_ERROR_SIGN_HASHES_FAILURE           = (SSL_ERROR_BASE + 66),
-    SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE    = (SSL_ERROR_BASE + 67),
-    SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE   = (SSL_ERROR_BASE + 68),
-    SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE   = (SSL_ERROR_BASE + 69),
-
-    SSL_ERROR_ENCRYPTION_FAILURE            = (SSL_ERROR_BASE + 70),
-    SSL_ERROR_DECRYPTION_FAILURE            = (SSL_ERROR_BASE + 71), /* don't use */
-    SSL_ERROR_SOCKET_WRITE_FAILURE          = (SSL_ERROR_BASE + 72),
-
-    SSL_ERROR_MD5_DIGEST_FAILURE            = (SSL_ERROR_BASE + 73),
-    SSL_ERROR_SHA_DIGEST_FAILURE            = (SSL_ERROR_BASE + 74),
-    SSL_ERROR_MAC_COMPUTATION_FAILURE       = (SSL_ERROR_BASE + 75),
-    SSL_ERROR_SYM_KEY_CONTEXT_FAILURE       = (SSL_ERROR_BASE + 76),
-    SSL_ERROR_SYM_KEY_UNWRAP_FAILURE        = (SSL_ERROR_BASE + 77),
-    SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED   = (SSL_ERROR_BASE + 78),
-    SSL_ERROR_IV_PARAM_FAILURE              = (SSL_ERROR_BASE + 79),
-    SSL_ERROR_INIT_CIPHER_SUITE_FAILURE     = (SSL_ERROR_BASE + 80),
-    SSL_ERROR_SESSION_KEY_GEN_FAILURE       = (SSL_ERROR_BASE + 81),
-    SSL_ERROR_NO_SERVER_KEY_FOR_ALG         = (SSL_ERROR_BASE + 82),
-    SSL_ERROR_TOKEN_INSERTION_REMOVAL       = (SSL_ERROR_BASE + 83),
-    SSL_ERROR_TOKEN_SLOT_NOT_FOUND          = (SSL_ERROR_BASE + 84),
-    SSL_ERROR_NO_COMPRESSION_OVERLAP        = (SSL_ERROR_BASE + 85),
-    SSL_ERROR_HANDSHAKE_NOT_COMPLETED       = (SSL_ERROR_BASE + 86),
-    SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE      = (SSL_ERROR_BASE + 87),
-    SSL_ERROR_CERT_KEA_MISMATCH             = (SSL_ERROR_BASE + 88),
-    /* SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA became obsolete in NSS 3.14. */
-    SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA      = (SSL_ERROR_BASE + 89),
-    SSL_ERROR_SESSION_NOT_FOUND             = (SSL_ERROR_BASE + 90),
-
-    SSL_ERROR_DECRYPTION_FAILED_ALERT       = (SSL_ERROR_BASE + 91),
-    SSL_ERROR_RECORD_OVERFLOW_ALERT         = (SSL_ERROR_BASE + 92),
-    SSL_ERROR_UNKNOWN_CA_ALERT              = (SSL_ERROR_BASE + 93),
-    SSL_ERROR_ACCESS_DENIED_ALERT           = (SSL_ERROR_BASE + 94),
-    SSL_ERROR_DECODE_ERROR_ALERT            = (SSL_ERROR_BASE + 95),
-    SSL_ERROR_DECRYPT_ERROR_ALERT           = (SSL_ERROR_BASE + 96),
-    SSL_ERROR_EXPORT_RESTRICTION_ALERT      = (SSL_ERROR_BASE + 97),
-    SSL_ERROR_PROTOCOL_VERSION_ALERT        = (SSL_ERROR_BASE + 98),
-    SSL_ERROR_INSUFFICIENT_SECURITY_ALERT   = (SSL_ERROR_BASE + 99),
-    SSL_ERROR_INTERNAL_ERROR_ALERT          = (SSL_ERROR_BASE + 100),
-    SSL_ERROR_USER_CANCELED_ALERT           = (SSL_ERROR_BASE + 101),
-    SSL_ERROR_NO_RENEGOTIATION_ALERT        = (SSL_ERROR_BASE + 102),
-
-    SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED   = (SSL_ERROR_BASE + 103),
-
-    SSL_ERROR_UNSUPPORTED_EXTENSION_ALERT   = (SSL_ERROR_BASE + 104),
-    SSL_ERROR_CERTIFICATE_UNOBTAINABLE_ALERT = (SSL_ERROR_BASE + 105),
-    SSL_ERROR_UNRECOGNIZED_NAME_ALERT       = (SSL_ERROR_BASE + 106),
-    SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT = (SSL_ERROR_BASE + 107),
-    SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT     = (SSL_ERROR_BASE + 108),
-
-    SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET = (SSL_ERROR_BASE + 109),
-    SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET = (SSL_ERROR_BASE + 110),
-
-    SSL_ERROR_DECOMPRESSION_FAILURE         = (SSL_ERROR_BASE + 111),
-    SSL_ERROR_RENEGOTIATION_NOT_ALLOWED     = (SSL_ERROR_BASE + 112),
-    SSL_ERROR_UNSAFE_NEGOTIATION            = (SSL_ERROR_BASE + 113),
-
-    SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD = (SSL_ERROR_BASE + 114),
-
-    SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY  = (SSL_ERROR_BASE + 115),
-
-    SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID    = (SSL_ERROR_BASE + 116),
-
-    SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2 = (SSL_ERROR_BASE + 117),
-    SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS = (SSL_ERROR_BASE + 118),
-    SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_CLIENTS = (SSL_ERROR_BASE + 119),
-
-    SSL_ERROR_INVALID_VERSION_RANGE         = (SSL_ERROR_BASE + 120),
-    SSL_ERROR_CIPHER_DISALLOWED_FOR_VERSION = (SSL_ERROR_BASE + 121),
-
-    SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST = (SSL_ERROR_BASE + 122),
-    SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST = (SSL_ERROR_BASE + 123),
-
-    SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION = (SSL_ERROR_BASE + 124),
-
-    SSL_ERROR_RX_UNEXPECTED_CERT_STATUS     = (SSL_ERROR_BASE + 125),
-
-    SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM    = (SSL_ERROR_BASE + 126),
-    SSL_ERROR_DIGEST_FAILURE                = (SSL_ERROR_BASE + 127),
-    SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 128),
-
-    SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK     = (SSL_ERROR_BASE + 129),
-    SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL     = (SSL_ERROR_BASE + 130),
-
-    SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT  = (SSL_ERROR_BASE + 131),
-
-    SSL_ERROR_WEAK_SERVER_CERT_KEY          = (SSL_ERROR_BASE + 132),
-
-    SSL_ERROR_RX_SHORT_DTLS_READ            = (SSL_ERROR_BASE + 133),
-
-    SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 134),
-    SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 135),
-
-    SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET = (SSL_ERROR_BASE + 136),
-    SSL_ERROR_UNEXPECTED_EXTENDED_MASTER_SECRET = (SSL_ERROR_BASE + 137),
-
-    SSL_ERROR_RX_MALFORMED_KEY_SHARE        = (SSL_ERROR_BASE + 138),
-    SSL_ERROR_MISSING_KEY_SHARE             = (SSL_ERROR_BASE + 139),
-    SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE  = (SSL_ERROR_BASE + 140),
-    SSL_ERROR_RX_MALFORMED_DHE_KEY_SHARE    = (SSL_ERROR_BASE + 141),
-
-    SSL_ERROR_RX_UNEXPECTED_ENCRYPTED_EXTENSIONS = (SSL_ERROR_BASE + 142),
-    SSL_ERROR_MISSING_EXTENSION_ALERT       = (SSL_ERROR_BASE + 143),
-
-    SSL_ERROR_KEY_EXCHANGE_FAILURE          = (SSL_ERROR_BASE + 144),
-    SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION = (SSL_ERROR_BASE + 145),
-    SSL_ERROR_RX_MALFORMED_ENCRYPTED_EXTENSIONS = (SSL_ERROR_BASE + 146),
-
- SSL_ERROR_BAD_CHANNEL_ID_DATA           = (SSL_ERROR_BASE + 147),
- SSL_ERROR_INVALID_CHANNEL_ID_KEY        = (SSL_ERROR_BASE + 148),
- SSL_ERROR_GET_CHANNEL_ID_FAILED         = (SSL_ERROR_BASE + 149),
-
-    SSL_ERROR_END_OF_LIST   /* let the c compiler determine the value of this. */
-} SSLErrorCodes;
-#endif /* NO_SECURITY_ERROR_ENUM */
-
-/* clang-format on */
-
-#endif /* __SSL_ERR_H_ */
diff --git a/net/third_party/nss/ssl/sslerrstrs.c b/net/third_party/nss/ssl/sslerrstrs.c
deleted file mode 100644
index 4e3db6d..0000000
--- a/net/third_party/nss/ssl/sslerrstrs.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "prerror.h"
-#include "sslerr.h"
-#include "prinit.h"
-#include "nssutil.h"
-#include "ssl.h"
-
-#define ER3(name, value, str) { #name, str },
-
-static const struct PRErrorMessage ssltext[] = {
-#include "SSLerrs.h"
-    { 0, 0 }
-};
-
-static const struct PRErrorTable ssl_et = {
-    ssltext, "sslerr", SSL_ERROR_BASE,
-    (sizeof ssltext) / (sizeof ssltext[0])
-};
-
-static PRStatus
-ssl_InitializePRErrorTableOnce(void)
-{
-    return PR_ErrorInstallTable(&ssl_et);
-}
-
-static PRCallOnceType once;
-
-SECStatus
-ssl_InitializePRErrorTable(void)
-{
-    return (PR_SUCCESS == PR_CallOnce(&once, ssl_InitializePRErrorTableOnce))
-               ? SECSuccess
-               : SECFailure;
-}
diff --git a/net/third_party/nss/ssl/sslgathr.c b/net/third_party/nss/ssl/sslgathr.c
deleted file mode 100644
index 48d615e..0000000
--- a/net/third_party/nss/ssl/sslgathr.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Gather (Read) entire SSL2 records from socket into buffer.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "cert.h"
-#include "ssl.h"
-#include "sslimpl.h"
-#include "sslproto.h"
-
-/* Forward static declarations */
-static SECStatus ssl2_HandleV3HandshakeRecord(sslSocket *ss);
-
-/*
-** Gather a single record of data from the receiving stream. This code
-** first gathers the header (2 or 3 bytes long depending on the value of
-** the most significant bit in the first byte) then gathers up the data
-** for the record into gs->buf. This code handles non-blocking I/O
-** and is to be called multiple times until ss->sec.recordLen != 0.
-** This function decrypts the gathered record in place, in gs_buf.
- *
- * Caller must hold RecvBufLock.
- *
- * Returns +1 when it has gathered a complete SSLV2 record.
- * Returns  0 if it hits EOF.
- * Returns -1 (SECFailure)    on any error
- * Returns -2 (SECWouldBlock) when it gathers an SSL v3 client hello header.
-**
-** The SSL2 Gather State machine has 4 states:
-** GS_INIT   - Done reading in previous record.  Haven't begun to read in
-**             next record.  When ssl2_GatherData is called with the machine
-**             in this state, the machine will attempt to read the first 3
-**             bytes of the SSL2 record header, and will advance the state
-**             to GS_HEADER.
-**
-** GS_HEADER - The machine is in this state while waiting for the completion
-**             of the first 3 bytes of the SSL2 record.  When complete, the
-**             machine will compute the remaining unread length of this record
-**             and will initiate a read of that many bytes.  The machine will
-**             advance to one of two states, depending on whether the record
-**             is encrypted (GS_MAC), or unencrypted (GS_DATA).
-**
-** GS_MAC    - The machine is in this state while waiting for the remainder
-**             of the SSL2 record to be read in.  When the read is completed,
-**             the machine checks the record for valid length, decrypts it,
-**             and checks and discards the MAC, then advances to GS_INIT.
-**
-** GS_DATA   - The machine is in this state while waiting for the remainder
-**             of the unencrypted SSL2 record to be read in.  Upon completion,
-**             the machine advances to the GS_INIT state and returns the data.
-*/
-int
-ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags)
-{
-    unsigned char *bp;
-    unsigned char *pBuf;
-    int nb, err, rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-
-    if (gs->state == GS_INIT) {
-        /* Initialize gathering engine */
-        gs->state = GS_HEADER;
-        gs->remainder = 3;
-        gs->count = 3;
-        gs->offset = 0;
-        gs->recordLen = 0;
-        gs->recordPadding = 0;
-        gs->hdr[2] = 0;
-
-        gs->writeOffset = 0;
-        gs->readOffset = 0;
-    }
-    if (gs->encrypted) {
-        PORT_Assert(ss->sec.hash != 0);
-    }
-
-    pBuf = gs->buf.buf;
-    for (;;) {
-        SSL_TRC(30, ("%d: SSL[%d]: gather state %d (need %d more)",
-                     SSL_GETPID(), ss->fd, gs->state, gs->remainder));
-        bp = ((gs->state != GS_HEADER) ? pBuf : gs->hdr) + gs->offset;
-        nb = ssl_DefRecv(ss, bp, gs->remainder, flags);
-        if (nb > 0) {
-            PRINT_BUF(60, (ss, "raw gather data:", bp, nb));
-        }
-        if (nb == 0) {
-            /* EOF */
-            SSL_TRC(30, ("%d: SSL[%d]: EOF", SSL_GETPID(), ss->fd));
-            rv = 0;
-            break;
-        }
-        if (nb < 0) {
-            SSL_DBG(("%d: SSL[%d]: recv error %d", SSL_GETPID(), ss->fd,
-                     PR_GetError()));
-            rv = SECFailure;
-            break;
-        }
-
-        gs->offset += nb;
-        gs->remainder -= nb;
-
-        if (gs->remainder > 0) {
-            continue;
-        }
-
-        /* Probably finished this piece */
-        switch (gs->state) {
-            case GS_HEADER:
-                if (!SSL3_ALL_VERSIONS_DISABLED(&ss->vrange) && !ss->firstHsDone) {
-
-                    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-                    /* If this looks like an SSL3 handshake record,
-                    ** and we're expecting an SSL2 Hello message from our peer,
-                    ** handle it here.
-                    */
-                    if (gs->hdr[0] == content_handshake) {
-                        if ((ss->nextHandshake == ssl2_HandleClientHelloMessage) ||
-                            (ss->nextHandshake == ssl2_HandleServerHelloMessage)) {
-                            rv = ssl2_HandleV3HandshakeRecord(ss);
-                            if (rv == SECFailure) {
-                                return SECFailure;
-                            }
-                        }
-                        /* XXX_1    The call stack to here is:
-                         * ssl_Do1stHandshake -> ssl_GatherRecord1stHandshake ->
-                         *          ssl2_GatherRecord -> here.
-                         * We want to return all the way out to ssl_Do1stHandshake,
-                         * and have it call ssl_GatherRecord1stHandshake again.
-                         * ssl_GatherRecord1stHandshake will call
-                         * ssl3_GatherCompleteHandshake when it is called again.
-                         *
-                         * Returning SECWouldBlock here causes
-                         * ssl_GatherRecord1stHandshake to return without clearing
-                         * ss->handshake, ensuring that ssl_Do1stHandshake will
-                         * call it again immediately.
-                         *
-                         * If we return 1 here, ssl_GatherRecord1stHandshake will
-                         * clear ss->handshake before returning, and thus will not
-                         * be called again by ssl_Do1stHandshake.
-                         */
-                        return SECWouldBlock;
-                    } else if (gs->hdr[0] == content_alert) {
-                        if (ss->nextHandshake == ssl2_HandleServerHelloMessage) {
-                            /* XXX This is a hack.  We're assuming that any failure
-                             * XXX on the client hello is a failure to match
-                             * XXX ciphers.
-                             */
-                            PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
-                            return SECFailure;
-                        }
-                    }
-                }
-
-                /* we've got the first 3 bytes.  The header may be two or three. */
-                if (gs->hdr[0] & 0x80) {
-                    /* This record has a 2-byte header, and no padding */
-                    gs->count = ((gs->hdr[0] & 0x7f) << 8) | gs->hdr[1];
-                    gs->recordPadding = 0;
-                } else {
-                    /* This record has a 3-byte header that is all read in now. */
-                    gs->count = ((gs->hdr[0] & 0x3f) << 8) | gs->hdr[1];
-                    /*  is_escape =  (gs->hdr[0] & 0x40) != 0; */
-                    gs->recordPadding = gs->hdr[2];
-                }
-                if (!gs->count) {
-                    PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
-                    goto cleanup;
-                }
-
-                if (gs->count > gs->buf.space) {
-                    err = sslBuffer_Grow(&gs->buf, gs->count);
-                    if (err) {
-                        return err;
-                    }
-                    pBuf = gs->buf.buf;
-                }
-
-                if (gs->hdr[0] & 0x80) {
-                    /* we've already read in the first byte of the body.
-                    ** Put it into the buffer.
-                    */
-                    pBuf[0] = gs->hdr[2];
-                    gs->offset = 1;
-                    gs->remainder = gs->count - 1;
-                } else {
-                    gs->offset = 0;
-                    gs->remainder = gs->count;
-                }
-
-                if (gs->encrypted) {
-                    gs->state = GS_MAC;
-                    gs->recordLen = gs->count - gs->recordPadding -
-                                    ss->sec.hash->length;
-                } else {
-                    gs->state = GS_DATA;
-                    gs->recordLen = gs->count;
-                }
-
-                break;
-
-            case GS_MAC:
-                /* Have read in entire rest of the ciphertext.
-                ** Check for valid length.
-                ** Decrypt it.
-                ** Check the MAC.
-                */
-                PORT_Assert(gs->encrypted);
-
-                {
-                    unsigned int macLen;
-                    int nout;
-                    unsigned char mac[SSL_MAX_MAC_BYTES];
-
-                    ssl_GetSpecReadLock(ss); /**********************************/
-
-                    /* If this is a stream cipher, blockSize will be 1,
-                     * and this test will always be false.
-                     * If this is a block cipher, this will detect records
-                     * that are not a multiple of the blocksize in length.
-                     */
-                    if (gs->count & (ss->sec.blockSize - 1)) {
-                        /* This is an error. Sender is misbehaving */
-                        SSL_DBG(("%d: SSL[%d]: sender, count=%d blockSize=%d",
-                                 SSL_GETPID(), ss->fd, gs->count,
-                                 ss->sec.blockSize));
-                        PORT_SetError(SSL_ERROR_BAD_BLOCK_PADDING);
-                        rv = SECFailure;
-                        goto spec_locked_done;
-                    }
-                    PORT_Assert(gs->count == gs->offset);
-
-                    if (gs->offset == 0) {
-                        rv = 0; /* means EOF. */
-                        goto spec_locked_done;
-                    }
-
-                    /* Decrypt the portion of data that we just received.
-                    ** Decrypt it in place.
-                    */
-                    rv = (*ss->sec.dec)(ss->sec.readcx, pBuf, &nout, gs->offset,
-                                        pBuf, gs->offset);
-                    if (rv != SECSuccess) {
-                        goto spec_locked_done;
-                    }
-
-                    /* Have read in all the MAC portion of record
-                    **
-                    ** Prepare MAC by resetting it and feeding it the shared secret
-                    */
-                    macLen = ss->sec.hash->length;
-                    if (gs->offset >= macLen) {
-                        PRUint32 sequenceNumber = ss->sec.rcvSequence++;
-                        unsigned char seq[4];
-
-                        seq[0] = (unsigned char)(sequenceNumber >> 24);
-                        seq[1] = (unsigned char)(sequenceNumber >> 16);
-                        seq[2] = (unsigned char)(sequenceNumber >> 8);
-                        seq[3] = (unsigned char)(sequenceNumber);
-
-                        (*ss->sec.hash->begin)(ss->sec.hashcx);
-                        (*ss->sec.hash->update)(ss->sec.hashcx, ss->sec.rcvSecret.data,
-                                                ss->sec.rcvSecret.len);
-                        (*ss->sec.hash->update)(ss->sec.hashcx, pBuf + macLen,
-                                                gs->offset - macLen);
-                        (*ss->sec.hash->update)(ss->sec.hashcx, seq, 4);
-                        (*ss->sec.hash->end)(ss->sec.hashcx, mac, &macLen, macLen);
-
-                        PORT_Assert(macLen == ss->sec.hash->length);
-
-                        ssl_ReleaseSpecReadLock(ss); /******************************/
-
-                        if (NSS_SecureMemcmp(mac, pBuf, macLen) != 0) {
-                            /* MAC's didn't match... */
-                            SSL_DBG(("%d: SSL[%d]: mac check failed, seq=%d",
-                                     SSL_GETPID(), ss->fd, ss->sec.rcvSequence));
-                            PRINT_BUF(1, (ss, "computed mac:", mac, macLen));
-                            PRINT_BUF(1, (ss, "received mac:", pBuf, macLen));
-                            PORT_SetError(SSL_ERROR_BAD_MAC_READ);
-                            rv = SECFailure;
-                            goto cleanup;
-                        }
-                    } else {
-                        ssl_ReleaseSpecReadLock(ss); /******************************/
-                    }
-
-                    if (gs->recordPadding + macLen <= gs->offset) {
-                        gs->recordOffset = macLen;
-                        gs->readOffset = macLen;
-                        gs->writeOffset = gs->offset - gs->recordPadding;
-                        rv = 1;
-                    } else {
-                        PORT_SetError(SSL_ERROR_BAD_BLOCK_PADDING);
-                    cleanup:
-                        /* nothing in the buffer any more. */
-                        gs->recordOffset = 0;
-                        gs->readOffset = 0;
-                        gs->writeOffset = 0;
-                        rv = SECFailure;
-                    }
-
-                    gs->recordLen = gs->writeOffset - gs->readOffset;
-                    gs->recordPadding = 0; /* forget we did any padding. */
-                    gs->state = GS_INIT;
-
-                    if (rv > 0) {
-                        PRINT_BUF(50, (ss, "recv clear record:",
-                                       pBuf + gs->recordOffset, gs->recordLen));
-                    }
-                    return rv;
-
-                spec_locked_done:
-                    ssl_ReleaseSpecReadLock(ss);
-                    return rv;
-                }
-
-            case GS_DATA:
-                /* Have read in all the DATA portion of record */
-
-                gs->recordOffset = 0;
-                gs->readOffset = 0;
-                gs->writeOffset = gs->offset;
-                PORT_Assert(gs->recordLen == gs->writeOffset - gs->readOffset);
-                gs->recordLen = gs->offset;
-                gs->recordPadding = 0;
-                gs->state = GS_INIT;
-
-                ++ss->sec.rcvSequence;
-
-                PRINT_BUF(50, (ss, "recv clear record:",
-                               pBuf + gs->recordOffset, gs->recordLen));
-                return 1;
-
-        } /* end switch gs->state */
-    }     /* end gather loop. */
-    return rv;
-}
-
-/*
-** Gather a single record of data from the receiving stream. This code
-** first gathers the header (2 or 3 bytes long depending on the value of
-** the most significant bit in the first byte) then gathers up the data
-** for the record into the readBuf. This code handles non-blocking I/O
-** and is to be called multiple times until ss->sec.recordLen != 0.
- *
- * Returns +1 when it has gathered a complete SSLV2 record.
- * Returns  0 if it hits EOF.
- * Returns -1 (SECFailure)    on any error
- * Returns -2 (SECWouldBlock)
- *
- * Called by ssl_GatherRecord1stHandshake in sslcon.c,
- * and by DoRecv in sslsecur.c
- * Caller must hold RecvBufLock.
- */
-int
-ssl2_GatherRecord(sslSocket *ss, int flags)
-{
-    return ssl2_GatherData(ss, &ss->gs, flags);
-}
-
-/* Caller should hold RecvBufLock. */
-SECStatus
-ssl_InitGather(sslGather *gs)
-{
-    SECStatus status;
-
-    gs->state = GS_INIT;
-    gs->writeOffset = 0;
-    gs->readOffset = 0;
-    gs->dtlsPacketOffset = 0;
-    gs->dtlsPacket.len = 0;
-    status = sslBuffer_Grow(&gs->buf, 4096);
-    return status;
-}
-
-/* Caller must hold RecvBufLock. */
-void
-ssl_DestroyGather(sslGather *gs)
-{
-    if (gs) { /* the PORT_*Free functions check for NULL pointers. */
-        PORT_ZFree(gs->buf.buf, gs->buf.space);
-        PORT_Free(gs->inbuf.buf);
-        PORT_Free(gs->dtlsPacket.buf);
-    }
-}
-
-/* Caller must hold RecvBufLock. */
-static SECStatus
-ssl2_HandleV3HandshakeRecord(sslSocket *ss)
-{
-    SECStatus rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-
-    /* We've read in 3 bytes, there are 2 more to go in an ssl3 header. */
-    ss->gs.remainder = 2;
-    ss->gs.count = 0;
-
-    /* Clearing these handshake pointers ensures that
-     * ssl_Do1stHandshake won't call ssl2_HandleMessage when we return.
-     */
-    ss->nextHandshake = 0;
-    ss->securityHandshake = 0;
-
-    /* Setting ss->version to an SSL 3.x value will cause
-    ** ssl_GatherRecord1stHandshake to invoke ssl3_GatherCompleteHandshake()
-    ** the next time it is called.
-    **/
-    rv = ssl3_NegotiateVersion(ss, SSL_LIBRARY_VERSION_MAX_SUPPORTED,
-                               PR_TRUE);
-    if (rv != SECSuccess) {
-        return rv;
-    }
-
-    ss->sec.send = ssl3_SendApplicationData;
-
-    return SECSuccess;
-}
diff --git a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h
deleted file mode 100644
index f56ab53c..0000000
--- a/net/third_party/nss/ssl/sslimpl.h
+++ /dev/null
@@ -1,2161 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is PRIVATE to SSL and should be the first thing included by
- * any SSL implementation file.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef __sslimpl_h_
-#define __sslimpl_h_
-
-#ifdef DEBUG
-#undef NDEBUG
-#else
-#undef NDEBUG
-#define NDEBUG
-#endif
-#include "secport.h"
-#include "secerr.h"
-#include "sslerr.h"
-#include "ssl3prot.h"
-#include "hasht.h"
-#include "nssilock.h"
-#include "pkcs11t.h"
-#if defined(XP_UNIX) || defined(XP_BEOS)
-#include "unistd.h"
-#endif
-#include "nssrwlk.h"
-#include "prthread.h"
-#include "prclist.h"
-
-#include "sslt.h" /* for some formerly private types, now public */
-
-/* to make some of these old enums public without namespace pollution,
-** it was necessary to prepend ssl_ to the names.
-** These #defines preserve compatibility with the old code here in libssl.
-*/
-typedef SSLKEAType SSL3KEAType;
-typedef SSLMACAlgorithm SSL3MACAlgorithm;
-
-#define calg_null ssl_calg_null
-#define calg_rc4 ssl_calg_rc4
-#define calg_rc2 ssl_calg_rc2
-#define calg_des ssl_calg_des
-#define calg_3des ssl_calg_3des
-#define calg_idea ssl_calg_idea
-#define calg_fortezza ssl_calg_fortezza /* deprecated, must preserve */
-#define calg_aes ssl_calg_aes
-#define calg_camellia ssl_calg_camellia
-#define calg_seed ssl_calg_seed
-#define calg_aes_gcm ssl_calg_aes_gcm
-#define calg_chacha20 ssl_calg_chacha20
-
-#define mac_null ssl_mac_null
-#define mac_md5 ssl_mac_md5
-#define mac_sha ssl_mac_sha
-#define hmac_md5 ssl_hmac_md5
-#define hmac_sha ssl_hmac_sha
-#define hmac_sha256 ssl_hmac_sha256
-#define mac_aead ssl_mac_aead
-
-#define SET_ERROR_CODE    /* reminder */
-#define SEND_ALERT        /* reminder */
-#define TEST_FOR_FAILURE  /* reminder */
-#define DEAL_WITH_FAILURE /* reminder */
-
-#if defined(DEBUG) || defined(TRACE)
-#ifdef __cplusplus
-#define Debug 1
-#else
-extern int Debug;
-#endif
-#else
-#undef Debug
-#endif
-
-#if defined(DEBUG) && !defined(TRACE) && !defined(NISCC_TEST)
-#define TRACE
-#endif
-
-#ifdef TRACE
-#define SSL_TRC(a, b)     \
-    if (ssl_trace >= (a)) \
-    ssl_Trace b
-#define PRINT_BUF(a, b)   \
-    if (ssl_trace >= (a)) \
-    ssl_PrintBuf b
-#define DUMP_MSG(a, b)    \
-    if (ssl_trace >= (a)) \
-    ssl_DumpMsg b
-#else
-#define SSL_TRC(a, b)
-#define PRINT_BUF(a, b)
-#define DUMP_MSG(a, b)
-#endif
-
-#ifdef DEBUG
-#define SSL_DBG(b) \
-    if (ssl_debug) \
-    ssl_Trace b
-#else
-#define SSL_DBG(b)
-#endif
-
-#include "private/pprthred.h" /* for PR_InMonitor() */
-#define ssl_InMonitor(m) PZ_InMonitor(m)
-
-#define LSB(x) ((unsigned char)((x)&0xff))
-#define MSB(x) ((unsigned char)(((unsigned)(x)) >> 8))
-
-/************************************************************************/
-
-typedef enum { SSLAppOpRead = 0,
-               SSLAppOpWrite,
-               SSLAppOpRDWR,
-               SSLAppOpPost,
-               SSLAppOpHeader
-} SSLAppOperation;
-
-#define SSL_MIN_MASTER_KEY_BYTES 5
-#define SSL_MAX_MASTER_KEY_BYTES 64
-
-#define SSL2_SESSIONID_BYTES 16
-#define SSL3_SESSIONID_BYTES 32
-
-#define SSL_MIN_CHALLENGE_BYTES 16
-#define SSL_MAX_CHALLENGE_BYTES 32
-#define SSL_CHALLENGE_BYTES 16
-
-#define SSL_CONNECTIONID_BYTES 16
-
-#define SSL_MIN_CYPHER_ARG_BYTES 0
-#define SSL_MAX_CYPHER_ARG_BYTES 32
-
-#define SSL_MAX_MAC_BYTES 16
-
-#define SSL3_RSA_PMS_LENGTH 48
-#define SSL3_MASTER_SECRET_LENGTH 48
-
-/* number of wrap mechanisms potentially used to wrap master secrets. */
-#define SSL_NUM_WRAP_MECHS 16
-
-/* This makes the cert cache entry exactly 4k. */
-#define SSL_MAX_CACHED_CERT_LEN 4060
-
-#define NUM_MIXERS 9
-
-/* Mask of the 25 named curves we support. */
-#define SSL3_ALL_SUPPORTED_CURVES_MASK 0x3fffffe
-/* Mask of only 3 curves, suite B */
-#define SSL3_SUITE_B_SUPPORTED_CURVES_MASK 0x3800000
-
-#ifndef BPB
-#define BPB 8 /* Bits Per Byte */
-#endif
-
-#define EXPORT_RSA_KEY_LENGTH 64 /* bytes */
-
-#define INITIAL_DTLS_TIMEOUT_MS 1000  /* Default value from RFC 4347 = 1s*/
-#define MAX_DTLS_TIMEOUT_MS 60000     /* 1 minute */
-#define DTLS_FINISHED_TIMER_MS 120000 /* Time to wait in FINISHED state */
-
-typedef struct sslBufferStr sslBuffer;
-typedef struct sslConnectInfoStr sslConnectInfo;
-typedef struct sslGatherStr sslGather;
-typedef struct sslSecurityInfoStr sslSecurityInfo;
-typedef struct sslSessionIDStr sslSessionID;
-typedef struct sslSocketStr sslSocket;
-typedef struct sslSocketOpsStr sslSocketOps;
-
-typedef struct ssl3StateStr ssl3State;
-typedef struct ssl3CertNodeStr ssl3CertNode;
-typedef struct ssl3BulkCipherDefStr ssl3BulkCipherDef;
-typedef struct ssl3MACDefStr ssl3MACDef;
-typedef struct ssl3KeyPairStr ssl3KeyPair;
-typedef struct ssl3DHParamsStr ssl3DHParams;
-
-struct ssl3CertNodeStr {
-    struct ssl3CertNodeStr *next;
-    CERTCertificate *cert;
-};
-
-typedef SECStatus (*sslHandshakeFunc)(sslSocket *ss);
-
-/* This type points to the low layer send func,
-** e.g. ssl2_SendStream or ssl3_SendPlainText.
-** These functions return the same values as PR_Send,
-** i.e.  >= 0 means number of bytes sent, < 0 means error.
-*/
-typedef PRInt32 (*sslSendFunc)(sslSocket *ss, const unsigned char *buf,
-                               PRInt32 n, PRInt32 flags);
-
-typedef void (*sslSessionIDCacheFunc)(sslSessionID *sid);
-typedef void (*sslSessionIDUncacheFunc)(sslSessionID *sid);
-typedef sslSessionID *(*sslSessionIDLookupFunc)(const PRIPv6Addr *addr,
-                                                unsigned char *sid,
-                                                unsigned int sidLen,
-                                                CERTCertDBHandle *dbHandle);
-
-/* registerable callback function that either appends extension to buffer
- * or returns length of data that it would have appended.
- */
-typedef PRInt32 (*ssl3HelloExtensionSenderFunc)(sslSocket *ss, PRBool append,
-                                                PRUint32 maxBytes);
-
-/* registerable callback function that handles a received extension,
- * of the given type.
- */
-typedef SECStatus (*ssl3HelloExtensionHandlerFunc)(sslSocket *ss,
-                                                   PRUint16 ex_type,
-                                                   SECItem *data);
-
-/* row in a table of hello extension senders */
-typedef struct {
-    PRInt32 ex_type;
-    ssl3HelloExtensionSenderFunc ex_sender;
-} ssl3HelloExtensionSender;
-
-/* row in a table of hello extension handlers */
-typedef struct {
-    PRInt32 ex_type;
-    ssl3HelloExtensionHandlerFunc ex_handler;
-} ssl3HelloExtensionHandler;
-
-extern SECStatus
-ssl3_RegisterServerHelloExtensionSender(sslSocket *ss, PRUint16 ex_type,
-                                        ssl3HelloExtensionSenderFunc cb);
-
-extern PRInt32
-ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
-                               const ssl3HelloExtensionSender *sender);
-
-extern unsigned int
-ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength);
-
-extern PRInt32
-ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
-                            PRUint32 maxBytes);
-
-/* Socket ops */
-struct sslSocketOpsStr {
-    int (*connect)(sslSocket *, const PRNetAddr *);
-    PRFileDesc *(*accept)(sslSocket *, PRNetAddr *);
-    int (*bind)(sslSocket *, const PRNetAddr *);
-    int (*listen)(sslSocket *, int);
-    int (*shutdown)(sslSocket *, int);
-    int (*close)(sslSocket *);
-
-    int (*recv)(sslSocket *, unsigned char *, int, int);
-
-    /* points to the higher-layer send func, e.g. ssl_SecureSend. */
-    int (*send)(sslSocket *, const unsigned char *, int, int);
-    int (*read)(sslSocket *, unsigned char *, int);
-    int (*write)(sslSocket *, const unsigned char *, int);
-
-    int (*getpeername)(sslSocket *, PRNetAddr *);
-    int (*getsockname)(sslSocket *, PRNetAddr *);
-};
-
-/* Flags interpreted by ssl send functions. */
-#define ssl_SEND_FLAG_FORCE_INTO_BUFFER 0x40000000
-#define ssl_SEND_FLAG_NO_BUFFER 0x20000000
-#define ssl_SEND_FLAG_USE_EPOCH 0x10000000     /* DTLS only */
-#define ssl_SEND_FLAG_NO_RETRANSMIT 0x08000000 /* DTLS only */
-#define ssl_SEND_FLAG_CAP_RECORD_VERSION \
-    0x04000000 /* TLS only */
-#define ssl_SEND_FLAG_MASK 0x7f000000
-
-/*
-** A buffer object.
-*/
-struct sslBufferStr {
-    unsigned char *buf;
-    unsigned int len;
-    unsigned int space;
-};
-
-/*
-** SSL3 cipher suite policy and preference struct.
-*/
-typedef struct {
-#if !defined(_WIN32)
-    unsigned int cipher_suite : 16;
-    unsigned int policy : 8;
-    unsigned int enabled : 1;
-    unsigned int isPresent : 1;
-#else
-    ssl3CipherSuite cipher_suite;
-    PRUint8 policy;
-    unsigned char enabled : 1;
-    unsigned char isPresent : 1;
-#endif
-} ssl3CipherSuiteCfg;
-
-#ifndef NSS_DISABLE_ECC
-#define ssl_V3_SUITES_IMPLEMENTED 67
-#else
-#define ssl_V3_SUITES_IMPLEMENTED 41
-#endif /* NSS_DISABLE_ECC */
-
-#define MAX_DTLS_SRTP_CIPHER_SUITES 4
-
-/* MAX_SIGNATURE_ALGORITHMS allows for a large number of combinations of
- * SSLSignType and SSLHashType, but not all combinations (specifically, this
- * doesn't allow space for combinations with MD5). */
-#define MAX_SIGNATURE_ALGORITHMS 15
-
-/* clang-format off */
-typedef struct sslOptionsStr {
-    /* If SSL_SetNextProtoNego has been called, then this contains the
-     * list of supported protocols. */
-    SECItem nextProtoNego;
-
-    unsigned int useSecurity                : 1;  /*  1 */
-    unsigned int useSocks                   : 1;  /*  2 */
-    unsigned int requestCertificate         : 1;  /*  3 */
-    unsigned int requireCertificate         : 2;  /*  4-5 */
-    unsigned int handshakeAsClient          : 1;  /*  6 */
-    unsigned int handshakeAsServer          : 1;  /*  7 */
-    unsigned int enableSSL2                 : 1;  /*  8 */
-    unsigned int unusedBit9                 : 1;  /*  9 */
-    unsigned int unusedBit10                : 1;  /* 10 */
-    unsigned int noCache                    : 1;  /* 11 */
-    unsigned int fdx                        : 1;  /* 12 */
-    unsigned int v2CompatibleHello          : 1;  /* 13 */
-    unsigned int detectRollBack             : 1;  /* 14 */
-    unsigned int noStepDown                 : 1;  /* 15 */
-    unsigned int bypassPKCS11               : 1;  /* 16 */
-    unsigned int noLocks                    : 1;  /* 17 */
-    unsigned int enableSessionTickets       : 1;  /* 18 */
-    unsigned int enableDeflate              : 1;  /* 19 */
-    unsigned int enableRenegotiation        : 2;  /* 20-21 */
-    unsigned int requireSafeNegotiation     : 1;  /* 22 */
-    unsigned int enableFalseStart           : 1;  /* 23 */
-    unsigned int cbcRandomIV                : 1;  /* 24 */
-    unsigned int enableOCSPStapling         : 1;  /* 25 */
-    unsigned int enableNPN                  : 1;  /* 26 */
-    unsigned int enableALPN                 : 1;  /* 27 */
-    unsigned int reuseServerECDHEKey        : 1;  /* 28 */
-    unsigned int enableFallbackSCSV         : 1;  /* 29 */
-    unsigned int enableServerDhe            : 1;  /* 30 */
-    unsigned int enableExtendedMS           : 1;  /* 31 */
-    unsigned int enableSignedCertTimestamps : 1;  /* 32 */
-} sslOptions;
-/* clang-format on */
-
-typedef enum { sslHandshakingUndetermined = 0,
-               sslHandshakingAsClient,
-               sslHandshakingAsServer
-} sslHandshakingType;
-
-typedef struct sslServerCertsStr {
-    /* Configuration state for server sockets */
-    CERTCertificate *serverCert;
-    CERTCertificateList *serverCertChain;
-    ssl3KeyPair *serverKeyPair;
-    unsigned int serverKeyBits;
-} sslServerCerts;
-
-#define SERVERKEY serverKeyPair->privKey
-
-#define SSL_LOCK_RANK_SPEC 255
-#define SSL_LOCK_RANK_GLOBAL NSS_RWLOCK_RANK_NONE
-
-/* These are the valid values for shutdownHow.
-** These values are each 1 greater than the NSPR values, and the code
-** depends on that relation to efficiently convert PR_SHUTDOWN values
-** into ssl_SHUTDOWN values.  These values use one bit for read, and
-** another bit for write, and can be used as bitmasks.
-*/
-#define ssl_SHUTDOWN_NONE 0 /* NOT shutdown at all */
-#define ssl_SHUTDOWN_RCV 1  /* PR_SHUTDOWN_RCV  +1 */
-#define ssl_SHUTDOWN_SEND 2 /* PR_SHUTDOWN_SEND +1 */
-#define ssl_SHUTDOWN_BOTH 3 /* PR_SHUTDOWN_BOTH +1 */
-
-/*
-** A gather object. Used to read some data until a count has been
-** satisfied. Primarily for support of async sockets.
-** Everything in here is protected by the recvBufLock.
-*/
-struct sslGatherStr {
-    int state; /* see GS_ values below. */ /* ssl 2 & 3 */
-
-    /* "buf" holds received plaintext SSL records, after decrypt and MAC check.
-     * SSL2: recv'd ciphertext records are put here, then decrypted in place.
-     * SSL3: recv'd ciphertext records are put in inbuf (see below), then
-     *       decrypted into buf.
-     */
-    sslBuffer buf; /*recvBufLock*/ /* ssl 2 & 3 */
-
-    /* number of bytes previously read into hdr or buf(ssl2) or inbuf (ssl3).
-    ** (offset - writeOffset) is the number of ciphertext bytes read in but
-    **     not yet deciphered.
-    */
-    unsigned int offset; /* ssl 2 & 3 */
-
-    /* number of bytes to read in next call to ssl_DefRecv (recv) */
-    unsigned int remainder; /* ssl 2 & 3 */
-
-    /* Number of ciphertext bytes to read in after 2-byte SSL record header. */
-    unsigned int count; /* ssl2 only */
-
-    /* size of the final plaintext record.
-    ** == count - (recordPadding + MAC size)
-    */
-    unsigned int recordLen; /* ssl2 only */
-
-    /* number of bytes of padding to be removed after decrypting. */
-    /* This value is taken from the record's hdr[2], which means a too large
-     * value could crash us.
-     */
-    unsigned int recordPadding; /* ssl2 only */
-
-    /* plaintext DATA begins this many bytes into "buf".  */
-    unsigned int recordOffset; /* ssl2 only */
-
-    int encrypted; /* SSL2 session is now encrypted.  ssl2 only */
-
-    /* These next two values are used by SSL2 and SSL3.
-    ** DoRecv uses them to extract application data.
-    ** The difference between writeOffset and readOffset is the amount of
-    ** data available to the application.   Note that the actual offset of
-    ** the data in "buf" is recordOffset (above), not readOffset.
-    ** In the current implementation, this is made available before the
-    ** MAC is checked!!
-    */
-    unsigned int readOffset; /* Spot where DATA reader (e.g. application
-                               ** or handshake code) will read next.
-                               ** Always zero for SSl3 application data.
-                               */
-    /* offset in buf/inbuf/hdr into which new data will be read from socket. */
-    unsigned int writeOffset;
-
-    /* Buffer for ssl3 to read (encrypted) data from the socket */
-    sslBuffer inbuf; /*recvBufLock*/ /* ssl3 only */
-
-    /* The ssl[23]_GatherData functions read data into this buffer, rather
-    ** than into buf or inbuf, while in the GS_HEADER state.
-    ** The portion of the SSL record header put here always comes off the wire
-    ** as plaintext, never ciphertext.
-    ** For SSL2, the plaintext portion is two bytes long.  For SSl3 it is 5.
-    ** For DTLS it is 13.
-    */
-    unsigned char hdr[13]; /* ssl 2 & 3 or dtls */
-
-    /* Buffer for DTLS data read off the wire as a single datagram */
-    sslBuffer dtlsPacket;
-
-    /* the start of the buffered DTLS record in dtlsPacket */
-    unsigned int dtlsPacketOffset;
-};
-
-/* sslGather.state */
-#define GS_INIT 0
-#define GS_HEADER 1
-#define GS_MAC 2
-#define GS_DATA 3
-#define GS_PAD 4
-
-/*
-** ssl3State and CipherSpec structs
-*/
-
-/* The SSL bulk cipher definition */
-typedef enum {
-    cipher_null,
-    cipher_rc4,
-    cipher_rc4_40,
-    cipher_rc4_56,
-    cipher_rc2,
-    cipher_rc2_40,
-    cipher_des,
-    cipher_3des,
-    cipher_des40,
-    cipher_idea,
-    cipher_aes_128,
-    cipher_aes_256,
-    cipher_camellia_128,
-    cipher_camellia_256,
-    cipher_seed,
-    cipher_aes_128_gcm,
-    cipher_chacha20,
-    cipher_missing /* reserved for no such supported cipher */
-    /* This enum must match ssl3_cipherName[] in ssl3con.c.  */
-} SSL3BulkCipher;
-
-typedef enum { type_stream,
-               type_block,
-               type_aead } CipherType;
-
-#define MAX_IV_LENGTH 24
-
-/*
- * Do not depend upon 64 bit arithmetic in the underlying machine.
- */
-typedef struct {
-    PRUint32 high;
-    PRUint32 low;
-} SSL3SequenceNumber;
-
-typedef PRUint16 DTLSEpoch;
-
-typedef void (*DTLSTimerCb)(sslSocket *);
-
-/* 400 is large enough for MD5, SHA-1, and SHA-256.
- * For SHA-384 support, increase it to 712. */
-#define MAX_MAC_CONTEXT_BYTES 400
-#define MAX_MAC_CONTEXT_LLONGS (MAX_MAC_CONTEXT_BYTES / 8)
-
-#define MAX_CIPHER_CONTEXT_BYTES 2080
-#define MAX_CIPHER_CONTEXT_LLONGS (MAX_CIPHER_CONTEXT_BYTES / 8)
-
-typedef struct {
-    SSL3Opaque wrapped_master_secret[48];
-    PRUint16 wrapped_master_secret_len;
-    PRUint8 msIsWrapped;
-    PRUint8 resumable;
-    PRUint8 extendedMasterSecretUsed;
-} ssl3SidKeys; /* 52 bytes */
-
-typedef struct {
-    PK11SymKey *write_key;
-    PK11SymKey *write_mac_key;
-    PK11Context *write_mac_context;
-    SECItem write_key_item;
-    SECItem write_iv_item;
-    SECItem write_mac_key_item;
-    SSL3Opaque write_iv[MAX_IV_LENGTH];
-    PRUint64 cipher_context[MAX_CIPHER_CONTEXT_LLONGS];
-} ssl3KeyMaterial;
-
-typedef SECStatus (*SSLCipher)(void *context,
-                               unsigned char *out,
-                               int *outlen,
-                               int maxout,
-                               const unsigned char *in,
-                               int inlen);
-typedef SECStatus (*SSLAEADCipher)(
-    ssl3KeyMaterial *keys,
-    PRBool doDecrypt,
-    unsigned char *out,
-    int *outlen,
-    int maxout,
-    const unsigned char *in,
-    int inlen,
-    const unsigned char *additionalData,
-    int additionalDataLen);
-typedef SECStatus (*SSLCompressor)(void *context,
-                                   unsigned char *out,
-                                   int *outlen,
-                                   int maxout,
-                                   const unsigned char *in,
-                                   int inlen);
-typedef SECStatus (*SSLDestroy)(void *context, PRBool freeit);
-
-/* The DTLS anti-replay window. Defined here because we need it in
- * the cipher spec. Note that this is a ring buffer but left and
- * right represent the true window, with modular arithmetic used to
- * map them onto the buffer.
- */
-#define DTLS_RECVD_RECORDS_WINDOW 1024 /* Packets; approximate   \
-                                        * Must be divisible by 8 \
-                                        */
-typedef struct DTLSRecvdRecordsStr {
-    unsigned char data[DTLS_RECVD_RECORDS_WINDOW / 8];
-    PRUint64 left;
-    PRUint64 right;
-} DTLSRecvdRecords;
-
-/*
-** These are the "specs" in the "ssl3" struct.
-** Access to the pointers to these specs, and all the specs' contents
-** (direct and indirect) is protected by the reader/writer lock ss->specLock.
-*/
-typedef struct {
-    const ssl3BulkCipherDef *cipher_def;
-    const ssl3MACDef *mac_def;
-    SSLCompressionMethod compression_method;
-    int mac_size;
-    SSLCipher encode;
-    SSLCipher decode;
-    SSLAEADCipher aead;
-    SSLDestroy destroy;
-    void *encodeContext;
-    void *decodeContext;
-    SSLCompressor compressor;   /* Don't name these fields compress */
-    SSLCompressor decompressor; /* and uncompress because zconf.h   */
-                                /* may define them as macros.       */
-    SSLDestroy destroyCompressContext;
-    void *compressContext;
-    SSLDestroy destroyDecompressContext;
-    void *decompressContext;
-    PRBool bypassCiphers; /* did double bypass (at least) */
-    PK11SymKey *master_secret;
-    SSL3SequenceNumber write_seq_num;
-    SSL3SequenceNumber read_seq_num;
-    SSL3ProtocolVersion version;
-    ssl3KeyMaterial client;
-    ssl3KeyMaterial server;
-    SECItem msItem;
-    unsigned char key_block[NUM_MIXERS * MD5_LENGTH];
-    unsigned char raw_master_secret[56];
-    SECItem srvVirtName; /* for server: name that was negotiated
-                          * with a client. For client - is
-                          * always set to NULL.*/
-    DTLSEpoch epoch;
-    DTLSRecvdRecords recvdRecords;
-} ssl3CipherSpec;
-
-typedef enum { never_cached,
-               in_client_cache,
-               in_server_cache,
-               invalid_cache /* no longer in any cache. */
-} Cached;
-
-#define MAX_PEER_CERT_CHAIN_SIZE 8
-
-struct sslSessionIDStr {
-    /* The global cache lock must be held when accessing these members when the
-     * sid is in any cache.
-     */
-    sslSessionID *next; /* chain used for client sockets, only */
-    Cached cached;
-    int references;
-    PRUint32 lastAccessTime; /* seconds since Jan 1, 1970 */
-
-    /* The rest of the members, except for the members of u.ssl3.locked, may
-     * be modified only when the sid is not in any cache.
-     */
-
-    CERTCertificate *peerCert;
-    CERTCertificate *peerCertChain[MAX_PEER_CERT_CHAIN_SIZE];
-    SECItemArray peerCertStatus; /* client only */
-    const char *peerID;          /* client only */
-    const char *urlSvrName;      /* client only */
-    CERTCertificate *localCert;
-
-    PRIPv6Addr addr;
-    PRUint16 port;
-
-    SSL3ProtocolVersion version;
-
-    PRUint32 creationTime;   /* seconds since Jan 1, 1970 */
-    PRUint32 expirationTime; /* seconds since Jan 1, 1970 */
-
-    SSLSignType authAlgorithm;
-    PRUint32 authKeyBits;
-    SSLKEAType keaType;
-    PRUint32 keaKeyBits;
-
-    union {
-        struct {
-            /* the V2 code depends upon the size of sessionID.  */
-            unsigned char sessionID[SSL2_SESSIONID_BYTES];
-
-            /* Stuff used to recreate key and read/write cipher objects */
-            SECItem masterKey; /* never wrapped */
-            int cipherType;
-            SECItem cipherArg;
-            int keyBits;
-            int secretKeyBits;
-        } ssl2;
-        struct {
-            /* values that are copied into the server's on-disk SID cache. */
-            PRUint8 sessionIDLength;
-            SSL3Opaque sessionID[SSL3_SESSIONID_BYTES];
-
-            ssl3CipherSuite cipherSuite;
-            SSLCompressionMethod compression;
-            int policy;
-            ssl3SidKeys keys;
-            CK_MECHANISM_TYPE masterWrapMech;
-            /* mechanism used to wrap master secret */
-            SSL3KEAType exchKeyType;
-            /* key type used in exchange algorithm,
-             * and to wrap the sym wrapping key. */
-#ifndef NSS_DISABLE_ECC
-            PRUint32 negotiatedECCurves;
-#endif /* NSS_DISABLE_ECC */
-
-            /* The following values are NOT restored from the server's on-disk
-             * session cache, but are restored from the client's cache.
-             */
-            PK11SymKey *clientWriteKey;
-            PK11SymKey *serverWriteKey;
-
-            /* The following values pertain to the slot that wrapped the
-            ** master secret. (used only in client)
-            */
-            SECMODModuleID masterModuleID;
-            /* what module wrapped the master secret */
-            CK_SLOT_ID masterSlotID;
-            PRUint16 masterWrapIndex;
-            /* what's the key index for the wrapping key */
-            PRUint16 masterWrapSeries;
-            /* keep track of the slot series, so we don't
-             * accidently try to use new keys after the
-             * card gets removed and replaced.*/
-
-            /* The following values pertain to the slot that did the signature
-            ** for client auth.   (used only in client)
-            */
-            SECMODModuleID clAuthModuleID;
-            CK_SLOT_ID clAuthSlotID;
-            PRUint16 clAuthSeries;
-
-            char masterValid;
-            char clAuthValid;
-
-            SECItem srvName;
-
-            /* originalHandshakeHash contains the hash of the original, full
-             * handshake prior to the server's final flow. This is either a
-             * SHA-1/MD5 combination (for TLS < 1.2) or the TLS PRF hash (for
-             * TLS 1.2). This is recorded and used only when ChannelID is
-             * negotiated as it's used to bind the ChannelID signature on the
-             * resumption handshake to the original handshake. */
-            SECItem originalHandshakeHash;
-
-            /* Signed certificate timestamps received in a TLS extension.
-            ** (used only in client).
-            */
-            SECItem signedCertTimestamps;
-
-            /* This lock is lazily initialized by CacheSID when a sid is first
-             * cached. Before then, there is no need to lock anything because
-             * the sid isn't being shared by anything.
-             */
-            PRRWLock *lock;
-
-            /* The lock must be held while reading or writing these members
-             * because they change while the sid is cached.
-             */
-            struct {
-                /* The session ticket, if we have one, is sent as an extension
-                 * in the ClientHello message. This field is used only by
-                 * clients. It is protected by lock when lock is non-null
-                 * (after the sid has been added to the client session cache).
-                 */
-                NewSessionTicket sessionTicket;
-            } locked;
-        } ssl3;
-    } u;
-};
-
-typedef struct ssl3CipherSuiteDefStr {
-    ssl3CipherSuite cipher_suite;
-    SSL3BulkCipher bulk_cipher_alg;
-    SSL3MACAlgorithm mac_alg;
-    SSL3KeyExchangeAlgorithm key_exchange_alg;
-} ssl3CipherSuiteDef;
-
-/*
-** There are tables of these, all const.
-*/
-typedef struct {
-    SSL3KeyExchangeAlgorithm kea;
-    SSL3KEAType exchKeyType;
-    SSLSignType signKeyType;
-    /* For export cipher suites:
-     * is_limited identifies a suite as having a limit on the key size.
-     * key_size_limit provides the corresponding limit. */
-    PRBool is_limited;
-    unsigned int key_size_limit;
-    PRBool tls_keygen;
-    /* True if the key exchange for the suite is ephemeral.  Or to be more
-     * precise: true if the ServerKeyExchange message is always required. */
-    PRBool ephemeral;
-    /* An OID describing the key exchange */
-    SECOidTag oid;
-} ssl3KEADef;
-
-/*
-** There are tables of these, all const.
-*/
-struct ssl3BulkCipherDefStr {
-    SSL3BulkCipher cipher;
-    SSLCipherAlgorithm calg;
-    int key_size;
-    int secret_key_size;
-    CipherType type;
-    int iv_size;
-    int block_size;
-    int tag_size;            /* authentication tag size for AEAD ciphers. */
-    int explicit_nonce_size; /* for AEAD ciphers. */
-    SECOidTag oid;
-};
-
-/*
-** There are tables of these, all const.
-*/
-struct ssl3MACDefStr {
-    SSL3MACAlgorithm mac;
-    CK_MECHANISM_TYPE mmech;
-    int pad_size;
-    int mac_size;
-    SECOidTag oid;
-};
-
-typedef enum {
-    wait_client_hello,
-    wait_client_cert,
-    wait_client_key,
-    wait_cert_verify,
-    wait_change_cipher,
-    wait_finished,
-    wait_server_hello,
-    wait_certificate_status,
-    wait_server_cert,
-    wait_server_key,
-    wait_cert_request,
-    wait_hello_done,
-    wait_new_session_ticket,
-    wait_encrypted_extensions,
-    idle_handshake,
-    wait_invalid /* Invalid value. There is no handshake message "invalid". */
-} SSL3WaitState;
-
-/*
- * TLS extension related constants and data structures.
- */
-typedef struct TLSExtensionDataStr TLSExtensionData;
-typedef struct SessionTicketDataStr SessionTicketData;
-
-struct TLSExtensionDataStr {
-    /* registered callbacks that send server hello extensions */
-    ssl3HelloExtensionSender serverHelloSenders[SSL_MAX_EXTENSIONS];
-    ssl3HelloExtensionSender encryptedExtensionsSenders[SSL_MAX_EXTENSIONS];
-
-    /* Keep track of the extensions that are negotiated. */
-    PRUint16 numAdvertised;
-    PRUint16 numNegotiated;
-    PRUint16 advertised[SSL_MAX_EXTENSIONS];
-    PRUint16 negotiated[SSL_MAX_EXTENSIONS];
-
-    /* SessionTicket Extension related data. */
-    PRBool ticketTimestampVerified;
-    PRBool emptySessionTicket;
-    PRBool sentSessionTicketInClientHello;
-
-    /* SNI Extension related data
-     * Names data is not coppied from the input buffer. It can not be
-     * used outside the scope where input buffer is defined and that
-     * is beyond ssl3_HandleClientHello function. */
-    SECItem *sniNameArr;
-    PRUint32 sniNameArrSize;
-
-    /* Signed Certificate Timestamps extracted from the TLS extension.
-     * (client only).
-     * This container holds a temporary pointer to the extension data,
-     * until a session structure (the sec.ci.sid of an sslSocket) is setup
-     * that can hold a permanent copy of the data
-     * (in sec.ci.sid.u.ssl3.signedCertTimestamps).
-     * The data pointed to by this structure is neither explicitly allocated
-     * nor copied: the pointer points to the handshake message buffer and is
-     * only valid in the scope of ssl3_HandleServerHello.
-     */
-    SECItem signedCertTimestamps;
-};
-
-typedef SECStatus (*sslRestartTarget)(sslSocket *);
-
-/*
-** A DTLS queued message (potentially to be retransmitted)
-*/
-typedef struct DTLSQueuedMessageStr {
-    PRCList link;         /* The linked list link */
-    DTLSEpoch epoch;      /* The epoch to use */
-    SSL3ContentType type; /* The message type */
-    unsigned char *data;  /* The data */
-    PRUint16 len;         /* The data length */
-} DTLSQueuedMessage;
-
-typedef struct TLS13KeyShareEntryStr {
-    PRCList link;         /* The linked list link */
-    PRUint16 group;       /* The group for the entry */
-    SECItem key_exchange; /* The share itself */
-} TLS13KeyShareEntry;
-
-typedef enum {
-    handshake_hash_unknown = 0,
-    handshake_hash_combo = 1, /* The MD5/SHA-1 combination */
-    handshake_hash_single = 2 /* A single hash */
-} SSL3HandshakeHashType;
-
-/*
-** This is the "hs" member of the "ssl3" struct.
-** This entire struct is protected by ssl3HandshakeLock
-*/
-typedef struct SSL3HandshakeStateStr {
-    SSL3Random server_random;
-    SSL3Random client_random;
-    SSL3WaitState ws; /* May also contain SSL3WaitState | 0x80 for TLS 1.3 */
-
-    /* This group of members is used for handshake running hashes. */
-    SSL3HandshakeHashType hashType;
-    sslBuffer messages; /* Accumulated handshake messages */
-#ifndef NO_PKCS11_BYPASS
-    /* Bypass mode:
-     * SSL 3.0 - TLS 1.1 use both |md5_cx| and |sha_cx|. |md5_cx| is used for
-     * MD5 and |sha_cx| for SHA-1.
-     * TLS 1.2 and later use only |sha_cx|, for SHA-256. NOTE: When we support
-     * SHA-384, increase MAX_MAC_CONTEXT_BYTES to 712. */
-    PRUint64 md5_cx[MAX_MAC_CONTEXT_LLONGS];
-    PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS];
-    const SECHashObject *sha_obj;
-    /* The function prototype of sha_obj->clone() does not match the prototype
-     * of the freebl <HASH>_Clone functions, so we need a dedicated function
-     * pointer for the <HASH>_Clone function. */
-    void (*sha_clone)(void *dest, void *src);
-#endif
-    /* PKCS #11 mode:
-     * SSL 3.0 - TLS 1.1 use both |md5| and |sha|. |md5| is used for MD5 and
-     * |sha| for SHA-1.
-     * TLS 1.2 and later use only |sha|, for SHA-256. */
-    /* NOTE: On the client side, TLS 1.2 and later use |md5| as a backup
-     * handshake hash for generating client auth signatures. Confusingly, the
-     * backup hash function is SHA-1. */
-#define backupHash md5
-    PK11Context *md5;
-    PK11Context *sha;
-
-    const ssl3KEADef *kea_def;
-    ssl3CipherSuite cipher_suite;
-    const ssl3CipherSuiteDef *suite_def;
-    SSLCompressionMethod compression;
-    sslBuffer msg_body; /* protected by recvBufLock */
-                        /* partial handshake message from record layer */
-    unsigned int header_bytes;
-    /* number of bytes consumed from handshake */
-    /* message for message type and header length */
-    SSL3HandshakeType msg_type;
-    unsigned long msg_len;
-    SECItem ca_list;        /* used only by client */
-    PRBool isResuming;      /* are we resuming a session */
-    PRBool usedStepDownKey; /* we did a server key exchange. */
-    PRBool sendingSCSV;     /* instead of empty RI */
-    sslBuffer msgState;     /* current state for handshake messages*/
-                            /* protected by recvBufLock */
-
-    /* The session ticket received in a NewSessionTicket message is temporarily
-     * stored in newSessionTicket until the handshake is finished; then it is
-     * moved to the sid.
-     */
-    PRBool receivedNewSessionTicket;
-    NewSessionTicket newSessionTicket;
-
-    PRUint16 finishedBytes; /* size of single finished below */
-    union {
-        TLSFinished tFinished[2]; /* client, then server */
-        SSL3Finished sFinished[2];
-        SSL3Opaque data[72];
-    } finishedMsgs;
-#ifndef NSS_DISABLE_ECC
-    PRUint32 negotiatedECCurves; /* bit mask */
-#endif                           /* NSS_DISABLE_ECC */
-
-    PRBool authCertificatePending;
-    /* Which function should SSL_RestartHandshake* call if we're blocked?
-     * One of NULL, ssl3_SendClientSecondRound, ssl3_FinishHandshake,
-     * or ssl3_AlwaysFail */
-    sslRestartTarget restartTarget;
-    /* Shared state between ssl3_HandleFinished and ssl3_FinishHandshake */
-    PRBool cacheSID;
-
-    PRBool canFalseStart; /* Can/did we False Start */
-    /* Which preliminaryinfo values have been set. */
-    PRUint32 preliminaryInfo;
-
-    /* clientSigAndHash contains the contents of the signature_algorithms
-     * extension (if any) from the client. This is only valid for TLS 1.2
-     * or later. */
-    SSLSignatureAndHashAlg *clientSigAndHash;
-    unsigned int numClientSigAndHash;
-
-    /* This group of values is used for DTLS */
-    PRUint16 sendMessageSeq;       /* The sending message sequence
-                                    * number */
-    PRCList lastMessageFlight;     /* The last message flight we
-                                    * sent */
-    PRUint16 maxMessageSent;       /* The largest message we sent */
-    PRUint16 recvMessageSeq;       /* The receiving message sequence
-                                    * number */
-    sslBuffer recvdFragments;      /* The fragments we have received in
-                                    * a bitmask */
-    PRInt32 recvdHighWater;        /* The high water mark for fragments
-                                    * received. -1 means no reassembly
-                                    * in progress. */
-    unsigned char cookie[32];      /* The cookie */
-    unsigned char cookieLen;       /* The length of the cookie */
-    PRIntervalTime rtTimerStarted; /* When the timer was started */
-    DTLSTimerCb rtTimerCb;         /* The function to call on expiry */
-    PRUint32 rtTimeoutMs;          /* The length of the current timeout
-                                    * used for backoff (in ms) */
-    PRUint32 rtRetries;            /* The retry counter */
-
-    /* This group of values is used for TLS 1.3 and above */
-    PRCList remoteKeyShares;           /* The other side's public keys */
-    PK11SymKey *xSS;                   /* Extracted static secret */
-    PK11SymKey *xES;                   /* Extracted ephemeral secret */
-    PK11SymKey *trafficSecret;         /* The source key to use to generate
-                                        * traffic keys */
-    PK11SymKey *clientFinishedSecret;  /* Used for client Finished */
-    PK11SymKey *serverFinishedSecret;  /* Used for server Finished */
-    unsigned char certReqContext[255]; /* Ties CertificateRequest
-                                        * to Certificate */
-    PRUint8 certReqContextLen;         /* Length of the context
-                                        * cannot be greater than 255. */
-} SSL3HandshakeState;
-
-/*
-** This is the "ssl3" struct, as in "ss->ssl3".
-** note:
-** usually,   crSpec == cwSpec and prSpec == pwSpec.
-** Sometimes, crSpec == pwSpec and prSpec == cwSpec.
-** But there are never more than 2 actual specs.
-** No spec must ever be modified if either "current" pointer points to it.
-*/
-struct ssl3StateStr {
-
-    /*
-    ** The following Specs and Spec pointers must be protected using the
-    ** Spec Lock.
-    */
-    ssl3CipherSpec *crSpec; /* current read spec. */
-    ssl3CipherSpec *prSpec; /* pending read spec. */
-    ssl3CipherSpec *cwSpec; /* current write spec. */
-    ssl3CipherSpec *pwSpec; /* pending write spec. */
-
-    CERTCertificate *clientCertificate;   /* used by client */
-    SECKEYPrivateKey *clientPrivateKey;   /* used by client */
-    CERTCertificateList *clientCertChain; /* used by client */
-    PRBool sendEmptyCert;                 /* used by client */
-
-    SECKEYPrivateKey *channelID;   /* used by client */
-    SECKEYPublicKey *channelIDPub; /* used by client */
-
-    int policy;
-    /* This says what cipher suites we can do, and should
-     * be either SSL_ALLOWED or SSL_RESTRICTED
-     */
-    PLArenaPool *peerCertArena;
-    /* These are used to keep track of the peer CA */
-    void *peerCertChain;
-    /* chain while we are trying to validate it.   */
-    CERTDistNames *ca_list;
-    /* used by server.  trusted CAs for this socket. */
-    PRBool initialized;
-    SSL3HandshakeState hs;
-    ssl3CipherSpec specs[2]; /* one is current, one is pending. */
-
-    /* In a client: if the server supports Next Protocol Negotiation, then
-     * this is the protocol that was negotiated.
-     */
-    SECItem nextProto;
-    SSLNextProtoState nextProtoState;
-
-    PRUint16 mtu; /* Our estimate of the MTU */
-
-    /* DTLS-SRTP cipher suite preferences (if any) */
-    PRUint16 dtlsSRTPCiphers[MAX_DTLS_SRTP_CIPHER_SUITES];
-    PRUint16 dtlsSRTPCipherCount;
-    PRUint16 dtlsSRTPCipherSuite; /* 0 if not selected */
-    PRBool fatalAlertSent;
-    PRUint16 numDHEGroups;      /* used by server */
-    SSLDHEGroupType *dheGroups; /* used by server */
-    PRBool dheWeakGroupEnabled; /* used by server */
-
-    /* TLS 1.2 introduces separate signature algorithm negotiation.
-     * This is our preference order. */
-    SSLSignatureAndHashAlg signatureAlgorithms[MAX_SIGNATURE_ALGORITHMS];
-    unsigned int signatureAlgorithmCount;
-
-    /* The version to check if we fell back from our highest version
-     * of TLS. Default is 0 in which case we check against the maximum
-     * configured version for this socket. Used only on the client. */
-    SSL3ProtocolVersion downgradeCheckVersion;
-};
-
-/* Ethernet MTU but without subtracting the headers,
- * so slightly larger than expected */
-#define DTLS_MAX_MTU 1500U
-#define IS_DTLS(ss) (ss->protocolVariant == ssl_variant_datagram)
-
-typedef struct {
-    SSL3ContentType type;
-    SSL3ProtocolVersion version;
-    SSL3SequenceNumber seq_num; /* DTLS only */
-    sslBuffer *buf;
-} SSL3Ciphertext;
-
-struct ssl3KeyPairStr {
-    SECKEYPrivateKey *privKey;
-    SECKEYPublicKey *pubKey;
-    PRInt32 refCount; /* use PR_Atomic calls for this. */
-};
-
-struct ssl3DHParamsStr {
-    SECItem prime; /* p */
-    SECItem base;  /* g */
-};
-
-typedef struct SSLWrappedSymWrappingKeyStr {
-    SSL3Opaque wrappedSymmetricWrappingkey[512];
-    CK_MECHANISM_TYPE symWrapMechanism;
-    /* unwrapped symmetric wrapping key uses this mechanism */
-    CK_MECHANISM_TYPE asymWrapMechanism;
-    /* mechanism used to wrap the SymmetricWrappingKey using
-     * server's public and/or private keys. */
-    SSL3KEAType exchKeyType; /* type of keys used to wrap SymWrapKey*/
-    PRInt32 symWrapMechIndex;
-    PRUint16 wrappedSymKeyLen;
-} SSLWrappedSymWrappingKey;
-
-typedef struct SessionTicketStr {
-    PRUint16 ticket_version;
-    SSL3ProtocolVersion ssl_version;
-    ssl3CipherSuite cipher_suite;
-    SSLCompressionMethod compression_method;
-    SSLSignType authAlgorithm;
-    PRUint32 authKeyBits;
-    SSLKEAType keaType;
-    PRUint32 keaKeyBits;
-    /*
-     * exchKeyType and msWrapMech contain meaningful values only if
-     * ms_is_wrapped is true.
-     */
-    PRUint8 ms_is_wrapped;
-    SSLKEAType exchKeyType; /* XXX(wtc): same as keaType above? */
-    CK_MECHANISM_TYPE msWrapMech;
-    PRUint16 ms_length;
-    SSL3Opaque master_secret[48];
-    PRBool extendedMasterSecretUsed;
-    ClientIdentity client_identity;
-    SECItem peer_cert;
-    PRUint32 timestamp;
-    SECItem srvName; /* negotiated server name */
-} SessionTicket;
-
-/*
- * SSL2 buffers used in SSL3.
- *     writeBuf in the SecurityInfo maintained by sslsecur.c is used
- *              to hold the data just about to be passed to the kernel
- *     sendBuf in the ConnectInfo maintained by sslcon.c is used
- *              to hold handshake messages as they are accumulated
- */
-
-/*
-** This is "ci", as in "ss->sec.ci".
-**
-** Protection:  All the variables in here are protected by
-** firstHandshakeLock AND (in ssl3) ssl3HandshakeLock
-*/
-struct sslConnectInfoStr {
-    /* outgoing handshakes appended to this. */
-    sslBuffer sendBuf; /*xmitBufLock*/ /* ssl 2 & 3 */
-
-    PRIPv6Addr peer;     /* ssl 2 & 3 */
-    unsigned short port; /* ssl 2 & 3 */
-
-    sslSessionID *sid; /* ssl 2 & 3 */
-
-    /* see CIS_HAVE defines below for the bit values in *elements. */
-    char elements;         /* ssl2 only */
-    char requiredElements; /* ssl2 only */
-    char sentElements;     /* ssl2 only */
-
-    char sentFinished; /* ssl2 only */
-
-    /* Length of server challenge.  Used by client when saving challenge */
-    int serverChallengeLen; /* ssl2 only */
-    /* type of authentication requested by server */
-    unsigned char authType; /* ssl2 only */
-
-    /* Challenge sent by client to server in client-hello message */
-    /* SSL3 gets a copy of this.  See ssl3_StartHandshakeHash().  */
-    unsigned char clientChallenge[SSL_MAX_CHALLENGE_BYTES]; /* ssl 2 & 3 */
-
-    /* Connection-id sent by server to client in server-hello message */
-    unsigned char connectionID[SSL_CONNECTIONID_BYTES]; /* ssl2 only */
-
-    /* Challenge sent by server to client in request-certificate message */
-    unsigned char serverChallenge[SSL_MAX_CHALLENGE_BYTES]; /* ssl2 only */
-
-    /* Information kept to handle a request-certificate message */
-    unsigned char readKey[SSL_MAX_MASTER_KEY_BYTES];  /* ssl2 only */
-    unsigned char writeKey[SSL_MAX_MASTER_KEY_BYTES]; /* ssl2 only */
-    unsigned keySize;                                 /* ssl2 only */
-};
-
-/* bit values for ci->elements, ci->requiredElements, sentElements. */
-#define CIS_HAVE_MASTER_KEY 0x01
-#define CIS_HAVE_CERTIFICATE 0x02
-#define CIS_HAVE_FINISHED 0x04
-#define CIS_HAVE_VERIFY 0x08
-
-/* Note: The entire content of this struct and whatever it points to gets
- * blown away by SSL_ResetHandshake().  This is "sec" as in "ss->sec".
- *
- * Unless otherwise specified below, the contents of this struct are
- * protected by firstHandshakeLock AND (in ssl3) ssl3HandshakeLock.
- */
-struct sslSecurityInfoStr {
-    sslSendFunc send; /*xmitBufLock*/   /* ssl 2 & 3 */
-    int isServer; /* Spec Lock?*/       /* ssl 2 & 3 */
-    sslBuffer writeBuf; /*xmitBufLock*/ /* ssl 2 & 3 */
-
-    int cipherType;             /* ssl 2 & 3 */
-    int keyBits;                /* ssl 2 & 3 */
-    int secretKeyBits;          /* ssl 2 & 3 */
-    CERTCertificate *localCert; /* ssl 2 & 3 */
-    CERTCertificate *peerCert;  /* ssl 2 & 3 */
-    SECKEYPublicKey *peerKey;   /* ssl3 only */
-
-    SSLSignType authAlgorithm;
-    PRUint32 authKeyBits;
-    SSLKEAType keaType;
-    PRUint32 keaKeyBits;
-
-    /*
-    ** Procs used for SID cache (nonce) management.
-    ** Different implementations exist for clients/servers
-    ** The lookup proc is only used for servers.  Baloney!
-    */
-    sslSessionIDCacheFunc cache;     /* ssl 2 & 3 */
-    sslSessionIDUncacheFunc uncache; /* ssl 2 & 3 */
-
-    /*
-    ** everything below here is for ssl2 only.
-    ** This stuff is equivalent to SSL3's "spec", and is protected by the
-    ** same "Spec Lock" as used for SSL3's specs.
-    */
-    PRUint32 sendSequence; /*xmitBufLock*/ /* ssl2 only */
-    PRUint32 rcvSequence; /*recvBufLock*/  /* ssl2 only */
-
-    /* Hash information; used for one-way-hash functions (MD2, MD5, etc.) */
-    const SECHashObject *hash; /* Spec Lock */ /* ssl2 only */
-    void *hashcx; /* Spec Lock */              /* ssl2 only */
-
-    SECItem sendSecret; /* Spec Lock */ /* ssl2 only */
-    SECItem rcvSecret; /* Spec Lock */  /* ssl2 only */
-
-    /* Session cypher contexts; one for each direction */
-    void *readcx; /* Spec Lock */                    /* ssl2 only */
-    void *writecx; /* Spec Lock */                   /* ssl2 only */
-    SSLCipher enc; /* Spec Lock */                   /* ssl2 only */
-    SSLCipher dec; /* Spec Lock */                   /* ssl2 only */
-    void (*destroy)(void *, PRBool); /* Spec Lock */ /* ssl2 only */
-
-    /* Blocking information for the session cypher */
-    int blockShift; /* Spec Lock */ /* ssl2 only */
-    int blockSize; /* Spec Lock */  /* ssl2 only */
-
-    /* These are used during a connection handshake */
-    sslConnectInfo ci; /* ssl 2 & 3 */
-};
-
-/*
-** SSL Socket struct
-**
-** Protection:  XXX
-*/
-struct sslSocketStr {
-    PRFileDesc *fd;
-
-    /* Pointer to operations vector for this socket */
-    const sslSocketOps *ops;
-
-    /* SSL socket options */
-    sslOptions opt;
-    /* Enabled version range */
-    SSLVersionRange vrange;
-
-    /* State flags */
-    unsigned long clientAuthRequested;
-    unsigned long delayDisabled;     /* Nagle delay disabled */
-    unsigned long firstHsDone;       /* first handshake is complete. */
-    unsigned long enoughFirstHsDone; /* enough of the first handshake is
-                                      * done for callbacks to be able to
-                                      * retrieve channel security
-                                      * parameters from the SSL socket. */
-    unsigned long handshakeBegun;
-    unsigned long lastWriteBlocked;
-    unsigned long recvdCloseNotify; /* received SSL EOF. */
-    unsigned long TCPconnected;
-    unsigned long appDataBuffered;
-    unsigned long peerRequestedProtection; /* from old renegotiation */
-
-    /* version of the protocol to use */
-    SSL3ProtocolVersion version;
-    SSL3ProtocolVersion clientHelloVersion; /* version sent in client hello. */
-
-    sslSecurityInfo sec; /* not a pointer any more */
-
-    /* protected by firstHandshakeLock AND (in ssl3) ssl3HandshakeLock. */
-    const char *url; /* ssl 2 & 3 */
-
-    sslHandshakeFunc handshake;         /*firstHandshakeLock*/
-    sslHandshakeFunc nextHandshake;     /*firstHandshakeLock*/
-    sslHandshakeFunc securityHandshake; /*firstHandshakeLock*/
-
-    /* the following variable is only used with socks or other proxies. */
-    char *peerID; /* String uniquely identifies target server. */
-
-    unsigned char *cipherSpecs;
-    unsigned int sizeCipherSpecs;
-    const unsigned char *preferredCipher;
-
-    /* TLS ClientCertificateTypes requested during HandleCertificateRequest. */
-    /* Will be NULL at all other times. */
-    const SECItem *requestedCertTypes;
-
-    ssl3KeyPair *stepDownKeyPair; /* RSA step down keys */
-
-    const ssl3DHParams *dheParams; /* DHE param */
-    ssl3KeyPair *dheKeyPair;       /* DHE keys */
-
-    /* Callbacks */
-    SSLAuthCertificate authCertificate;
-    void *authCertificateArg;
-    SSLGetClientAuthData getClientAuthData;
-    void *getClientAuthDataArg;
-    SSLSNISocketConfig sniSocketConfig;
-    void *sniSocketConfigArg;
-    SSLBadCertHandler handleBadCert;
-    void *badCertArg;
-    SSLHandshakeCallback handshakeCallback;
-    void *handshakeCallbackData;
-    SSLCanFalseStartCallback canFalseStartCallback;
-    void *canFalseStartCallbackData;
-    void *pkcs11PinArg;
-    SSLNextProtoCallback nextProtoCallback;
-    void *nextProtoArg;
-
-    SSLClientChannelIDCallback getChannelID;
-    void *getChannelIDArg;
-
-    PRIntervalTime rTimeout; /* timeout for NSPR I/O */
-    PRIntervalTime wTimeout; /* timeout for NSPR I/O */
-    PRIntervalTime cTimeout; /* timeout for NSPR I/O */
-
-    PZLock *recvLock; /* lock against multiple reader threads. */
-    PZLock *sendLock; /* lock against multiple sender threads. */
-
-    PZMonitor *recvBufLock; /* locks low level recv buffers. */
-    PZMonitor *xmitBufLock; /* locks low level xmit buffers. */
-
-    /* Only one thread may operate on the socket until the initial handshake
-    ** is complete.  This Monitor ensures that.  Since SSL2 handshake is
-    ** only done once, this is also effectively the SSL2 handshake lock.
-    */
-    PZMonitor *firstHandshakeLock;
-
-    /* This monitor protects the ssl3 handshake state machine data.
-    ** Only one thread (reader or writer) may be in the ssl3 handshake state
-    ** machine at any time.  */
-    PZMonitor *ssl3HandshakeLock;
-
-    /* reader/writer lock, protects the secret data needed to encrypt and MAC
-    ** outgoing records, and to decrypt and MAC check incoming ciphertext
-    ** records.  */
-    NSSRWLock *specLock;
-
-    /* handle to perm cert db (and implicitly to the temp cert db) used
-    ** with this socket.
-    */
-    CERTCertDBHandle *dbHandle;
-
-    PRThread *writerThread; /* thread holds SSL_LOCK_WRITER lock */
-
-    PRUint16 shutdownHow; /* See ssl_SHUTDOWN defines below. */
-
-    PRUint16 allowedByPolicy;      /* copy of global policy bits. */
-    PRUint16 maybeAllowedByPolicy; /* copy of global policy bits. */
-    PRUint16 chosenPreference;     /* SSL2 cipher preferences. */
-
-    sslHandshakingType handshaking;
-
-    /* Gather object used for gathering data */
-    sslGather gs; /*recvBufLock*/
-
-    sslBuffer saveBuf;    /*xmitBufLock*/
-    sslBuffer pendingBuf; /*xmitBufLock*/
-
-    /* Configuration state for server sockets */
-    /* server cert and key for each KEA type */
-    sslServerCerts serverCerts[kt_kea_size];
-    /* each cert needs its own status */
-    SECItemArray *certStatusArray[kt_kea_size];
-    /* Serialized signed certificate timestamps to be sent to the client
-    ** in a TLS extension (server only). Each certificate needs its own
-    ** timestamps item.
-    */
-    SECItem signedCertTimestamps[kt_kea_size];
-
-    ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED];
-    ssl3KeyPair *ephemeralECDHKeyPair; /* for ECDHE-* handshake */
-
-    /* SSL3 state info.  Formerly was a pointer */
-    ssl3State ssl3;
-
-    /*
-     * TLS extension related data.
-     */
-    /* True when the current session is a stateless resume. */
-    PRBool statelessResume;
-    TLSExtensionData xtnData;
-
-    /* Whether we are doing stream or datagram mode */
-    SSLProtocolVariant protocolVariant;
-};
-
-/* All the global data items declared here should be protected using the
-** ssl_global_data_lock, which is a reader/writer lock.
-*/
-extern NSSRWLock *ssl_global_data_lock;
-extern char ssl_debug;
-extern char ssl_trace;
-extern FILE *ssl_trace_iob;
-extern FILE *ssl_keylog_iob;
-extern CERTDistNames *ssl3_server_ca_list;
-extern PRUint32 ssl_sid_timeout;
-extern PRUint32 ssl3_sid_timeout;
-
-extern const char *const ssl_cipherName[];
-extern const char *const ssl3_cipherName[];
-
-extern sslSessionIDLookupFunc ssl_sid_lookup;
-extern sslSessionIDCacheFunc ssl_sid_cache;
-extern sslSessionIDUncacheFunc ssl_sid_uncache;
-
-/************************************************************************/
-
-SEC_BEGIN_PROTOS
-
-/* Internal initialization and installation of the SSL error tables */
-extern SECStatus ssl_Init(void);
-extern SECStatus ssl_InitializePRErrorTable(void);
-
-/* Implementation of ops for default (non socks, non secure) case */
-extern int ssl_DefConnect(sslSocket *ss, const PRNetAddr *addr);
-extern PRFileDesc *ssl_DefAccept(sslSocket *ss, PRNetAddr *addr);
-extern int ssl_DefBind(sslSocket *ss, const PRNetAddr *addr);
-extern int ssl_DefListen(sslSocket *ss, int backlog);
-extern int ssl_DefShutdown(sslSocket *ss, int how);
-extern int ssl_DefClose(sslSocket *ss);
-extern int ssl_DefRecv(sslSocket *ss, unsigned char *buf, int len, int flags);
-extern int ssl_DefSend(sslSocket *ss, const unsigned char *buf,
-                       int len, int flags);
-extern int ssl_DefRead(sslSocket *ss, unsigned char *buf, int len);
-extern int ssl_DefWrite(sslSocket *ss, const unsigned char *buf, int len);
-extern int ssl_DefGetpeername(sslSocket *ss, PRNetAddr *name);
-extern int ssl_DefGetsockname(sslSocket *ss, PRNetAddr *name);
-extern int ssl_DefGetsockopt(sslSocket *ss, PRSockOption optname,
-                             void *optval, PRInt32 *optlen);
-extern int ssl_DefSetsockopt(sslSocket *ss, PRSockOption optname,
-                             const void *optval, PRInt32 optlen);
-
-/* Implementation of ops for socks only case */
-extern int ssl_SocksConnect(sslSocket *ss, const PRNetAddr *addr);
-extern PRFileDesc *ssl_SocksAccept(sslSocket *ss, PRNetAddr *addr);
-extern int ssl_SocksBind(sslSocket *ss, const PRNetAddr *addr);
-extern int ssl_SocksListen(sslSocket *ss, int backlog);
-extern int ssl_SocksGetsockname(sslSocket *ss, PRNetAddr *name);
-extern int ssl_SocksRecv(sslSocket *ss, unsigned char *buf, int len, int flags);
-extern int ssl_SocksSend(sslSocket *ss, const unsigned char *buf,
-                         int len, int flags);
-extern int ssl_SocksRead(sslSocket *ss, unsigned char *buf, int len);
-extern int ssl_SocksWrite(sslSocket *ss, const unsigned char *buf, int len);
-
-/* Implementation of ops for secure only case */
-extern int ssl_SecureConnect(sslSocket *ss, const PRNetAddr *addr);
-extern PRFileDesc *ssl_SecureAccept(sslSocket *ss, PRNetAddr *addr);
-extern int ssl_SecureRecv(sslSocket *ss, unsigned char *buf,
-                          int len, int flags);
-extern int ssl_SecureSend(sslSocket *ss, const unsigned char *buf,
-                          int len, int flags);
-extern int ssl_SecureRead(sslSocket *ss, unsigned char *buf, int len);
-extern int ssl_SecureWrite(sslSocket *ss, const unsigned char *buf, int len);
-extern int ssl_SecureShutdown(sslSocket *ss, int how);
-extern int ssl_SecureClose(sslSocket *ss);
-
-/* Implementation of ops for secure socks case */
-extern int ssl_SecureSocksConnect(sslSocket *ss, const PRNetAddr *addr);
-extern PRFileDesc *ssl_SecureSocksAccept(sslSocket *ss, PRNetAddr *addr);
-extern PRFileDesc *ssl_FindTop(sslSocket *ss);
-
-/* Gather funcs. */
-extern sslGather *ssl_NewGather(void);
-extern SECStatus ssl_InitGather(sslGather *gs);
-extern void ssl_DestroyGather(sslGather *gs);
-extern int ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags);
-extern int ssl2_GatherRecord(sslSocket *ss, int flags);
-extern SECStatus ssl_GatherRecord1stHandshake(sslSocket *ss);
-
-extern SECStatus ssl2_HandleClientHelloMessage(sslSocket *ss);
-extern SECStatus ssl2_HandleServerHelloMessage(sslSocket *ss);
-
-extern SECStatus ssl_CreateSecurityInfo(sslSocket *ss);
-extern SECStatus ssl_CopySecurityInfo(sslSocket *ss, sslSocket *os);
-extern void ssl_ResetSecurityInfo(sslSecurityInfo *sec, PRBool doMemset);
-extern void ssl_DestroySecurityInfo(sslSecurityInfo *sec);
-
-extern void ssl_PrintBuf(sslSocket *ss, const char *msg, const void *cp, int len);
-extern void ssl_DumpMsg(sslSocket *ss, unsigned char *bp, unsigned len);
-
-extern int ssl_SendSavedWriteData(sslSocket *ss);
-extern SECStatus ssl_SaveWriteData(sslSocket *ss,
-                                   const void *p, unsigned int l);
-extern SECStatus ssl2_BeginClientHandshake(sslSocket *ss);
-extern SECStatus ssl2_BeginServerHandshake(sslSocket *ss);
-extern int ssl_Do1stHandshake(sslSocket *ss);
-
-extern SECStatus sslBuffer_Grow(sslBuffer *b, unsigned int newLen);
-extern SECStatus sslBuffer_Append(sslBuffer *b, const void *data,
-                                  unsigned int len);
-
-extern void ssl2_UseClearSendFunc(sslSocket *ss);
-extern void ssl_ChooseSessionIDProcs(sslSecurityInfo *sec);
-
-extern sslSessionID *ssl3_NewSessionID(sslSocket *ss, PRBool is_server);
-extern sslSessionID *ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port,
-                                   const char *peerID, const char *urlSvrName);
-extern void ssl_FreeSID(sslSessionID *sid);
-
-extern int ssl3_SendApplicationData(sslSocket *ss, const PRUint8 *in,
-                                    int len, int flags);
-
-extern PRBool ssl_FdIsBlocking(PRFileDesc *fd);
-
-extern PRBool ssl_SocketIsBlocking(sslSocket *ss);
-
-extern void ssl3_SetAlwaysBlock(sslSocket *ss);
-
-extern SECStatus ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled);
-
-extern void ssl_FinishHandshake(sslSocket *ss);
-
-extern SECStatus ssl_CipherPolicySet(PRInt32 which, PRInt32 policy);
-
-extern SECStatus ssl_CipherPrefSetDefault(PRInt32 which, PRBool enabled);
-
-extern SECStatus ssl3_ConstrainRangeByPolicy(void);
-
-/* Returns PR_TRUE if we are still waiting for the server to complete its
- * response to our client second round. Once we've received the Finished from
- * the server then there is no need to check false start.
- */
-extern PRBool ssl3_WaitingForServerSecondRound(sslSocket *ss);
-
-extern SECStatus
-ssl3_CompressMACEncryptRecord(ssl3CipherSpec *cwSpec,
-                              PRBool isServer,
-                              PRBool isDTLS,
-                              PRBool capRecordVersion,
-                              SSL3ContentType type,
-                              const SSL3Opaque *pIn,
-                              PRUint32 contentLen,
-                              sslBuffer *wrBuf);
-
-extern PRInt32 ssl3_SendRecord(sslSocket *ss, DTLSEpoch epoch,
-                               SSL3ContentType type,
-                               const SSL3Opaque *pIn, PRInt32 nIn,
-                               PRInt32 flags);
-
-#ifdef NSS_SSL_ENABLE_ZLIB
-/*
- * The DEFLATE algorithm can result in an expansion of 0.1% + 12 bytes. For a
- * maximum TLS record payload of 2**14 bytes, that's 29 bytes.
- */
-#define SSL3_COMPRESSION_MAX_EXPANSION 29
-#else /* !NSS_SSL_ENABLE_ZLIB */
-#define SSL3_COMPRESSION_MAX_EXPANSION 0
-#endif
-
-/*
- * make sure there is room in the write buffer for padding and
- * other compression and cryptographic expansions.
- */
-#define SSL3_BUFFER_FUDGE 100 + SSL3_COMPRESSION_MAX_EXPANSION
-
-#define SSL_LOCK_READER(ss) \
-    if (ss->recvLock)       \
-    PZ_Lock(ss->recvLock)
-#define SSL_UNLOCK_READER(ss) \
-    if (ss->recvLock)         \
-    PZ_Unlock(ss->recvLock)
-#define SSL_LOCK_WRITER(ss) \
-    if (ss->sendLock)       \
-    PZ_Lock(ss->sendLock)
-#define SSL_UNLOCK_WRITER(ss) \
-    if (ss->sendLock)         \
-    PZ_Unlock(ss->sendLock)
-
-/* firstHandshakeLock -> recvBufLock */
-#define ssl_Get1stHandshakeLock(ss)                               \
-    {                                                             \
-        if (!ss->opt.noLocks) {                                   \
-            PORT_Assert(PZ_InMonitor((ss)->firstHandshakeLock) || \
-                        !ssl_HaveRecvBufLock(ss));                \
-            PZ_EnterMonitor((ss)->firstHandshakeLock);            \
-        }                                                         \
-    }
-#define ssl_Release1stHandshakeLock(ss)               \
-    {                                                 \
-        if (!ss->opt.noLocks)                         \
-            PZ_ExitMonitor((ss)->firstHandshakeLock); \
-    }
-#define ssl_Have1stHandshakeLock(ss) \
-    (PZ_InMonitor((ss)->firstHandshakeLock))
-
-/* ssl3HandshakeLock -> xmitBufLock */
-#define ssl_GetSSL3HandshakeLock(ss)                  \
-    {                                                 \
-        if (!ss->opt.noLocks) {                       \
-            PORT_Assert(!ssl_HaveXmitBufLock(ss));    \
-            PZ_EnterMonitor((ss)->ssl3HandshakeLock); \
-        }                                             \
-    }
-#define ssl_ReleaseSSL3HandshakeLock(ss)             \
-    {                                                \
-        if (!ss->opt.noLocks)                        \
-            PZ_ExitMonitor((ss)->ssl3HandshakeLock); \
-    }
-#define ssl_HaveSSL3HandshakeLock(ss) \
-    (PZ_InMonitor((ss)->ssl3HandshakeLock))
-
-#define ssl_GetSpecReadLock(ss)                 \
-    {                                           \
-        if (!ss->opt.noLocks)                   \
-            NSSRWLock_LockRead((ss)->specLock); \
-    }
-#define ssl_ReleaseSpecReadLock(ss)               \
-    {                                             \
-        if (!ss->opt.noLocks)                     \
-            NSSRWLock_UnlockRead((ss)->specLock); \
-    }
-/* NSSRWLock_HaveReadLock is not exported so there's no
- * ssl_HaveSpecReadLock macro. */
-
-#define ssl_GetSpecWriteLock(ss)                 \
-    {                                            \
-        if (!ss->opt.noLocks)                    \
-            NSSRWLock_LockWrite((ss)->specLock); \
-    }
-#define ssl_ReleaseSpecWriteLock(ss)               \
-    {                                              \
-        if (!ss->opt.noLocks)                      \
-            NSSRWLock_UnlockWrite((ss)->specLock); \
-    }
-#define ssl_HaveSpecWriteLock(ss) \
-    (NSSRWLock_HaveWriteLock((ss)->specLock))
-
-/* recvBufLock -> ssl3HandshakeLock -> xmitBufLock */
-#define ssl_GetRecvBufLock(ss)                           \
-    {                                                    \
-        if (!ss->opt.noLocks) {                          \
-            PORT_Assert(!ssl_HaveSSL3HandshakeLock(ss)); \
-            PORT_Assert(!ssl_HaveXmitBufLock(ss));       \
-            PZ_EnterMonitor((ss)->recvBufLock);          \
-        }                                                \
-    }
-#define ssl_ReleaseRecvBufLock(ss)             \
-    {                                          \
-        if (!ss->opt.noLocks)                  \
-            PZ_ExitMonitor((ss)->recvBufLock); \
-    }
-#define ssl_HaveRecvBufLock(ss) \
-    (PZ_InMonitor((ss)->recvBufLock))
-
-/* xmitBufLock -> specLock */
-#define ssl_GetXmitBufLock(ss)                  \
-    {                                           \
-        if (!ss->opt.noLocks)                   \
-            PZ_EnterMonitor((ss)->xmitBufLock); \
-    }
-#define ssl_ReleaseXmitBufLock(ss)             \
-    {                                          \
-        if (!ss->opt.noLocks)                  \
-            PZ_ExitMonitor((ss)->xmitBufLock); \
-    }
-#define ssl_HaveXmitBufLock(ss) \
-    (PZ_InMonitor((ss)->xmitBufLock))
-
-/* Placeholder value used in version ranges when SSL 3.0 and all
- * versions of TLS are disabled.
- */
-#define SSL_LIBRARY_VERSION_NONE 0
-
-/* SSL_LIBRARY_VERSION_MAX_SUPPORTED is the maximum version that this version
- * of libssl supports. Applications should use SSL_VersionRangeGetSupported at
- * runtime to determine which versions are supported by the version of libssl
- * in use.
- */
-#ifdef NSS_ENABLE_TLS_1_3
-#define SSL_LIBRARY_VERSION_MAX_SUPPORTED SSL_LIBRARY_VERSION_TLS_1_3
-#else
-#define SSL_LIBRARY_VERSION_MAX_SUPPORTED SSL_LIBRARY_VERSION_TLS_1_2
-#endif
-
-/* Rename this macro SSL_ALL_VERSIONS_DISABLED when SSL 2.0 is removed. */
-#define SSL3_ALL_VERSIONS_DISABLED(vrange) \
-    ((vrange)->min == SSL_LIBRARY_VERSION_NONE)
-
-extern PRBool ssl3_VersionIsSupported(SSLProtocolVariant protocolVariant,
-                                      SSL3ProtocolVersion version);
-
-extern SECStatus ssl3_KeyAndMacDeriveBypass(ssl3CipherSpec *pwSpec,
-                                            const unsigned char *cr, const unsigned char *sr,
-                                            PRBool isTLS, PRBool isExport);
-extern SECStatus ssl3_MasterSecretDeriveBypass(ssl3CipherSpec *pwSpec,
-                                               const unsigned char *cr, const unsigned char *sr,
-                                               const SECItem *pms, PRBool isTLS, PRBool isRSA);
-
-/* These functions are called from secnav, even though they're "private". */
-
-extern int ssl2_SendErrorMessage(struct sslSocketStr *ss, int error);
-extern sslSocket *ssl_FindSocket(PRFileDesc *fd);
-extern void ssl_FreeSocket(struct sslSocketStr *ssl);
-extern SECStatus SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level,
-                                SSL3AlertDescription desc);
-extern SECStatus ssl3_DecodeError(sslSocket *ss);
-
-extern SECStatus ssl3_RestartHandshakeAfterCertReq(struct sslSocketStr *ss,
-                                                   CERTCertificate *cert,
-                                                   SECKEYPrivateKey *key,
-                                                   CERTCertificateList *certChain);
-
-extern SECStatus ssl3_RestartHandshakeAfterChannelIDReq(
-    sslSocket *ss,
-    SECKEYPublicKey *channelIDPub,
-    SECKEYPrivateKey *channelID);
-
-extern SECStatus ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error);
-
-/*
- * for dealing with SSL 3.0 clients sending SSL 2.0 format hellos
- */
-extern SECStatus ssl3_HandleV2ClientHello(
-    sslSocket *ss, unsigned char *buffer, int length);
-extern SECStatus ssl3_StartHandshakeHash(
-    sslSocket *ss, unsigned char *buf, int length);
-
-/*
- * SSL3 specific routines
- */
-SECStatus ssl3_SendClientHello(sslSocket *ss, PRBool resending);
-
-/*
- * input into the SSL3 machinery from the actualy network reading code
- */
-SECStatus ssl3_HandleRecord(
-    sslSocket *ss, SSL3Ciphertext *cipher, sslBuffer *out);
-
-int ssl3_GatherAppDataRecord(sslSocket *ss, int flags);
-int ssl3_GatherCompleteHandshake(sslSocket *ss, int flags);
-/*
- * When talking to export clients or using export cipher suites, servers
- * with public RSA keys larger than 512 bits need to use a 512-bit public
- * key, signed by the larger key.  The smaller key is a "step down" key.
- * Generate that key pair and keep it around.
- */
-extern SECStatus ssl3_CreateRSAStepDownKeys(sslSocket *ss);
-
-extern SECStatus ssl3_SelectDHParams(sslSocket *ss);
-
-#ifndef NSS_DISABLE_ECC
-extern void ssl3_FilterECCipherSuitesByServerCerts(sslSocket *ss);
-extern PRBool ssl3_IsECCEnabled(sslSocket *ss);
-extern SECStatus ssl3_DisableECCSuites(sslSocket *ss,
-                                       const ssl3CipherSuite *suite);
-extern PRUint32 ssl3_GetSupportedECCurveMask(sslSocket *ss);
-
-/* Macro for finding a curve equivalent in strength to RSA key's */
-/* clang-format off */
-#define SSL_RSASTRENGTH_TO_ECSTRENGTH(s)                                       \
-        ((s <= 1024) ? 160                                                     \
-                     : ((s <= 2048) ? 224                                      \
-                                    : ((s <= 3072) ? 256                       \
-                                                   : ((s <= 7168) ? 384        \
-                                                                  : 521 ) ) ) )
-/* clang-format on */
-
-/* Types and names of elliptic curves used in TLS */
-typedef enum { ec_type_explicitPrime = 1,
-               ec_type_explicitChar2Curve = 2,
-               ec_type_named
-} ECType;
-
-typedef enum { ec_noName = 0,
-               ec_sect163k1 = 1,
-               ec_sect163r1 = 2,
-               ec_sect163r2 = 3,
-               ec_sect193r1 = 4,
-               ec_sect193r2 = 5,
-               ec_sect233k1 = 6,
-               ec_sect233r1 = 7,
-               ec_sect239k1 = 8,
-               ec_sect283k1 = 9,
-               ec_sect283r1 = 10,
-               ec_sect409k1 = 11,
-               ec_sect409r1 = 12,
-               ec_sect571k1 = 13,
-               ec_sect571r1 = 14,
-               ec_secp160k1 = 15,
-               ec_secp160r1 = 16,
-               ec_secp160r2 = 17,
-               ec_secp192k1 = 18,
-               ec_secp192r1 = 19,
-               ec_secp224k1 = 20,
-               ec_secp224r1 = 21,
-               ec_secp256k1 = 22,
-               ec_secp256r1 = 23,
-               ec_secp384r1 = 24,
-               ec_secp521r1 = 25,
-               ec_pastLastName
-} ECName;
-
-extern SECStatus ssl3_ECName2Params(PLArenaPool *arena, ECName curve,
-                                    SECKEYECParams *params);
-ECName ssl3_PubKey2ECName(SECKEYPublicKey *pubKey);
-
-ECName ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits);
-ECName ssl3_GetCurveNameForServerSocket(sslSocket *ss);
-
-#endif /* NSS_DISABLE_ECC */
-
-extern SECStatus ssl3_CipherPrefSetDefault(ssl3CipherSuite which, PRBool on);
-extern SECStatus ssl3_CipherPrefGetDefault(ssl3CipherSuite which, PRBool *on);
-extern SECStatus ssl2_CipherPrefSetDefault(PRInt32 which, PRBool enabled);
-extern SECStatus ssl2_CipherPrefGetDefault(PRInt32 which, PRBool *enabled);
-
-extern SECStatus ssl3_CipherPrefSet(sslSocket *ss, ssl3CipherSuite which, PRBool on);
-extern SECStatus ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *on);
-extern SECStatus ssl2_CipherPrefSet(sslSocket *ss, PRInt32 which, PRBool enabled);
-extern SECStatus ssl2_CipherPrefGet(sslSocket *ss, PRInt32 which, PRBool *enabled);
-extern SECStatus ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *cipher,
-                                     unsigned int len);
-
-extern SECStatus ssl3_SetPolicy(ssl3CipherSuite which, PRInt32 policy);
-extern SECStatus ssl3_GetPolicy(ssl3CipherSuite which, PRInt32 *policy);
-extern SECStatus ssl2_SetPolicy(PRInt32 which, PRInt32 policy);
-extern SECStatus ssl2_GetPolicy(PRInt32 which, PRInt32 *policy);
-
-extern void ssl2_InitSocketPolicy(sslSocket *ss);
-extern void ssl3_InitSocketPolicy(sslSocket *ss);
-
-extern SECStatus ssl3_ConstructV2CipherSpecsHack(sslSocket *ss,
-                                                 unsigned char *cs, int *size);
-
-extern SECStatus ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache);
-extern SECStatus ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b,
-                                             PRUint32 length);
-
-extern void ssl3_DestroySSL3Info(sslSocket *ss);
-
-extern SECStatus ssl3_NegotiateVersion(sslSocket *ss,
-                                       SSL3ProtocolVersion peerVersion,
-                                       PRBool allowLargerPeerVersion);
-
-extern SECStatus ssl_GetPeerInfo(sslSocket *ss);
-
-#ifndef NSS_DISABLE_ECC
-/* ECDH functions */
-extern SECStatus ssl3_SendECDHClientKeyExchange(sslSocket *ss,
-                                                SECKEYPublicKey *svrPubKey);
-extern SECStatus ssl3_HandleECDHServerKeyExchange(sslSocket *ss,
-                                                  SSL3Opaque *b, PRUint32 length);
-extern SECStatus ssl3_HandleECDHClientKeyExchange(sslSocket *ss,
-                                                  SSL3Opaque *b, PRUint32 length,
-                                                  SECKEYPublicKey *srvrPubKey,
-                                                  SECKEYPrivateKey *srvrPrivKey);
-extern SECStatus ssl3_SendECDHServerKeyExchange(
-    sslSocket *ss, const SSLSignatureAndHashAlg *sigAndHash);
-SECKEYPublicKey *tls13_ImportECDHKeyShare(
-    sslSocket *ss, SSL3Opaque *b, PRUint32 length, ECName curve);
-ECName tls13_GroupForECDHEKeyShare(ssl3KeyPair *pair);
-unsigned int tls13_SizeOfECDHEKeyShareKEX(ssl3KeyPair *pair);
-SECStatus tls13_EncodeECDHEKeyShareKEX(sslSocket *ss, ssl3KeyPair *pair);
-#endif
-
-extern SECStatus ssl3_ComputeCommonKeyHash(SSLHashType hashAlg,
-                                           PRUint8 *hashBuf,
-                                           unsigned int bufLen, SSL3Hashes *hashes,
-                                           PRBool bypassPKCS11);
-extern void ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName);
-extern SECStatus ssl3_InitPendingCipherSpec(sslSocket *ss, PK11SymKey *pms);
-extern SECStatus ssl3_AppendHandshake(sslSocket *ss, const void *void_src,
-                                      PRInt32 bytes);
-extern SECStatus ssl3_AppendHandshakeHeader(sslSocket *ss,
-                                            SSL3HandshakeType t, PRUint32 length);
-extern SECStatus ssl3_AppendHandshakeNumber(sslSocket *ss, PRInt32 num,
-                                            PRInt32 lenSize);
-extern SECStatus ssl3_AppendHandshakeVariable(sslSocket *ss,
-                                              const SSL3Opaque *src, PRInt32 bytes, PRInt32 lenSize);
-extern SECStatus ssl3_AppendSignatureAndHashAlgorithm(
-    sslSocket *ss, const SSLSignatureAndHashAlg *sigAndHash);
-extern SECStatus ssl3_ConsumeHandshake(sslSocket *ss, void *v, PRInt32 bytes,
-                                       SSL3Opaque **b, PRUint32 *length);
-extern PRInt32 ssl3_ConsumeHandshakeNumber(sslSocket *ss, PRInt32 bytes,
-                                           SSL3Opaque **b, PRUint32 *length);
-extern SECStatus ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i,
-                                               PRInt32 bytes, SSL3Opaque **b, PRUint32 *length);
-extern PRBool ssl3_IsSupportedSignatureAlgorithm(
-    const SSLSignatureAndHashAlg *alg);
-extern SECStatus ssl3_CheckSignatureAndHashAlgorithmConsistency(
-    sslSocket *ss, const SSLSignatureAndHashAlg *sigAndHash,
-    CERTCertificate *cert);
-extern SECStatus ssl3_ConsumeSignatureAndHashAlgorithm(
-    sslSocket *ss, SSL3Opaque **b, PRUint32 *length,
-    SSLSignatureAndHashAlg *out);
-extern SECStatus ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key,
-                                 SECItem *buf, PRBool isTLS);
-extern SECStatus ssl3_VerifySignedHashes(SSL3Hashes *hash,
-                                         CERTCertificate *cert, SECItem *buf, PRBool isTLS,
-                                         void *pwArg);
-extern SECStatus ssl3_CacheWrappedMasterSecret(sslSocket *ss,
-                                               sslSessionID *sid, ssl3CipherSpec *spec,
-                                               SSL3KEAType effectiveExchKeyType);
-
-/* Functions that handle ClientHello and ServerHello extensions. */
-extern SECStatus ssl3_HandleServerNameXtn(sslSocket *ss,
-                                          PRUint16 ex_type, SECItem *data);
-extern SECStatus ssl3_HandleSupportedCurvesXtn(sslSocket *ss,
-                                               PRUint16 ex_type, SECItem *data);
-extern SECStatus ssl3_HandleSupportedPointFormatsXtn(sslSocket *ss,
-                                                     PRUint16 ex_type, SECItem *data);
-extern SECStatus ssl3_ClientHandleSessionTicketXtn(sslSocket *ss,
-                                                   PRUint16 ex_type, SECItem *data);
-extern SECStatus ssl3_ServerHandleSessionTicketXtn(sslSocket *ss,
-                                                   PRUint16 ex_type, SECItem *data);
-
-/* ClientHello and ServerHello extension senders.
- * Note that not all extension senders are exposed here; only those that
- * that need exposure.
- */
-extern PRInt32 ssl3_SendSessionTicketXtn(sslSocket *ss, PRBool append,
-                                         PRUint32 maxBytes);
-
-/* ClientHello and ServerHello extension senders.
- * The code is in ssl3ext.c.
- */
-extern PRInt32 ssl3_SendServerNameXtn(sslSocket *ss, PRBool append,
-                                      PRUint32 maxBytes);
-
-/* Assigns new cert, cert chain and keys to ss->serverCerts
- * struct. If certChain is NULL, tries to find one. Aborts if
- * fails to do so. If cert and keyPair are NULL - unconfigures
- * sslSocket of kea type.*/
-extern SECStatus ssl_ConfigSecureServer(sslSocket *ss, CERTCertificate *cert,
-                                        const CERTCertificateList *certChain,
-                                        ssl3KeyPair *keyPair, SSLKEAType kea);
-
-#ifndef NSS_DISABLE_ECC
-extern PRInt32 ssl3_SendSupportedCurvesXtn(sslSocket *ss,
-                                           PRBool append, PRUint32 maxBytes);
-extern PRInt32 ssl3_SendSupportedPointFormatsXtn(sslSocket *ss,
-                                                 PRBool append, PRUint32 maxBytes);
-#endif
-
-/* call the registered extension handlers. */
-extern SECStatus ssl3_HandleHelloExtensions(sslSocket *ss,
-                                            SSL3Opaque **b, PRUint32 *length,
-                                            SSL3HandshakeType handshakeMessage);
-
-/* Hello Extension related routines. */
-extern PRBool ssl3_ExtensionNegotiated(sslSocket *ss, PRUint16 ex_type);
-extern void ssl3_SetSIDSessionTicket(sslSessionID *sid,
-                                     /*in/out*/ NewSessionTicket *session_ticket);
-extern SECStatus ssl3_SendNewSessionTicket(sslSocket *ss);
-extern PRBool ssl_GetSessionTicketKeys(unsigned char *keyName,
-                                       unsigned char *encKey, unsigned char *macKey);
-extern PRBool ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey *svrPrivKey,
-                                             SECKEYPublicKey *svrPubKey, void *pwArg,
-                                             unsigned char *keyName, PK11SymKey **aesKey,
-                                             PK11SymKey **macKey);
-
-/* Tell clients to consider tickets valid for this long. */
-#define TLS_EX_SESS_TICKET_LIFETIME_HINT (2 * 24 * 60 * 60) /* 2 days */
-#define TLS_EX_SESS_TICKET_VERSION (0x0101)
-
-extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char *data,
-                                            unsigned int length);
-
-extern SECStatus ssl3_GetTLSUniqueChannelBinding(sslSocket *ss,
-                                                 unsigned char *out,
-                                                 unsigned int *outLen,
-                                                 unsigned int outLenMax);
-
-/* Construct a new NSPR socket for the app to use */
-extern PRFileDesc *ssl_NewPRSocket(sslSocket *ss, PRFileDesc *fd);
-extern void ssl_FreePRSocket(PRFileDesc *fd);
-
-/* Internal config function so SSL3 can initialize the present state of
- * various ciphers */
-extern int ssl3_config_match_init(sslSocket *);
-
-/* Create a new ref counted key pair object from two keys. */
-extern ssl3KeyPair *ssl3_NewKeyPair(SECKEYPrivateKey *privKey,
-                                    SECKEYPublicKey *pubKey);
-
-/* get a new reference (bump ref count) to an ssl3KeyPair. */
-extern ssl3KeyPair *ssl3_GetKeyPairRef(ssl3KeyPair *keyPair);
-
-/* Decrement keypair's ref count and free if zero. */
-extern void ssl3_FreeKeyPair(ssl3KeyPair *keyPair);
-
-/* calls for accessing wrapping keys across processes. */
-extern PRBool
-ssl_GetWrappingKey(PRInt32 symWrapMechIndex,
-                   SSL3KEAType exchKeyType,
-                   SSLWrappedSymWrappingKey *wswk);
-
-/* The caller passes in the new value it wants
- * to set.  This code tests the wrapped sym key entry in the file on disk.
- * If it is uninitialized, this function writes the caller's value into
- * the disk entry, and returns false.
- * Otherwise, it overwrites the caller's wswk with the value obtained from
- * the disk, and returns PR_TRUE.
- * This is all done while holding the locks/semaphores necessary to make
- * the operation atomic.
- */
-extern PRBool
-ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk);
-
-/* get rid of the symmetric wrapping key references. */
-extern SECStatus SSL3_ShutdownServerCache(void);
-
-extern SECStatus ssl_InitSymWrapKeysLock(void);
-
-extern SECStatus ssl_FreeSymWrapKeysLock(void);
-
-extern SECStatus ssl_InitSessionCacheLocks(void);
-
-/**************** DTLS-specific functions **************/
-extern void dtls_FreeQueuedMessage(DTLSQueuedMessage *msg);
-extern void dtls_FreeQueuedMessages(PRCList *lst);
-extern void dtls_FreeHandshakeMessages(PRCList *lst);
-
-extern SECStatus dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf);
-extern SECStatus dtls_HandleHelloVerifyRequest(sslSocket *ss,
-                                               SSL3Opaque *b, PRUint32 length);
-extern SECStatus dtls_StageHandshakeMessage(sslSocket *ss);
-extern SECStatus dtls_QueueMessage(sslSocket *ss, SSL3ContentType type,
-                                   const SSL3Opaque *pIn, PRInt32 nIn);
-extern SECStatus dtls_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags);
-extern SECStatus dtls_CompressMACEncryptRecord(sslSocket *ss,
-                                               DTLSEpoch epoch,
-                                               PRBool use_epoch,
-                                               SSL3ContentType type,
-                                               const SSL3Opaque *pIn,
-                                               PRUint32 contentLen,
-                                               sslBuffer *wrBuf);
-SECStatus ssl3_DisableNonDTLSSuites(sslSocket *ss);
-extern SECStatus dtls_StartTimer(sslSocket *ss, DTLSTimerCb cb);
-extern SECStatus dtls_RestartTimer(sslSocket *ss, PRBool backoff,
-                                   DTLSTimerCb cb);
-extern void dtls_CheckTimer(sslSocket *ss);
-extern void dtls_CancelTimer(sslSocket *ss);
-extern void dtls_FinishedTimerCb(sslSocket *ss);
-extern void dtls_SetMTU(sslSocket *ss, PRUint16 advertised);
-extern void dtls_InitRecvdRecords(DTLSRecvdRecords *records);
-extern int dtls_RecordGetRecvd(const DTLSRecvdRecords *records, PRUint64 seq);
-extern void dtls_RecordSetRecvd(DTLSRecvdRecords *records, PRUint64 seq);
-extern void dtls_RehandshakeCleanup(sslSocket *ss);
-extern SSL3ProtocolVersion
-dtls_TLSVersionToDTLSVersion(SSL3ProtocolVersion tlsv);
-extern SSL3ProtocolVersion
-dtls_DTLSVersionToTLSVersion(SSL3ProtocolVersion dtlsv);
-extern PRBool dtls_IsRelevant(sslSocket *ss, const ssl3CipherSpec *crSpec,
-                              const SSL3Ciphertext *cText, PRUint64 *seqNum);
-
-CK_MECHANISM_TYPE ssl3_Alg2Mech(SSLCipherAlgorithm calg);
-SECStatus ssl3_SetupPendingCipherSpec(sslSocket *ss);
-SECStatus ssl3_FlushHandshake(sslSocket *ss, PRInt32 flags);
-SECStatus ssl3_SendCertificate(sslSocket *ss);
-SECStatus ssl3_CompleteHandleCertificate(sslSocket *ss,
-                                         SSL3Opaque *b, PRUint32 length);
-SECStatus ssl3_SendEmptyCertificate(sslSocket *ss);
-SECStatus ssl3_SendCertificateStatus(sslSocket *ss);
-SECStatus ssl3_CompleteHandleCertificateStatus(sslSocket *ss, SSL3Opaque *b,
-                                               PRUint32 length);
-SECStatus ssl3_EncodeCertificateRequestSigAlgs(sslSocket *ss, PRUint8 *buf,
-                                               unsigned maxLen, PRUint32 *len);
-void ssl3_GetCertificateRequestCAs(sslSocket *ss, int *calenp, SECItem **namesp,
-                                   int *nnamesp);
-SECStatus ssl3_ParseCertificateRequestCAs(sslSocket *ss, SSL3Opaque **b,
-                                          PRUint32 *length, PLArenaPool *arena,
-                                          CERTDistNames *ca_list);
-SECStatus ssl3_CompleteHandleCertificateRequest(sslSocket *ss,
-                                                SECItem *algorithms,
-                                                CERTDistNames *ca_list);
-SECStatus ssl3_SendCertificateVerify(sslSocket *ss,
-                                     SECKEYPrivateKey *privKey);
-SECStatus ssl3_SendServerHello(sslSocket *ss);
-SECOidTag ssl3_TLSHashAlgorithmToOID(SSLHashType hashFunc);
-SECStatus ssl3_ComputeHandshakeHashes(sslSocket *ss,
-                                      ssl3CipherSpec *spec,
-                                      SSL3Hashes *hashes,
-                                      PRUint32 sender);
-void ssl3_BumpSequenceNumber(SSL3SequenceNumber *num);
-PRInt32 tls13_ServerSendKeyShareXtn(sslSocket *ss, PRBool append,
-                                    PRUint32 maxBytes);
-#ifndef NSS_DISABLE_ECC
-SECStatus ssl3_CreateECDHEphemeralKeyPair(ECName ec_curve,
-                                          ssl3KeyPair **keyPair);
-PK11SymKey *tls13_ComputeECDHSharedKey(sslSocket *ss,
-                                       SECKEYPrivateKey *myPrivKey,
-                                       SECKEYPublicKey *peerKey);
-#endif
-
-/* Pull in TLS 1.3 functions */
-#include "tls13con.h"
-
-/********************** misc calls *********************/
-
-#ifdef DEBUG
-extern void ssl3_CheckCipherSuiteOrderConsistency();
-#endif
-
-extern int ssl_MapLowLevelError(int hiLevelError);
-
-extern PRUint32 ssl_Time(void);
-
-extern void SSL_AtomicIncrementLong(long *x);
-
-SECStatus SSL_DisableDefaultExportCipherSuites(void);
-SECStatus SSL_DisableExportCipherSuites(PRFileDesc *fd);
-PRBool SSL_IsExportCipherSuite(PRUint16 cipherSuite);
-
-SECStatus ssl3_ApplyNSSPolicy(void);
-
-extern SECStatus
-ssl3_TLSPRFWithMasterSecret(ssl3CipherSpec *spec,
-                            const char *label, unsigned int labelLen,
-                            const unsigned char *val, unsigned int valLen,
-                            unsigned char *out, unsigned int outLen);
-extern SECOidTag
-ssl3_TLSHashAlgorithmToOID(SSLHashType hashFunc);
-
-#ifdef TRACE
-#define SSL_TRACE(msg) ssl_Trace msg
-#else
-#define SSL_TRACE(msg)
-#endif
-
-void ssl_Trace(const char *format, ...);
-
-SEC_END_PROTOS
-
-#if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS)
-#define SSL_GETPID getpid
-#elif defined(WIN32)
-extern int __cdecl _getpid(void);
-#define SSL_GETPID _getpid
-#else
-#define SSL_GETPID() 0
-#endif
-
-#endif /* __sslimpl_h_ */
diff --git a/net/third_party/nss/ssl/sslinfo.c b/net/third_party/nss/ssl/sslinfo.c
deleted file mode 100644
index c59879c..0000000
--- a/net/third_party/nss/ssl/sslinfo.c
+++ /dev/null
@@ -1,460 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "ssl.h"
-#include "sslimpl.h"
-#include "sslproto.h"
-
-static const char *
-ssl_GetCompressionMethodName(SSLCompressionMethod compression)
-{
-    switch (compression) {
-        case ssl_compression_null:
-            return "NULL";
-#ifdef NSS_ENABLE_ZLIB
-        case ssl_compression_deflate:
-            return "DEFLATE";
-#endif
-        default:
-            return "???";
-    }
-}
-
-SECStatus
-SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len)
-{
-    sslSocket *ss;
-    SSLChannelInfo inf;
-    sslSessionID *sid;
-
-    /* Check if we can properly return the length of data written and that
-     * we're not asked to return more information than we know how to provide.
-     */
-    if (!info || len < sizeof inf.length || len > sizeof inf) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelInfo",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    memset(&inf, 0, sizeof inf);
-    inf.length = PR_MIN(sizeof inf, len);
-
-    if (ss->opt.useSecurity && ss->enoughFirstHsDone) {
-        sid = ss->sec.ci.sid;
-        inf.protocolVersion = ss->version;
-        inf.authKeyBits = ss->sec.authKeyBits;
-        inf.keaKeyBits = ss->sec.keaKeyBits;
-        if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */
-            inf.cipherSuite = ss->sec.cipherType | 0xff00;
-            inf.compressionMethod = ssl_compression_null;
-            inf.compressionMethodName = "N/A";
-        } else if (ss->ssl3.initialized) { /* SSL3 and TLS */
-            ssl_GetSpecReadLock(ss);
-            /* XXX  The cipher suite should be in the specs and this
-             * function should get it from cwSpec rather than from the "hs".
-             * See bug 275744 comment 69 and bug 766137.
-             */
-            inf.cipherSuite = ss->ssl3.hs.cipher_suite;
-            inf.compressionMethod = ss->ssl3.cwSpec->compression_method;
-            ssl_ReleaseSpecReadLock(ss);
-            inf.compressionMethodName =
-                ssl_GetCompressionMethodName(inf.compressionMethod);
-        }
-        if (sid) {
-            inf.creationTime = sid->creationTime;
-            inf.lastAccessTime = sid->lastAccessTime;
-            inf.expirationTime = sid->expirationTime;
-            inf.extendedMasterSecretUsed =
-                (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 ||
-                 sid->u.ssl3.keys.extendedMasterSecretUsed)
-                    ? PR_TRUE
-                    : PR_FALSE;
-
-            if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */
-                inf.sessionIDLength = SSL2_SESSIONID_BYTES;
-                memcpy(inf.sessionID, sid->u.ssl2.sessionID,
-                       SSL2_SESSIONID_BYTES);
-            } else {
-                unsigned int sidLen = sid->u.ssl3.sessionIDLength;
-                sidLen = PR_MIN(sidLen, sizeof inf.sessionID);
-                inf.sessionIDLength = sidLen;
-                memcpy(inf.sessionID, sid->u.ssl3.sessionID, sidLen);
-            }
-        }
-    }
-
-    memcpy(info, &inf, inf.length);
-
-    return SECSuccess;
-}
-
-SECStatus
-SSL_GetPreliminaryChannelInfo(PRFileDesc *fd,
-                              SSLPreliminaryChannelInfo *info,
-                              PRUintn len)
-{
-    sslSocket *ss;
-    SSLPreliminaryChannelInfo inf;
-
-    /* Check if we can properly return the length of data written and that
-     * we're not asked to return more information than we know how to provide.
-     */
-    if (!info || len < sizeof inf.length || len > sizeof inf) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetPreliminaryChannelInfo",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (ss->version < SSL_LIBRARY_VERSION_3_0) {
-        PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION);
-        return SECFailure;
-    }
-
-    memset(&inf, 0, sizeof(inf));
-    inf.length = PR_MIN(sizeof(inf), len);
-
-    inf.valuesSet = ss->ssl3.hs.preliminaryInfo;
-    inf.protocolVersion = ss->version;
-    inf.cipherSuite = ss->ssl3.hs.cipher_suite;
-
-    memcpy(info, &inf, inf.length);
-    return SECSuccess;
-}
-
-#define CS(x) x, #x
-#define CK(x) x | 0xff00, #x
-
-#define S_DSA "DSA", ssl_auth_dsa
-#define S_RSA "RSA", ssl_auth_rsa
-#define S_KEA "KEA", ssl_auth_kea
-#define S_ECDSA "ECDSA", ssl_auth_ecdsa
-
-#define K_DHE "DHE", kt_dh
-#define K_RSA "RSA", kt_rsa
-#define K_KEA "KEA", kt_kea
-#define K_ECDH "ECDH", kt_ecdh
-#define K_ECDHE "ECDHE", kt_ecdh
-
-#define C_SEED "SEED", calg_seed
-#define C_CAMELLIA "CAMELLIA", calg_camellia
-#define C_AES "AES", calg_aes
-#define C_RC4 "RC4", calg_rc4
-#define C_RC2 "RC2", calg_rc2
-#define C_DES "DES", calg_des
-#define C_3DES "3DES", calg_3des
-#define C_NULL "NULL", calg_null
-#define C_SJ "SKIPJACK", calg_sj
-#define C_AESGCM "AES-GCM", calg_aes_gcm
-#define C_CHACHA20 "CHACHA20POLY1305", calg_chacha20
-
-#define B_256 256, 256, 256
-#define B_128 128, 128, 128
-#define B_3DES 192, 156, 112
-#define B_SJ 96, 80, 80
-#define B_DES 64, 56, 56
-#define B_56 128, 56, 56
-#define B_40 128, 40, 40
-#define B_0 0, 0, 0
-
-#define M_AEAD_128 "AEAD", ssl_mac_aead, 128
-#define M_SHA256 "SHA256", ssl_hmac_sha256, 256
-#define M_SHA "SHA1", ssl_mac_sha, 160
-#define M_MD5 "MD5", ssl_mac_md5, 128
-#define M_NULL "NULL", ssl_mac_null, 0
-
-/* clang-format off */
-static const SSLCipherSuiteInfo suiteInfo[] = {
-    /* <------ Cipher suite --------------------> <auth> <KEA>  <bulk cipher> <MAC> <FIPS> */
-    {0,CS(TLS_RSA_WITH_AES_128_GCM_SHA256),       S_RSA, K_RSA, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 },
-    {0,CS(TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_DHE, C_CHACHA20, B_256, M_AEAD_128, 0, 0, 0 },
-
-    {0,CS(TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256),   S_RSA, K_DHE, C_AES, B_256, M_SHA256, 1, 0, 0 },
-    {0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA),      S_RSA, K_DHE, C_AES, B_256, M_SHA, 1, 0, 0 },
-    {0,CS(TLS_DHE_DSS_WITH_AES_256_CBC_SHA),      S_DSA, K_DHE, C_AES, B_256, M_SHA, 1, 0, 0 },
-    {0,CS(TLS_DHE_DSS_WITH_AES_256_CBC_SHA256),   S_DSA, K_DHE, C_AES, B_256, M_SHA256, 1, 0, 0 },
-    {0,CS(TLS_RSA_WITH_CAMELLIA_256_CBC_SHA),     S_RSA, K_RSA, C_CAMELLIA, B_256, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_RSA_WITH_AES_256_CBC_SHA256),       S_RSA, K_RSA, C_AES, B_256, M_SHA256, 1, 0, 0 },
-    {0,CS(TLS_RSA_WITH_AES_256_CBC_SHA),          S_RSA, K_RSA, C_AES, B_256, M_SHA, 1, 0, 0 },
-
-    {0,CS(TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_128, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_128, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_DHE_DSS_WITH_RC4_128_SHA),          S_DSA, K_DHE, C_RC4, B_128, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256),   S_RSA, K_DHE, C_AES, B_128, M_SHA256, 1, 0, 0 },
-    {0,CS(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256),   S_RSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 },
-    {0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA),      S_RSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0 },
-    {0,CS(TLS_DHE_DSS_WITH_AES_128_GCM_SHA256),   S_DSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 },
-    {0,CS(TLS_DHE_DSS_WITH_AES_128_CBC_SHA),      S_DSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0 },
-    {0,CS(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256),   S_DSA, K_DHE, C_AES, B_128, M_SHA256, 1, 0, 0 },
-    {0,CS(TLS_RSA_WITH_SEED_CBC_SHA),             S_RSA, K_RSA, C_SEED,B_128, M_SHA, 1, 0, 0 },
-    {0,CS(TLS_RSA_WITH_CAMELLIA_128_CBC_SHA),     S_RSA, K_RSA, C_CAMELLIA, B_128, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_RSA_WITH_RC4_128_SHA),              S_RSA, K_RSA, C_RC4, B_128, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_RSA_WITH_RC4_128_MD5),              S_RSA, K_RSA, C_RC4, B_128, M_MD5, 0, 0, 0 },
-    {0,CS(TLS_RSA_WITH_AES_128_CBC_SHA256),       S_RSA, K_RSA, C_AES, B_128, M_SHA256, 1, 0, 0 },
-    {0,CS(TLS_RSA_WITH_AES_128_CBC_SHA),          S_RSA, K_RSA, C_AES, B_128, M_SHA, 1, 0, 0 },
-
-    {0,CS(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA),     S_RSA, K_DHE, C_3DES,B_3DES,M_SHA, 1, 0, 0 },
-    {0,CS(TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA),     S_DSA, K_DHE, C_3DES,B_3DES,M_SHA, 1, 0, 0 },
-    {0,CS(SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA),    S_RSA, K_RSA, C_3DES,B_3DES,M_SHA, 1, 0, 1 },
-    {0,CS(TLS_RSA_WITH_3DES_EDE_CBC_SHA),         S_RSA, K_RSA, C_3DES,B_3DES,M_SHA, 1, 0, 0 },
-
-    {0,CS(TLS_DHE_RSA_WITH_DES_CBC_SHA),          S_RSA, K_DHE, C_DES, B_DES, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_DHE_DSS_WITH_DES_CBC_SHA),          S_DSA, K_DHE, C_DES, B_DES, M_SHA, 0, 0, 0 },
-    {0,CS(SSL_RSA_FIPS_WITH_DES_CBC_SHA),         S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 0, 1 },
-    {0,CS(TLS_RSA_WITH_DES_CBC_SHA),              S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 0, 0 },
-
-    {0,CS(TLS_RSA_EXPORT1024_WITH_RC4_56_SHA),    S_RSA, K_RSA, C_RC4, B_56,  M_SHA, 0, 1, 0 },
-    {0,CS(TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA),   S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 1, 0 },
-    {0,CS(TLS_RSA_EXPORT_WITH_RC4_40_MD5),        S_RSA, K_RSA, C_RC4, B_40,  M_MD5, 0, 1, 0 },
-    {0,CS(TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5),    S_RSA, K_RSA, C_RC2, B_40,  M_MD5, 0, 1, 0 },
-    {0,CS(TLS_RSA_WITH_NULL_SHA256),              S_RSA, K_RSA, C_NULL,B_0,   M_SHA256, 0, 1, 0 },
-    {0,CS(TLS_RSA_WITH_NULL_SHA),                 S_RSA, K_RSA, C_NULL,B_0,   M_SHA, 0, 1, 0 },
-    {0,CS(TLS_RSA_WITH_NULL_MD5),                 S_RSA, K_RSA, C_NULL,B_0,   M_MD5, 0, 1, 0 },
-
-    #ifndef NSS_DISABLE_ECC
-    /* ECC cipher suites */
-    {0,CS(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 },
-    {0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), S_ECDSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 },
-
-    {0,CS(TLS_ECDH_ECDSA_WITH_NULL_SHA),          S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_ECDH_ECDSA_WITH_RC4_128_SHA),       S_ECDSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA),  S_ECDSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0 },
-    {0,CS(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA),   S_ECDSA, K_ECDH, C_AES, B_128, M_SHA, 1, 0, 0 },
-    {0,CS(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA),   S_ECDSA, K_ECDH, C_AES, B_256, M_SHA, 1, 0, 0 },
-
-    {0,CS(TLS_ECDHE_ECDSA_WITH_NULL_SHA),         S_ECDSA, K_ECDHE, C_NULL, B_0, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_ECDHE_ECDSA_WITH_RC4_128_SHA),      S_ECDSA, K_ECDHE, C_RC4, B_128, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDHE, C_3DES, B_3DES, M_SHA, 1, 0, 0 },
-    {0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA),  S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA, 1, 0, 0 },
-    {0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA256, 1, 0, 0 },
-    {0,CS(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA),  S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA, 1, 0, 0 },
-    {0,CS(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), S_ECDSA, K_ECDHE, C_CHACHA20, B_256, M_AEAD_128, 0, 0, 0 },
-
-    {0,CS(TLS_ECDH_RSA_WITH_NULL_SHA),            S_RSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_ECDH_RSA_WITH_RC4_128_SHA),         S_RSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA),    S_RSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0 },
-    {0,CS(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA),     S_RSA, K_ECDH, C_AES, B_128, M_SHA, 1, 0, 0 },
-    {0,CS(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA),     S_RSA, K_ECDH, C_AES, B_256, M_SHA, 1, 0, 0 },
-
-    {0,CS(TLS_ECDHE_RSA_WITH_NULL_SHA),           S_RSA, K_ECDHE, C_NULL, B_0, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_ECDHE_RSA_WITH_RC4_128_SHA),        S_RSA, K_ECDHE, C_RC4, B_128, M_SHA, 0, 0, 0 },
-    {0,CS(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA),   S_RSA, K_ECDHE, C_3DES, B_3DES, M_SHA, 1, 0, 0 },
-    {0,CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA),    S_RSA, K_ECDHE, C_AES, B_128, M_SHA, 1, 0, 0 },
-    {0,CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_ECDHE, C_AES, B_128, M_SHA256, 1, 0, 0 },
-    {0,CS(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA),    S_RSA, K_ECDHE, C_AES, B_256, M_SHA, 1, 0, 0 },
-    {0,CS(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_ECDHE, C_CHACHA20, B_256, M_AEAD_128, 0, 0, 0 },
-    #endif /* NSS_DISABLE_ECC */
-
-    /* SSL 2 table */
-    {0,CK(SSL_CK_RC4_128_WITH_MD5),               S_RSA, K_RSA, C_RC4, B_128, M_MD5, 0, 0, 0 },
-    {0,CK(SSL_CK_RC2_128_CBC_WITH_MD5),           S_RSA, K_RSA, C_RC2, B_128, M_MD5, 0, 0, 0 },
-    {0,CK(SSL_CK_DES_192_EDE3_CBC_WITH_MD5),      S_RSA, K_RSA, C_3DES,B_3DES,M_MD5, 0, 0, 0 },
-    {0,CK(SSL_CK_DES_64_CBC_WITH_MD5),            S_RSA, K_RSA, C_DES, B_DES, M_MD5, 0, 0, 0 },
-    {0,CK(SSL_CK_RC4_128_EXPORT40_WITH_MD5),      S_RSA, K_RSA, C_RC4, B_40,  M_MD5, 0, 1, 0 },
-    {0,CK(SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5),  S_RSA, K_RSA, C_RC2, B_40,  M_MD5, 0, 1, 0 }
-};
-/* clang-format on */
-
-#define NUM_SUITEINFOS ((sizeof suiteInfo) / (sizeof suiteInfo[0]))
-
-SECStatus
-SSL_GetCipherSuiteInfo(PRUint16 cipherSuite,
-                       SSLCipherSuiteInfo *info, PRUintn len)
-{
-    unsigned int i;
-
-    /* Check if we can properly return the length of data written and that
-     * we're not asked to return more information than we know how to provide.
-     */
-    if (!info || len < sizeof suiteInfo[0].length ||
-        len > sizeof suiteInfo[0]) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-    len = PR_MIN(len, sizeof suiteInfo[0]);
-    for (i = 0; i < NUM_SUITEINFOS; i++) {
-        if (suiteInfo[i].cipherSuite == cipherSuite) {
-            memcpy(info, &suiteInfo[i], len);
-            info->length = len;
-            return SECSuccess;
-        }
-    }
-    PORT_SetError(SEC_ERROR_INVALID_ARGS);
-    return SECFailure;
-}
-
-/* This function might be a candidate to be public.
- * Disables all export ciphers in the default set of enabled ciphers.
- */
-SECStatus
-SSL_DisableDefaultExportCipherSuites(void)
-{
-    const SSLCipherSuiteInfo *pInfo = suiteInfo;
-    unsigned int i;
-
-    for (i = 0; i < NUM_SUITEINFOS; ++i, ++pInfo) {
-        if (pInfo->isExportable) {
-            PORT_CheckSuccess(SSL_CipherPrefSetDefault(pInfo->cipherSuite, PR_FALSE));
-        }
-    }
-    return SECSuccess;
-}
-
-/* This function might be a candidate to be public,
- * except that it takes an sslSocket pointer as an argument.
- * A Public version would take a PRFileDesc pointer.
- * Disables all export ciphers in the default set of enabled ciphers.
- */
-SECStatus
-SSL_DisableExportCipherSuites(PRFileDesc *fd)
-{
-    const SSLCipherSuiteInfo *pInfo = suiteInfo;
-    unsigned int i;
-
-    for (i = 0; i < NUM_SUITEINFOS; ++i, ++pInfo) {
-        if (pInfo->isExportable) {
-            PORT_CheckSuccess(SSL_CipherPrefSet(fd, pInfo->cipherSuite, PR_FALSE));
-        }
-    }
-    return SECSuccess;
-}
-
-/* Tells us if the named suite is exportable
- * returns false for unknown suites.
- */
-PRBool
-SSL_IsExportCipherSuite(PRUint16 cipherSuite)
-{
-    unsigned int i;
-    for (i = 0; i < NUM_SUITEINFOS; i++) {
-        if (suiteInfo[i].cipherSuite == cipherSuite) {
-            return (PRBool)(suiteInfo[i].isExportable);
-        }
-    }
-    return PR_FALSE;
-}
-
-SECItem *
-SSL_GetNegotiatedHostInfo(PRFileDesc *fd)
-{
-    SECItem *sniName = NULL;
-    sslSocket *ss;
-    char *name = NULL;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetNegotiatedHostInfo",
-                 SSL_GETPID(), fd));
-        return NULL;
-    }
-
-    if (ss->sec.isServer) {
-        if (ss->version > SSL_LIBRARY_VERSION_3_0 &&
-            ss->ssl3.initialized) { /* TLS */
-            SECItem *crsName;
-            ssl_GetSpecReadLock(ss); /*********************************/
-            crsName = &ss->ssl3.cwSpec->srvVirtName;
-            if (crsName->data) {
-                sniName = SECITEM_DupItem(crsName);
-            }
-            ssl_ReleaseSpecReadLock(ss); /*----------------------------*/
-        }
-        return sniName;
-    }
-    name = SSL_RevealURL(fd);
-    if (name) {
-        sniName = PORT_ZNew(SECItem);
-        if (!sniName) {
-            PORT_Free(name);
-            return NULL;
-        }
-        sniName->data = (void *)name;
-        sniName->len = PORT_Strlen(name);
-    }
-    return sniName;
-}
-
-SECStatus
-SSL_ExportKeyingMaterial(PRFileDesc *fd,
-                         const char *label, unsigned int labelLen,
-                         PRBool hasContext,
-                         const unsigned char *context, unsigned int contextLen,
-                         unsigned char *out, unsigned int outLen)
-{
-    sslSocket *ss;
-    unsigned char *val = NULL;
-    unsigned int valLen, i;
-    SECStatus rv = SECFailure;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in ExportKeyingMaterial",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    ssl_GetRecvBufLock(ss);
-    ssl_GetSSL3HandshakeLock(ss);
-
-    if (ss->version < SSL_LIBRARY_VERSION_3_1_TLS) {
-        PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION);
-        ssl_ReleaseSSL3HandshakeLock(ss);
-        ssl_ReleaseRecvBufLock(ss);
-        return SECFailure;
-    }
-
-    /* construct PRF arguments */
-    valLen = SSL3_RANDOM_LENGTH * 2;
-    if (hasContext) {
-        valLen += 2 /* PRUint16 length */ + contextLen;
-    }
-    val = PORT_Alloc(valLen);
-    if (!val) {
-        ssl_ReleaseSSL3HandshakeLock(ss);
-        ssl_ReleaseRecvBufLock(ss);
-        return SECFailure;
-    }
-    i = 0;
-    PORT_Memcpy(val + i, &ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH);
-    i += SSL3_RANDOM_LENGTH;
-    PORT_Memcpy(val + i, &ss->ssl3.hs.server_random.rand, SSL3_RANDOM_LENGTH);
-    i += SSL3_RANDOM_LENGTH;
-    if (hasContext) {
-        val[i++] = contextLen >> 8;
-        val[i++] = contextLen;
-        PORT_Memcpy(val + i, context, contextLen);
-        i += contextLen;
-    }
-    PORT_Assert(i == valLen);
-
-    /* Allow TLS keying material to be exported sooner, when the master
-     * secret is available and we have sent ChangeCipherSpec.
-     */
-    ssl_GetSpecReadLock(ss);
-    if (!ss->ssl3.cwSpec->master_secret && !ss->ssl3.cwSpec->msItem.len) {
-        PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
-        rv = SECFailure;
-    } else {
-        rv = ssl3_TLSPRFWithMasterSecret(ss->ssl3.cwSpec, label, labelLen, val,
-                                         valLen, out, outLen);
-    }
-    ssl_ReleaseSpecReadLock(ss);
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    ssl_ReleaseRecvBufLock(ss);
-
-    PORT_ZFree(val, valLen);
-    return rv;
-}
diff --git a/net/third_party/nss/ssl/sslinit.c b/net/third_party/nss/ssl/sslinit.c
deleted file mode 100644
index 0f38c0b5..0000000
--- a/net/third_party/nss/ssl/sslinit.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * NSS utility functions
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "prtypes.h"
-#include "prinit.h"
-#include "seccomon.h"
-#include "secerr.h"
-#include "ssl.h"
-#include "sslimpl.h"
-#include "sslproto.h"
-
-static int ssl_isInited = 0;
-static PRCallOnceType ssl_init = { 0 };
-
-PRStatus
-ssl_InitCallOnce(void *arg)
-{
-    int *error = (int *)arg;
-    SECStatus rv;
-
-    rv = ssl_InitializePRErrorTable();
-    if (rv != SECSuccess) {
-        *error = SEC_ERROR_NO_MEMORY;
-        return PR_FAILURE;
-    }
-#ifdef DEBUG
-    ssl3_CheckCipherSuiteOrderConsistency();
-#endif
-
-    rv = ssl3_ApplyNSSPolicy();
-    if (rv != SECSuccess) {
-        *error = PORT_GetError();
-        return PR_FAILURE;
-    }
-    return PR_SUCCESS;
-}
-
-SECStatus
-ssl_Init(void)
-{
-    PRStatus nrv;
-
-    /* short circuit test if we are already inited */
-    if (!ssl_isInited) {
-        int error;
-        /* only do this once at init time, block all others until we are done */
-        nrv = PR_CallOnceWithArg(&ssl_init, ssl_InitCallOnce, &error);
-        if (nrv != PR_SUCCESS) {
-            PORT_SetError(error);
-            return SECFailure;
-        }
-        ssl_isInited = 1;
-    }
-    return SECSuccess;
-}
diff --git a/net/third_party/nss/ssl/sslmutex.c b/net/third_party/nss/ssl/sslmutex.c
deleted file mode 100644
index 0e2edc9..0000000
--- a/net/third_party/nss/ssl/sslmutex.c
+++ /dev/null
@@ -1,647 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "seccomon.h"
-/* This ifdef should match the one in sslsnce.c */
-#if defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_OS2) || defined(XP_BEOS)
-
-#include "sslmutex.h"
-#include "prerr.h"
-
-static SECStatus
-single_process_sslMutex_Init(sslMutex* pMutex)
-{
-    PR_ASSERT(pMutex != 0 && pMutex->u.sslLock == 0);
-
-    pMutex->u.sslLock = PR_NewLock();
-    if (!pMutex->u.sslLock) {
-        return SECFailure;
-    }
-    return SECSuccess;
-}
-
-static SECStatus
-single_process_sslMutex_Destroy(sslMutex* pMutex)
-{
-    PR_ASSERT(pMutex != 0);
-    PR_ASSERT(pMutex->u.sslLock != 0);
-    if (!pMutex->u.sslLock) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return SECFailure;
-    }
-    PR_DestroyLock(pMutex->u.sslLock);
-    return SECSuccess;
-}
-
-static SECStatus
-single_process_sslMutex_Unlock(sslMutex* pMutex)
-{
-    PR_ASSERT(pMutex != 0);
-    PR_ASSERT(pMutex->u.sslLock != 0);
-    if (!pMutex->u.sslLock) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return SECFailure;
-    }
-    PR_Unlock(pMutex->u.sslLock);
-    return SECSuccess;
-}
-
-static SECStatus
-single_process_sslMutex_Lock(sslMutex* pMutex)
-{
-    PR_ASSERT(pMutex != 0);
-    PR_ASSERT(pMutex->u.sslLock != 0);
-    if (!pMutex->u.sslLock) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return SECFailure;
-    }
-    PR_Lock(pMutex->u.sslLock);
-    return SECSuccess;
-}
-
-#if defined(LINUX) || defined(AIX) || defined(BEOS) || defined(BSDI) || (defined(NETBSD) && __NetBSD_Version__ < 500000000) || defined(OPENBSD)
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include "unix_err.h"
-#include "pratom.h"
-
-#define SSL_MUTEX_MAGIC 0xfeedfd
-#define NONBLOCKING_POSTS 1 /* maybe this is faster */
-
-#if NONBLOCKING_POSTS
-
-#ifndef FNONBLOCK
-#define FNONBLOCK O_NONBLOCK
-#endif
-
-static int
-setNonBlocking(int fd, int nonBlocking)
-{
-    int flags;
-    int err;
-
-    flags = fcntl(fd, F_GETFL, 0);
-    if (0 > flags)
-        return flags;
-    if (nonBlocking)
-        flags |= FNONBLOCK;
-    else
-        flags &= ~FNONBLOCK;
-    err = fcntl(fd, F_SETFL, flags);
-    return err;
-}
-#endif
-
-SECStatus
-sslMutex_Init(sslMutex* pMutex, int shared)
-{
-    int err;
-    PR_ASSERT(pMutex);
-    pMutex->isMultiProcess = (PRBool)(shared != 0);
-    if (!shared) {
-        return single_process_sslMutex_Init(pMutex);
-    }
-    pMutex->u.pipeStr.mPipes[0] = -1;
-    pMutex->u.pipeStr.mPipes[1] = -1;
-    pMutex->u.pipeStr.mPipes[2] = -1;
-    pMutex->u.pipeStr.nWaiters = 0;
-
-    err = pipe(pMutex->u.pipeStr.mPipes);
-    if (err) {
-        nss_MD_unix_map_default_error(errno);
-        return err;
-    }
-#if NONBLOCKING_POSTS
-    err = setNonBlocking(pMutex->u.pipeStr.mPipes[1], 1);
-    if (err)
-        goto loser;
-#endif
-
-    pMutex->u.pipeStr.mPipes[2] = SSL_MUTEX_MAGIC;
-
-#if defined(LINUX) && defined(i386)
-    /* Pipe starts out empty */
-    return SECSuccess;
-#else
-    /* Pipe starts with one byte. */
-    return sslMutex_Unlock(pMutex);
-#endif
-
-loser:
-    nss_MD_unix_map_default_error(errno);
-    close(pMutex->u.pipeStr.mPipes[0]);
-    close(pMutex->u.pipeStr.mPipes[1]);
-    return SECFailure;
-}
-
-SECStatus
-sslMutex_Destroy(sslMutex* pMutex, PRBool processLocal)
-{
-    if (PR_FALSE == pMutex->isMultiProcess) {
-        return single_process_sslMutex_Destroy(pMutex);
-    }
-    if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return SECFailure;
-    }
-    close(pMutex->u.pipeStr.mPipes[0]);
-    close(pMutex->u.pipeStr.mPipes[1]);
-
-    if (processLocal) {
-        return SECSuccess;
-    }
-
-    pMutex->u.pipeStr.mPipes[0] = -1;
-    pMutex->u.pipeStr.mPipes[1] = -1;
-    pMutex->u.pipeStr.mPipes[2] = -1;
-    pMutex->u.pipeStr.nWaiters = 0;
-
-    return SECSuccess;
-}
-
-#if defined(LINUX) && defined(i386)
-/* No memory barrier needed for this platform */
-
-/* nWaiters includes the holder of the lock (if any) and the number
-** threads waiting for it.  After incrementing nWaiters, if the count
-** is exactly 1, then you have the lock and may proceed.  If the
-** count is greater than 1, then you must wait on the pipe.
-*/
-
-SECStatus
-sslMutex_Unlock(sslMutex* pMutex)
-{
-    PRInt32 newValue;
-    if (PR_FALSE == pMutex->isMultiProcess) {
-        return single_process_sslMutex_Unlock(pMutex);
-    }
-
-    if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return SECFailure;
-    }
-    /* Do Memory Barrier here. */
-    newValue = PR_ATOMIC_DECREMENT(&pMutex->u.pipeStr.nWaiters);
-    if (newValue > 0) {
-        int cc;
-        char c = 1;
-        do {
-            cc = write(pMutex->u.pipeStr.mPipes[1], &c, 1);
-        } while (cc < 0 && (errno == EINTR || errno == EAGAIN));
-        if (cc != 1) {
-            if (cc < 0)
-                nss_MD_unix_map_default_error(errno);
-            else
-                PORT_SetError(PR_UNKNOWN_ERROR);
-            return SECFailure;
-        }
-    }
-    return SECSuccess;
-}
-
-SECStatus
-sslMutex_Lock(sslMutex* pMutex)
-{
-    PRInt32 newValue;
-    if (PR_FALSE == pMutex->isMultiProcess) {
-        return single_process_sslMutex_Lock(pMutex);
-    }
-
-    if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return SECFailure;
-    }
-    newValue = PR_ATOMIC_INCREMENT(&pMutex->u.pipeStr.nWaiters);
-    /* Do Memory Barrier here. */
-    if (newValue > 1) {
-        int cc;
-        char c;
-        do {
-            cc = read(pMutex->u.pipeStr.mPipes[0], &c, 1);
-        } while (cc < 0 && errno == EINTR);
-        if (cc != 1) {
-            if (cc < 0)
-                nss_MD_unix_map_default_error(errno);
-            else
-                PORT_SetError(PR_UNKNOWN_ERROR);
-            return SECFailure;
-        }
-    }
-    return SECSuccess;
-}
-
-#else
-
-/* Using Atomic operations requires the use of a memory barrier instruction
-** on PowerPC, Sparc, and Alpha.  NSPR's PR_Atomic functions do not perform
-** them, and NSPR does not provide a function that does them (e.g. PR_Barrier).
-** So, we don't use them on those platforms.
-*/
-
-SECStatus
-sslMutex_Unlock(sslMutex* pMutex)
-{
-    int cc;
-    char c = 1;
-
-    if (PR_FALSE == pMutex->isMultiProcess) {
-        return single_process_sslMutex_Unlock(pMutex);
-    }
-
-    if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return SECFailure;
-    }
-    do {
-        cc = write(pMutex->u.pipeStr.mPipes[1], &c, 1);
-    } while (cc < 0 && (errno == EINTR || errno == EAGAIN));
-    if (cc != 1) {
-        if (cc < 0)
-            nss_MD_unix_map_default_error(errno);
-        else
-            PORT_SetError(PR_UNKNOWN_ERROR);
-        return SECFailure;
-    }
-
-    return SECSuccess;
-}
-
-SECStatus
-sslMutex_Lock(sslMutex* pMutex)
-{
-    int cc;
-    char c;
-
-    if (PR_FALSE == pMutex->isMultiProcess) {
-        return single_process_sslMutex_Lock(pMutex);
-    }
-
-    if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return SECFailure;
-    }
-
-    do {
-        cc = read(pMutex->u.pipeStr.mPipes[0], &c, 1);
-    } while (cc < 0 && errno == EINTR);
-    if (cc != 1) {
-        if (cc < 0)
-            nss_MD_unix_map_default_error(errno);
-        else
-            PORT_SetError(PR_UNKNOWN_ERROR);
-        return SECFailure;
-    }
-
-    return SECSuccess;
-}
-
-#endif
-
-#elif defined(WIN32)
-
-#include "win32err.h"
-
-/* on Windows, we need to find the optimal type of locking mechanism to use
- for the sslMutex.
-
- There are 3 cases :
- 1) single-process, use a PRLock, as for all other platforms
- 2) Win95 multi-process, use a Win32 mutex
- 3) on WINNT multi-process, use a PRLock + a Win32 mutex
-
-*/
-
-#ifdef WINNT
-
-SECStatus
-sslMutex_2LevelInit(sslMutex *sem)
-{
-    /*  the following adds a PRLock to sslMutex . This is done in each
-        process of a multi-process server and is only needed on WINNT, if
-        using fibers. We can't tell if native threads or fibers are used, so
-        we always do it on WINNT
-    */
-    PR_ASSERT(sem);
-    if (sem) {
-        /* we need to reset the sslLock in the children or the single_process init
-           function below will assert */
-        sem->u.sslLock = NULL;
-    }
-    return single_process_sslMutex_Init(sem);
-}
-
-static SECStatus
-sslMutex_2LevelDestroy(sslMutex *sem)
-{
-    return single_process_sslMutex_Destroy(sem);
-}
-
-#endif
-
-SECStatus
-sslMutex_Init(sslMutex *pMutex, int shared)
-{
-#ifdef WINNT
-    SECStatus retvalue;
-#endif
-    HANDLE hMutex;
-    SECURITY_ATTRIBUTES attributes =
-        { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
-
-    PR_ASSERT(pMutex != 0 && (pMutex->u.sslMutx == 0 ||
-                              pMutex->u.sslMutx ==
-                                  INVALID_HANDLE_VALUE));
-
-    pMutex->isMultiProcess = (PRBool)(shared != 0);
-
-    if (PR_FALSE == pMutex->isMultiProcess) {
-        return single_process_sslMutex_Init(pMutex);
-    }
-
-#ifdef WINNT
-    /*  we need a lock on WINNT for fibers in the parent process */
-    retvalue = sslMutex_2LevelInit(pMutex);
-    if (SECSuccess != retvalue)
-        return SECFailure;
-#endif
-
-    if (!pMutex || ((hMutex = pMutex->u.sslMutx) != 0 &&
-                    hMutex !=
-                        INVALID_HANDLE_VALUE)) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return SECFailure;
-    }
-    attributes.bInheritHandle = (shared ? TRUE : FALSE);
-    hMutex = CreateMutex(&attributes, FALSE, NULL);
-    if (hMutex == NULL) {
-        hMutex = INVALID_HANDLE_VALUE;
-        nss_MD_win32_map_default_error(GetLastError());
-        return SECFailure;
-    }
-    pMutex->u.sslMutx = hMutex;
-    return SECSuccess;
-}
-
-SECStatus
-sslMutex_Destroy(sslMutex *pMutex, PRBool processLocal)
-{
-    HANDLE hMutex;
-    int rv;
-    int retvalue = SECSuccess;
-
-    PR_ASSERT(pMutex != 0);
-    if (PR_FALSE == pMutex->isMultiProcess) {
-        return single_process_sslMutex_Destroy(pMutex);
-    }
-
-/*  multi-process mode */
-#ifdef WINNT
-    /* on NT, get rid of the PRLock used for fibers within a process */
-    retvalue = sslMutex_2LevelDestroy(pMutex);
-#endif
-
-    PR_ASSERT(pMutex->u.sslMutx != 0 &&
-              pMutex->u.sslMutx != INVALID_HANDLE_VALUE);
-    if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0 ||
-        hMutex == INVALID_HANDLE_VALUE) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return SECFailure;
-    }
-
-    rv = CloseHandle(hMutex); /* ignore error */
-    if (!processLocal && rv) {
-        pMutex->u.sslMutx = hMutex = INVALID_HANDLE_VALUE;
-    }
-    if (!rv) {
-        nss_MD_win32_map_default_error(GetLastError());
-        retvalue = SECFailure;
-    }
-    return retvalue;
-}
-
-int
-sslMutex_Unlock(sslMutex *pMutex)
-{
-    BOOL success = FALSE;
-    HANDLE hMutex;
-
-    PR_ASSERT(pMutex != 0);
-    if (PR_FALSE == pMutex->isMultiProcess) {
-        return single_process_sslMutex_Unlock(pMutex);
-    }
-
-    PR_ASSERT(pMutex->u.sslMutx != 0 &&
-              pMutex->u.sslMutx != INVALID_HANDLE_VALUE);
-    if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0 ||
-        hMutex == INVALID_HANDLE_VALUE) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return SECFailure;
-    }
-    success = ReleaseMutex(hMutex);
-    if (!success) {
-        nss_MD_win32_map_default_error(GetLastError());
-        return SECFailure;
-    }
-#ifdef WINNT
-    return single_process_sslMutex_Unlock(pMutex);
-    /* release PRLock for other fibers in the process */
-#else
-    return SECSuccess;
-#endif
-}
-
-int
-sslMutex_Lock(sslMutex *pMutex)
-{
-    HANDLE hMutex;
-    DWORD event;
-    DWORD lastError;
-    SECStatus rv;
-    SECStatus retvalue = SECSuccess;
-    PR_ASSERT(pMutex != 0);
-
-    if (PR_FALSE == pMutex->isMultiProcess) {
-        return single_process_sslMutex_Lock(pMutex);
-    }
-#ifdef WINNT
-    /* lock first to preserve from other threads/fibers
-       in the same process */
-    retvalue = single_process_sslMutex_Lock(pMutex);
-#endif
-    PR_ASSERT(pMutex->u.sslMutx != 0 &&
-              pMutex->u.sslMutx != INVALID_HANDLE_VALUE);
-    if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0 ||
-        hMutex == INVALID_HANDLE_VALUE) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return SECFailure; /* what else ? */
-    }
-    /* acquire the mutex to be the only owner accross all other processes */
-    event = WaitForSingleObject(hMutex, INFINITE);
-    switch (event) {
-        case WAIT_OBJECT_0:
-        case WAIT_ABANDONED:
-            rv = SECSuccess;
-            break;
-
-        case WAIT_TIMEOUT:
-#if defined(WAIT_IO_COMPLETION)
-        case WAIT_IO_COMPLETION:
-#endif
-        default: /* should never happen. nothing we can do. */
-            PR_ASSERT(!("WaitForSingleObject returned invalid value."));
-            PORT_SetError(PR_UNKNOWN_ERROR);
-            rv = SECFailure;
-            break;
-
-        case WAIT_FAILED: /* failure returns this */
-            rv = SECFailure;
-            lastError = GetLastError(); /* for debugging */
-            nss_MD_win32_map_default_error(lastError);
-            break;
-    }
-
-    if (!(SECSuccess == retvalue && SECSuccess == rv)) {
-        return SECFailure;
-    }
-
-    return SECSuccess;
-}
-
-#elif defined(XP_UNIX) && !defined(DARWIN)
-
-#include <errno.h>
-#include "unix_err.h"
-
-SECStatus
-sslMutex_Init(sslMutex* pMutex, int shared)
-{
-    int rv;
-    PR_ASSERT(pMutex);
-    pMutex->isMultiProcess = (PRBool)(shared != 0);
-    if (!shared) {
-        return single_process_sslMutex_Init(pMutex);
-    }
-    do {
-        rv = sem_init(&pMutex->u.sem, shared, 1);
-    } while (rv < 0 && errno == EINTR);
-    if (rv < 0) {
-        nss_MD_unix_map_default_error(errno);
-        return SECFailure;
-    }
-    return SECSuccess;
-}
-
-SECStatus
-sslMutex_Destroy(sslMutex* pMutex, PRBool processLocal)
-{
-    int rv;
-    if (PR_FALSE == pMutex->isMultiProcess) {
-        return single_process_sslMutex_Destroy(pMutex);
-    }
-
-    /* semaphores are global resources. See SEM_DESTROY(3) man page */
-    if (processLocal) {
-        return SECSuccess;
-    }
-    do {
-        rv = sem_destroy(&pMutex->u.sem);
-    } while (rv < 0 && errno == EINTR);
-    if (rv < 0) {
-        nss_MD_unix_map_default_error(errno);
-        return SECFailure;
-    }
-    return SECSuccess;
-}
-
-SECStatus
-sslMutex_Unlock(sslMutex* pMutex)
-{
-    int rv;
-    if (PR_FALSE == pMutex->isMultiProcess) {
-        return single_process_sslMutex_Unlock(pMutex);
-    }
-    do {
-        rv = sem_post(&pMutex->u.sem);
-    } while (rv < 0 && errno == EINTR);
-    if (rv < 0) {
-        nss_MD_unix_map_default_error(errno);
-        return SECFailure;
-    }
-    return SECSuccess;
-}
-
-SECStatus
-sslMutex_Lock(sslMutex* pMutex)
-{
-    int rv;
-    if (PR_FALSE == pMutex->isMultiProcess) {
-        return single_process_sslMutex_Lock(pMutex);
-    }
-    do {
-        rv = sem_wait(&pMutex->u.sem);
-    } while (rv < 0 && errno == EINTR);
-    if (rv < 0) {
-        nss_MD_unix_map_default_error(errno);
-        return SECFailure;
-    }
-    return SECSuccess;
-}
-
-#else
-
-SECStatus
-sslMutex_Init(sslMutex* pMutex, int shared)
-{
-    PR_ASSERT(pMutex);
-    pMutex->isMultiProcess = (PRBool)(shared != 0);
-    if (!shared) {
-        return single_process_sslMutex_Init(pMutex);
-    }
-    PORT_Assert(!("sslMutex_Init not implemented for multi-process applications !"));
-    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
-    return SECFailure;
-}
-
-SECStatus
-sslMutex_Destroy(sslMutex* pMutex, PRBool processLocal)
-{
-    PR_ASSERT(pMutex);
-    if (PR_FALSE == pMutex->isMultiProcess) {
-        return single_process_sslMutex_Destroy(pMutex);
-    }
-    PORT_Assert(!("sslMutex_Destroy not implemented for multi-process applications !"));
-    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
-    return SECFailure;
-}
-
-SECStatus
-sslMutex_Unlock(sslMutex* pMutex)
-{
-    PR_ASSERT(pMutex);
-    if (PR_FALSE == pMutex->isMultiProcess) {
-        return single_process_sslMutex_Unlock(pMutex);
-    }
-    PORT_Assert(!("sslMutex_Unlock not implemented for multi-process applications !"));
-    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
-    return SECFailure;
-}
-
-SECStatus
-sslMutex_Lock(sslMutex* pMutex)
-{
-    PR_ASSERT(pMutex);
-    if (PR_FALSE == pMutex->isMultiProcess) {
-        return single_process_sslMutex_Lock(pMutex);
-    }
-    PORT_Assert(!("sslMutex_Lock not implemented for multi-process applications !"));
-    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
-    return SECFailure;
-}
-
-#endif
-
-#endif
diff --git a/net/third_party/nss/ssl/sslmutex.h b/net/third_party/nss/ssl/sslmutex.h
deleted file mode 100644
index 7611148..0000000
--- a/net/third_party/nss/ssl/sslmutex.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#ifndef __SSLMUTEX_H_
-#define __SSLMUTEX_H_ 1
-
-/* What SSL really wants is portable process-shared unnamed mutexes in
- * shared memory, that have the property that if the process that holds
- * them dies, they are released automatically, and that (unlike fcntl
- * record locking) lock to the thread, not to the process.
- * NSPR doesn't provide that.
- * Windows has mutexes that meet that description, but they're not portable.
- * POSIX mutexes are not automatically released when the holder dies,
- * and other processes/threads cannot release the mutex on behalf of the
- * dead holder.
- * POSIX semaphores can be used to accomplish this on systems that implement
- * process-shared unnamed POSIX semaphores, because a watchdog thread can
- * discover and release semaphores that were held by a dead process.
- * On systems that do not support process-shared POSIX unnamed semaphores,
- * they can be emulated using pipes.
- * The performance cost of doing that is not yet measured.
- *
- * So, this API looks a lot like POSIX pthread mutexes.
- */
-
-#include "prtypes.h"
-#include "prlock.h"
-
-#if defined(NETBSD)
-#include <sys/param.h> /* for __NetBSD_Version__ */
-#endif
-
-#if defined(WIN32)
-
-#include <wtypes.h>
-
-typedef struct {
-    PRBool isMultiProcess;
-#ifdef WINNT
-    /* on WINNT we need both the PRLock and the Win32 mutex for fibers */
-    struct {
-#else
-    union {
-#endif
-        PRLock *sslLock;
-        HANDLE sslMutx;
-    } u;
-} sslMutex;
-
-typedef int sslPID;
-
-#elif defined(LINUX) || defined(AIX) || defined(BEOS) || defined(BSDI) || (defined(NETBSD) && __NetBSD_Version__ < 500000000) || defined(OPENBSD)
-
-#include <sys/types.h>
-#include "prtypes.h"
-
-typedef struct {
-    PRBool isMultiProcess;
-    union {
-        PRLock *sslLock;
-        struct {
-            int mPipes[3];
-            PRInt32 nWaiters;
-        } pipeStr;
-    } u;
-} sslMutex;
-typedef pid_t sslPID;
-
-/* other types of unix, except OS X */
-#elif defined(XP_UNIX) && !defined(DARWIN)
-
-#include <sys/types.h> /* for pid_t */
-#include <semaphore.h> /* for sem_t, and sem_* functions */
-
-typedef struct {
-    PRBool isMultiProcess;
-    union {
-        PRLock *sslLock;
-        sem_t sem;
-    } u;
-} sslMutex;
-
-typedef pid_t sslPID;
-
-#else /* no support for cross-process locking */
-
-/* what platform is this ?? */
-
-typedef struct {
-    PRBool isMultiProcess;
-    union {
-        PRLock *sslLock;
-        /* include cross-process locking mechanism here */
-    } u;
-} sslMutex;
-
-#ifdef DARWIN
-typedef pid_t sslPID;
-#else
-typedef int sslPID;
-#endif
-
-#endif
-
-#include "seccomon.h"
-
-SEC_BEGIN_PROTOS
-
-extern SECStatus sslMutex_Init(sslMutex *sem, int shared);
-
-/* If processLocal is set to true, then just free resources which are *only* associated
- * with the current process. Leave any shared resources (including the state of
- * shared memory) intact. */
-extern SECStatus sslMutex_Destroy(sslMutex *sem, PRBool processLocal);
-
-extern SECStatus sslMutex_Unlock(sslMutex *sem);
-
-extern SECStatus sslMutex_Lock(sslMutex *sem);
-
-#ifdef WINNT
-
-extern SECStatus sslMutex_2LevelInit(sslMutex *sem);
-
-#endif
-
-SEC_END_PROTOS
-
-#endif
diff --git a/net/third_party/nss/ssl/sslnonce.c b/net/third_party/nss/ssl/sslnonce.c
deleted file mode 100644
index 99591cc1..0000000
--- a/net/third_party/nss/ssl/sslnonce.c
+++ /dev/null
@@ -1,467 +0,0 @@
-/*
- * This file implements the CLIENT Session ID cache.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "cert.h"
-#include "pk11pub.h"
-#include "secitem.h"
-#include "ssl.h"
-#include "nss.h"
-
-#include "sslimpl.h"
-#include "sslproto.h"
-#include "nssilock.h"
-#if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS)
-#include <time.h>
-#endif
-
-PRUint32 ssl_sid_timeout = 100;
-PRUint32 ssl3_sid_timeout = 86400L; /* 24 hours */
-
-static sslSessionID *cache = NULL;
-static PZLock *cacheLock = NULL;
-
-/* sids can be in one of 4 states:
- *
- * never_cached,        created, but not yet put into cache.
- * in_client_cache,     in the client cache's linked list.
- * in_server_cache,     entry came from the server's cache file.
- * invalid_cache        has been removed from the cache.
- */
-
-#define LOCK_CACHE lock_cache()
-#define UNLOCK_CACHE PZ_Unlock(cacheLock)
-
-static PRCallOnceType lockOnce;
-
-/* FreeSessionCacheLocks is a callback from NSS_RegisterShutdown which destroys
- * the session cache locks on shutdown and resets them to their initial
- * state. */
-static SECStatus
-FreeSessionCacheLocks(void *appData, void *nssData)
-{
-    static const PRCallOnceType pristineCallOnce;
-    SECStatus rv;
-
-    if (!cacheLock) {
-        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
-        return SECFailure;
-    }
-
-    PZ_DestroyLock(cacheLock);
-    cacheLock = NULL;
-
-    rv = ssl_FreeSymWrapKeysLock();
-    if (rv != SECSuccess) {
-        return rv;
-    }
-
-    lockOnce = pristineCallOnce;
-    return SECSuccess;
-}
-
-/* InitSessionCacheLocks is called, protected by lockOnce, to create the
- * session cache locks. */
-static PRStatus
-InitSessionCacheLocks(void)
-{
-    SECStatus rv;
-
-    cacheLock = PZ_NewLock(nssILockCache);
-    if (cacheLock == NULL) {
-        return PR_FAILURE;
-    }
-    rv = ssl_InitSymWrapKeysLock();
-    if (rv != SECSuccess) {
-        PRErrorCode error = PORT_GetError();
-        PZ_DestroyLock(cacheLock);
-        cacheLock = NULL;
-        PORT_SetError(error);
-        return PR_FAILURE;
-    }
-
-    rv = NSS_RegisterShutdown(FreeSessionCacheLocks, NULL);
-    PORT_Assert(SECSuccess == rv);
-    if (SECSuccess != rv) {
-        return PR_FAILURE;
-    }
-    return PR_SUCCESS;
-}
-
-SECStatus
-ssl_InitSessionCacheLocks()
-{
-    return (PR_SUCCESS ==
-            PR_CallOnce(&lockOnce, InitSessionCacheLocks))
-               ? SECSuccess
-               : SECFailure;
-}
-
-static void
-lock_cache(void)
-{
-    ssl_InitSessionCacheLocks();
-    PZ_Lock(cacheLock);
-}
-
-/* BEWARE: This function gets called for both client and server SIDs !!
- * If the unreferenced sid is not in the cache, Free sid and its contents.
- */
-static void
-ssl_DestroySID(sslSessionID *sid)
-{
-    int i;
-    SSL_TRC(8, ("SSL: destroy sid: sid=0x%x cached=%d", sid, sid->cached));
-    PORT_Assert(sid->references == 0);
-    PORT_Assert(sid->cached != in_client_cache);
-
-    if (sid->version < SSL_LIBRARY_VERSION_3_0) {
-        SECITEM_ZfreeItem(&sid->u.ssl2.masterKey, PR_FALSE);
-        SECITEM_ZfreeItem(&sid->u.ssl2.cipherArg, PR_FALSE);
-    } else {
-        if (sid->u.ssl3.locked.sessionTicket.ticket.data) {
-            SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket,
-                             PR_FALSE);
-        }
-        if (sid->u.ssl3.srvName.data) {
-            SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE);
-        }
-        if (sid->u.ssl3.signedCertTimestamps.data) {
-            SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE);
-        }
-        if (sid->u.ssl3.originalHandshakeHash.data) {
-            SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE);
-        }
-
-        if (sid->u.ssl3.lock) {
-            PR_DestroyRWLock(sid->u.ssl3.lock);
-        }
-    }
-
-    if (sid->peerID != NULL)
-        PORT_Free((void *)sid->peerID); /* CONST */
-
-    if (sid->urlSvrName != NULL)
-        PORT_Free((void *)sid->urlSvrName); /* CONST */
-
-    if (sid->peerCert) {
-        CERT_DestroyCertificate(sid->peerCert);
-    }
-    for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) {
-	CERT_DestroyCertificate(sid->peerCertChain[i]);
-    }
-    if (sid->peerCertStatus.items) {
-        SECITEM_FreeArray(&sid->peerCertStatus, PR_FALSE);
-    }
-
-    if (sid->localCert) {
-        CERT_DestroyCertificate(sid->localCert);
-    }
-
-    PORT_ZFree(sid, sizeof(sslSessionID));
-}
-
-/* BEWARE: This function gets called for both client and server SIDs !!
- * Decrement reference count, and
- *    free sid if ref count is zero, and sid is not in the cache.
- * Does NOT remove from the cache first.
- * If the sid is still in the cache, it is left there until next time
- * the cache list is traversed.
- */
-static void
-ssl_FreeLockedSID(sslSessionID *sid)
-{
-    PORT_Assert(sid->references >= 1);
-    if (--sid->references == 0) {
-        ssl_DestroySID(sid);
-    }
-}
-
-/* BEWARE: This function gets called for both client and server SIDs !!
- * Decrement reference count, and
- *    free sid if ref count is zero, and sid is not in the cache.
- * Does NOT remove from the cache first.
- * These locks are necessary because the sid _might_ be in the cache list.
- */
-void
-ssl_FreeSID(sslSessionID *sid)
-{
-    LOCK_CACHE;
-    ssl_FreeLockedSID(sid);
-    UNLOCK_CACHE;
-}
-
-/************************************************************************/
-
-/*
-**  Lookup sid entry in cache by Address, port, and peerID string.
-**  If found, Increment reference count, and return pointer to caller.
-**  If it has timed out or ref count is zero, remove from list and free it.
-*/
-
-sslSessionID *
-ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID,
-              const char *urlSvrName)
-{
-    sslSessionID **sidp;
-    sslSessionID *sid;
-    PRUint32 now;
-
-    if (!urlSvrName)
-        return NULL;
-    now = ssl_Time();
-    LOCK_CACHE;
-    sidp = &cache;
-    while ((sid = *sidp) != 0) {
-        PORT_Assert(sid->cached == in_client_cache);
-        PORT_Assert(sid->references >= 1);
-
-        SSL_TRC(8, ("SSL: Lookup1: sid=0x%x", sid));
-
-        if (sid->expirationTime < now) {
-            /*
-            ** This session-id timed out.
-            ** Don't even care who it belongs to, blow it out of our cache.
-            */
-            SSL_TRC(7, ("SSL: lookup1, throwing sid out, age=%d refs=%d",
-                        now - sid->creationTime, sid->references));
-
-            *sidp = sid->next;                                      /* delink it from the list. */
-            sid->cached = invalid_cache;                            /* mark not on list. */
-            ssl_FreeLockedSID(sid);                                 /* drop ref count, free. */
-        } else if (!memcmp(&sid->addr, addr, sizeof(PRIPv6Addr)) && /* server IP addr matches */
-                   (sid->port == port) &&                           /* server port matches */
-                   /* proxy (peerID) matches */
-                   (((peerID == NULL) && (sid->peerID == NULL)) ||
-                    ((peerID != NULL) && (sid->peerID != NULL) &&
-                     PORT_Strcmp(sid->peerID, peerID) == 0)) &&
-                   /* is cacheable */
-                   (sid->version < SSL_LIBRARY_VERSION_3_0 ||
-                    sid->u.ssl3.keys.resumable) &&
-                   /* server hostname matches. */
-                   (sid->urlSvrName != NULL) &&
-                   (0 == PORT_Strcmp(urlSvrName, sid->urlSvrName))) {
-            /* Hit */
-            sid->lastAccessTime = now;
-            sid->references++;
-            break;
-        } else {
-            sidp = &sid->next;
-        }
-    }
-    UNLOCK_CACHE;
-    return sid;
-}
-
-/*
-** Add an sid to the cache or return a previously cached entry to the cache.
-** Although this is static, it is called via ss->sec.cache().
-*/
-static void
-CacheSID(sslSessionID *sid)
-{
-    PRUint32 expirationPeriod;
-
-    PORT_Assert(sid->cached == never_cached);
-
-    SSL_TRC(8, ("SSL: Cache: sid=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%04x "
-                "time=%x cached=%d",
-                sid, sid->cached, sid->addr.pr_s6_addr32[0],
-                sid->addr.pr_s6_addr32[1], sid->addr.pr_s6_addr32[2],
-                sid->addr.pr_s6_addr32[3], sid->port, sid->creationTime,
-                sid->cached));
-
-    if (!sid->urlSvrName) {
-        /* don't cache this SID because it can never be matched */
-        return;
-    }
-
-    /* XXX should be different trace for version 2 vs. version 3 */
-    if (sid->version < SSL_LIBRARY_VERSION_3_0) {
-        expirationPeriod = ssl_sid_timeout;
-        PRINT_BUF(8, (0, "sessionID:",
-                      sid->u.ssl2.sessionID, sizeof(sid->u.ssl2.sessionID)));
-        PRINT_BUF(8, (0, "masterKey:",
-                      sid->u.ssl2.masterKey.data, sid->u.ssl2.masterKey.len));
-        PRINT_BUF(8, (0, "cipherArg:",
-                      sid->u.ssl2.cipherArg.data, sid->u.ssl2.cipherArg.len));
-    } else {
-        if (sid->u.ssl3.sessionIDLength == 0 &&
-            sid->u.ssl3.locked.sessionTicket.ticket.data == NULL)
-            return;
-
-        /* Client generates the SessionID if this was a stateless resume. */
-        if (sid->u.ssl3.sessionIDLength == 0) {
-            SECStatus rv;
-            rv = PK11_GenerateRandom(sid->u.ssl3.sessionID,
-                                     SSL3_SESSIONID_BYTES);
-            if (rv != SECSuccess)
-                return;
-            sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES;
-        }
-        expirationPeriod = ssl3_sid_timeout;
-        PRINT_BUF(8, (0, "sessionID:",
-                      sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength));
-
-        sid->u.ssl3.lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, NULL);
-        if (!sid->u.ssl3.lock) {
-            return;
-        }
-    }
-    PORT_Assert(sid->creationTime != 0 && sid->expirationTime != 0);
-    if (!sid->creationTime)
-        sid->lastAccessTime = sid->creationTime = ssl_Time();
-    if (!sid->expirationTime)
-        sid->expirationTime = sid->creationTime + expirationPeriod;
-
-    /*
-     * Put sid into the cache.  Bump reference count to indicate that
-     * cache is holding a reference. Uncache will reduce the cache
-     * reference.
-     */
-    LOCK_CACHE;
-    sid->references++;
-    sid->cached = in_client_cache;
-    sid->next = cache;
-    cache = sid;
-    UNLOCK_CACHE;
-}
-
-/*
- * If sid "zap" is in the cache,
- *    removes sid from cache, and decrements reference count.
- * Caller must hold cache lock.
- */
-static void
-UncacheSID(sslSessionID *zap)
-{
-    sslSessionID **sidp = &cache;
-    sslSessionID *sid;
-
-    if (zap->cached != in_client_cache) {
-        return;
-    }
-
-    SSL_TRC(8, ("SSL: Uncache: zap=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%04x "
-                "time=%x cipher=%d",
-                zap, zap->cached, zap->addr.pr_s6_addr32[0],
-                zap->addr.pr_s6_addr32[1], zap->addr.pr_s6_addr32[2],
-                zap->addr.pr_s6_addr32[3], zap->port, zap->creationTime,
-                zap->u.ssl2.cipherType));
-    if (zap->version < SSL_LIBRARY_VERSION_3_0) {
-        PRINT_BUF(8, (0, "sessionID:",
-                      zap->u.ssl2.sessionID, sizeof(zap->u.ssl2.sessionID)));
-        PRINT_BUF(8, (0, "masterKey:",
-                      zap->u.ssl2.masterKey.data, zap->u.ssl2.masterKey.len));
-        PRINT_BUF(8, (0, "cipherArg:",
-                      zap->u.ssl2.cipherArg.data, zap->u.ssl2.cipherArg.len));
-    }
-
-    /* See if it's in the cache, if so nuke it */
-    while ((sid = *sidp) != 0) {
-        if (sid == zap) {
-            /*
-            ** Bingo. Reduce reference count by one so that when
-            ** everyone is done with the sid we can free it up.
-            */
-            *sidp = zap->next;
-            zap->cached = invalid_cache;
-            ssl_FreeLockedSID(zap);
-            return;
-        }
-        sidp = &sid->next;
-    }
-}
-
-/* If sid "zap" is in the cache,
- *    removes sid from cache, and decrements reference count.
- * Although this function is static, it is called externally via
- *    ss->sec.uncache().
- */
-static void
-LockAndUncacheSID(sslSessionID *zap)
-{
-    LOCK_CACHE;
-    UncacheSID(zap);
-    UNLOCK_CACHE;
-}
-
-/* choose client or server cache functions for this sslsocket. */
-void
-ssl_ChooseSessionIDProcs(sslSecurityInfo *sec)
-{
-    if (sec->isServer) {
-        sec->cache = ssl_sid_cache;
-        sec->uncache = ssl_sid_uncache;
-    } else {
-        sec->cache = CacheSID;
-        sec->uncache = LockAndUncacheSID;
-    }
-}
-
-/* wipe out the entire client session cache. */
-void
-SSL_ClearSessionCache(void)
-{
-    LOCK_CACHE;
-    while (cache != NULL)
-        UncacheSID(cache);
-    UNLOCK_CACHE;
-}
-
-/* returns an unsigned int containing the number of seconds in PR_Now() */
-PRUint32
-ssl_Time(void)
-{
-    PRUint32 myTime;
-#if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS)
-    myTime = time(NULL); /* accurate until the year 2038. */
-#else
-    /* portable, but possibly slower */
-    PRTime now;
-    PRInt64 ll;
-
-    now = PR_Now();
-    LL_I2L(ll, 1000000L);
-    LL_DIV(now, now, ll);
-    LL_L2UI(myTime, now);
-#endif
-    return myTime;
-}
-
-void
-ssl3_SetSIDSessionTicket(sslSessionID *sid,
-                         /*in/out*/ NewSessionTicket *newSessionTicket)
-{
-    PORT_Assert(sid);
-    PORT_Assert(newSessionTicket);
-    PORT_Assert(newSessionTicket->ticket.data);
-    PORT_Assert(newSessionTicket->ticket.len != 0);
-
-    /* if sid->u.ssl3.lock, we are updating an existing entry that is already
-     * cached or was once cached, so we need to acquire and release the write
-     * lock. Otherwise, this is a new session that isn't shared with anything
-     * yet, so no locking is needed.
-     */
-    if (sid->u.ssl3.lock) {
-        PR_RWLock_Wlock(sid->u.ssl3.lock);
-        if (sid->u.ssl3.locked.sessionTicket.ticket.data) {
-            SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket,
-                             PR_FALSE);
-        }
-    }
-
-    PORT_Assert(!sid->u.ssl3.locked.sessionTicket.ticket.data);
-
-    /* Do a shallow copy, moving the ticket data. */
-    sid->u.ssl3.locked.sessionTicket = *newSessionTicket;
-    newSessionTicket->ticket.data = NULL;
-    newSessionTicket->ticket.len = 0;
-
-    if (sid->u.ssl3.lock) {
-        PR_RWLock_Unlock(sid->u.ssl3.lock);
-    }
-}
diff --git a/net/third_party/nss/ssl/sslproto.h b/net/third_party/nss/ssl/sslproto.h
deleted file mode 100644
index 4fa260d..0000000
--- a/net/third_party/nss/ssl/sslproto.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Various and sundry protocol constants. DON'T CHANGE THESE. These values
- * are mostly defined by the SSL2, SSL3, or TLS protocol specifications.
- * Cipher kinds and ciphersuites are part of the public API.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef __sslproto_h_
-#define __sslproto_h_
-
-/* clang-format off */
-
-/* All versions less than 3_0 are treated as SSL version 2 */
-#define SSL_LIBRARY_VERSION_2                   0x0002
-#define SSL_LIBRARY_VERSION_3_0                 0x0300
-#define SSL_LIBRARY_VERSION_TLS_1_0             0x0301
-#define SSL_LIBRARY_VERSION_TLS_1_1             0x0302
-#define SSL_LIBRARY_VERSION_TLS_1_2             0x0303
-#define SSL_LIBRARY_VERSION_TLS_1_3             0x0304
-
-/* Note: this is the internal format, not the wire format */
-#define SSL_LIBRARY_VERSION_DTLS_1_0            0x0302
-#define SSL_LIBRARY_VERSION_DTLS_1_2            0x0303
-#define SSL_LIBRARY_VERSION_DTLS_1_3            0x0304
-
-/* deprecated old name */
-#define SSL_LIBRARY_VERSION_3_1_TLS SSL_LIBRARY_VERSION_TLS_1_0
-
-/* The DTLS versions used in the spec */
-#define SSL_LIBRARY_VERSION_DTLS_1_0_WIRE       ((~0x0100) & 0xffff)
-#define SSL_LIBRARY_VERSION_DTLS_1_2_WIRE       ((~0x0102) & 0xffff)
-#define SSL_LIBRARY_VERSION_DTLS_1_3_WIRE       ((~0x0103) & 0xffff)
-
-/* Header lengths of some of the messages */
-#define SSL_HL_ERROR_HBYTES                     3
-#define SSL_HL_CLIENT_HELLO_HBYTES              9
-#define SSL_HL_CLIENT_MASTER_KEY_HBYTES         10
-#define SSL_HL_CLIENT_FINISHED_HBYTES           1
-#define SSL_HL_SERVER_HELLO_HBYTES              11
-#define SSL_HL_SERVER_VERIFY_HBYTES             1
-#define SSL_HL_SERVER_FINISHED_HBYTES           1
-#define SSL_HL_REQUEST_CERTIFICATE_HBYTES       2
-#define SSL_HL_CLIENT_CERTIFICATE_HBYTES        6
-
-/* Security handshake protocol codes */
-#define SSL_MT_ERROR                            0
-#define SSL_MT_CLIENT_HELLO                     1
-#define SSL_MT_CLIENT_MASTER_KEY                2
-#define SSL_MT_CLIENT_FINISHED                  3
-#define SSL_MT_SERVER_HELLO                     4
-#define SSL_MT_SERVER_VERIFY                    5
-#define SSL_MT_SERVER_FINISHED                  6
-#define SSL_MT_REQUEST_CERTIFICATE              7
-#define SSL_MT_CLIENT_CERTIFICATE               8
-
-/* Certificate types */
-#define SSL_CT_X509_CERTIFICATE                 0x01
-#if 0 /* XXX Not implemented yet */
-#define SSL_PKCS6_CERTIFICATE                   0x02
-#endif
-#define SSL_AT_MD5_WITH_RSA_ENCRYPTION          0x01
-
-/* Error codes */
-#define SSL_PE_NO_CYPHERS                       0x0001
-#define SSL_PE_NO_CERTIFICATE                   0x0002
-#define SSL_PE_BAD_CERTIFICATE                  0x0004
-#define SSL_PE_UNSUPPORTED_CERTIFICATE_TYPE     0x0006
-
-/* Cypher kinds (not the spec version!) */
-#define SSL_CK_RC4_128_WITH_MD5                 0x01
-#define SSL_CK_RC4_128_EXPORT40_WITH_MD5        0x02
-#define SSL_CK_RC2_128_CBC_WITH_MD5             0x03
-#define SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5    0x04
-#define SSL_CK_IDEA_128_CBC_WITH_MD5            0x05
-#define SSL_CK_DES_64_CBC_WITH_MD5              0x06
-#define SSL_CK_DES_192_EDE3_CBC_WITH_MD5        0x07
-
-/* Cipher enables.  These are used only for SSL_EnableCipher
- * These values define the SSL2 suites, and do not colide with the
- * SSL3 Cipher suites defined below.
- */
-#define SSL_EN_RC4_128_WITH_MD5                 0xFF01
-#define SSL_EN_RC4_128_EXPORT40_WITH_MD5        0xFF02
-#define SSL_EN_RC2_128_CBC_WITH_MD5             0xFF03
-#define SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5    0xFF04
-#define SSL_EN_IDEA_128_CBC_WITH_MD5            0xFF05
-#define SSL_EN_DES_64_CBC_WITH_MD5              0xFF06
-#define SSL_EN_DES_192_EDE3_CBC_WITH_MD5        0xFF07
-
-/* Deprecated SSL 3.0 & libssl names replaced by IANA-registered TLS names. */
-#ifndef SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES
-#define SSL_NULL_WITH_NULL_NULL                TLS_NULL_WITH_NULL_NULL
-#define SSL_RSA_WITH_NULL_MD5                  TLS_RSA_WITH_NULL_MD5
-#define SSL_RSA_WITH_NULL_SHA                  TLS_RSA_WITH_NULL_SHA
-#define SSL_RSA_EXPORT_WITH_RC4_40_MD5         TLS_RSA_EXPORT_WITH_RC4_40_MD5
-#define SSL_RSA_WITH_RC4_128_MD5               TLS_RSA_WITH_RC4_128_MD5
-#define SSL_RSA_WITH_RC4_128_SHA               TLS_RSA_WITH_RC4_128_SHA
-#define SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5     TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
-#define SSL_RSA_WITH_IDEA_CBC_SHA              TLS_RSA_WITH_IDEA_CBC_SHA
-#define SSL_RSA_EXPORT_WITH_DES40_CBC_SHA      TLS_RSA_EXPORT_WITH_DES40_CBC_SHA
-#define SSL_RSA_WITH_DES_CBC_SHA               TLS_RSA_WITH_DES_CBC_SHA
-#define SSL_RSA_WITH_3DES_EDE_CBC_SHA          TLS_RSA_WITH_3DES_EDE_CBC_SHA
-#define SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA   TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
-#define SSL_DH_DSS_WITH_DES_CBC_SHA            TLS_DH_DSS_WITH_DES_CBC_SHA
-#define SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA       TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA
-#define SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA   TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
-#define SSL_DH_RSA_WITH_DES_CBC_SHA            TLS_DH_RSA_WITH_DES_CBC_SHA
-#define SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA       TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA
-#define SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA  TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
-#define SSL_DHE_DSS_WITH_DES_CBC_SHA           TLS_DHE_DSS_WITH_DES_CBC_SHA
-#define SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA      TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
-#define SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA  TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
-#define SSL_DHE_RSA_WITH_DES_CBC_SHA           TLS_DHE_RSA_WITH_DES_CBC_SHA
-#define SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA      TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
-#define SSL_DH_ANON_WITH_RC4_128_MD5           TLS_DH_anon_WITH_RC4_128_MD5
-#define SSL_DH_ANON_EXPORT_WITH_DES40_CBC_SHA  TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA
-#define SSL_DH_ANON_WITH_DES_CBC_SHA           TLS_DH_anon_WITH_DES_CBC_SHA
-#define SSL_DH_ANON_WITH_3DES_EDE_CBC_SHA      TLS_DH_anon_WITH_3DES_EDE_CBC_SHA
-#define SSL_DH_ANON_EXPORT_WITH_RC4_40_MD5     TLS_DH_anon_EXPORT_WITH_RC4_40_MD5
-#define TLS_DH_ANON_WITH_AES_128_CBC_SHA       TLS_DH_anon_WITH_AES_128_CBC_SHA
-#define TLS_DH_ANON_WITH_AES_256_CBC_SHA       TLS_DH_anon_WITH_AES_256_CBC_SHA
-#define TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA  TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA
-#define TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA  TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA
-#endif
-
-#define TLS_NULL_WITH_NULL_NULL                 0x0000
-
-#define TLS_RSA_WITH_NULL_MD5                   0x0001
-#define TLS_RSA_WITH_NULL_SHA                   0x0002
-#define TLS_RSA_EXPORT_WITH_RC4_40_MD5          0x0003
-#define TLS_RSA_WITH_RC4_128_MD5                0x0004
-#define TLS_RSA_WITH_RC4_128_SHA                0x0005
-#define TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5      0x0006
-#define TLS_RSA_WITH_IDEA_CBC_SHA               0x0007
-#define TLS_RSA_EXPORT_WITH_DES40_CBC_SHA       0x0008
-#define TLS_RSA_WITH_DES_CBC_SHA                0x0009
-#define TLS_RSA_WITH_3DES_EDE_CBC_SHA           0x000a
-
-#define TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA    0x000b
-#define TLS_DH_DSS_WITH_DES_CBC_SHA             0x000c
-#define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA        0x000d
-#define TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA    0x000e
-#define TLS_DH_RSA_WITH_DES_CBC_SHA             0x000f
-#define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA        0x0010
-
-#define TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA   0x0011
-#define TLS_DHE_DSS_WITH_DES_CBC_SHA            0x0012
-#define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA       0x0013
-#define TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA   0x0014
-#define TLS_DHE_RSA_WITH_DES_CBC_SHA            0x0015
-#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA       0x0016
-
-#define TLS_DH_anon_EXPORT_WITH_RC4_40_MD5      0x0017
-#define TLS_DH_anon_WITH_RC4_128_MD5            0x0018
-#define TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA   0x0019
-#define TLS_DH_anon_WITH_DES_CBC_SHA            0x001a
-#define TLS_DH_anon_WITH_3DES_EDE_CBC_SHA       0x001b
-
-#define SSL_FORTEZZA_DMS_WITH_NULL_SHA          0x001c /* deprecated */
-#define SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA  0x001d /* deprecated */
-#define SSL_FORTEZZA_DMS_WITH_RC4_128_SHA       0x001e /* deprecated */
-
-#define TLS_RSA_WITH_AES_128_CBC_SHA            0x002F
-#define TLS_DH_DSS_WITH_AES_128_CBC_SHA         0x0030
-#define TLS_DH_RSA_WITH_AES_128_CBC_SHA         0x0031
-#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA        0x0032
-#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA        0x0033
-#define TLS_DH_anon_WITH_AES_128_CBC_SHA        0x0034
-
-#define TLS_RSA_WITH_AES_256_CBC_SHA            0x0035
-#define TLS_DH_DSS_WITH_AES_256_CBC_SHA         0x0036
-#define TLS_DH_RSA_WITH_AES_256_CBC_SHA         0x0037
-#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA        0x0038
-#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA        0x0039
-#define TLS_DH_anon_WITH_AES_256_CBC_SHA        0x003A
-#define TLS_RSA_WITH_NULL_SHA256                0x003B
-#define TLS_RSA_WITH_AES_128_CBC_SHA256         0x003C
-#define TLS_RSA_WITH_AES_256_CBC_SHA256         0x003D
-
-#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA256     0x0040
-#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA       0x0041
-#define TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA    0x0042
-#define TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA    0x0043
-#define TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA   0x0044
-#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA   0x0045
-#define TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA   0x0046
-
-#define TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA     0x0062
-#define TLS_RSA_EXPORT1024_WITH_RC4_56_SHA      0x0064
-
-#define TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA 0x0063
-#define TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA  0x0065
-#define TLS_DHE_DSS_WITH_RC4_128_SHA            0x0066
-#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256     0x0067
-#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA256     0x006A
-#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256     0x006B
-
-#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA       0x0084
-#define TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA    0x0085
-#define TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA    0x0086
-#define TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA   0x0087
-#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA   0x0088
-#define TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA   0x0089
-
-#define TLS_RSA_WITH_SEED_CBC_SHA               0x0096
-
-#define TLS_RSA_WITH_AES_128_GCM_SHA256         0x009C
-#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256     0x009E
-#define TLS_DHE_DSS_WITH_AES_128_GCM_SHA256     0x00A2
-
-/* TLS "Signaling Cipher Suite Value" (SCSV). May be requested by client.
- * Must NEVER be chosen by server.  SSL 3.0 server acknowledges by sending
- * back an empty Renegotiation Info (RI) server hello extension.
- */
-#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV       0x00FF
-
-/* TLS_FALLBACK_SCSV is a signaling cipher suite value that indicates that a
- * handshake is the result of TLS version fallback.
- */
-#define TLS_FALLBACK_SCSV                       0x5600
-
-/* Cipher Suite Values starting with 0xC000 are defined in informational
- * RFCs.
- */
-#define TLS_ECDH_ECDSA_WITH_NULL_SHA            0xC001
-#define TLS_ECDH_ECDSA_WITH_RC4_128_SHA         0xC002
-#define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA    0xC003
-#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA     0xC004
-#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA     0xC005
-
-#define TLS_ECDHE_ECDSA_WITH_NULL_SHA           0xC006
-#define TLS_ECDHE_ECDSA_WITH_RC4_128_SHA        0xC007
-#define TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA   0xC008
-#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA    0xC009
-#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA    0xC00A
-
-#define TLS_ECDH_RSA_WITH_NULL_SHA              0xC00B
-#define TLS_ECDH_RSA_WITH_RC4_128_SHA           0xC00C
-#define TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA      0xC00D
-#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA       0xC00E
-#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA       0xC00F
-
-#define TLS_ECDHE_RSA_WITH_NULL_SHA             0xC010
-#define TLS_ECDHE_RSA_WITH_RC4_128_SHA          0xC011
-#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA     0xC012
-#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA      0xC013
-#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA      0xC014
-
-#define TLS_ECDH_anon_WITH_NULL_SHA             0xC015
-#define TLS_ECDH_anon_WITH_RC4_128_SHA          0xC016
-#define TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA     0xC017
-#define TLS_ECDH_anon_WITH_AES_128_CBC_SHA      0xC018
-#define TLS_ECDH_anon_WITH_AES_256_CBC_SHA      0xC019
-
-#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023
-#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256   0xC027
-
-#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B
-#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256  0xC02D
-#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256   0xC02F
-#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256    0xC031
-
-#define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256   0xCCA8
-#define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9
-#define TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256     0xCCAA
-
-/* Netscape "experimental" cipher suites. */
-#define SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA   0xffe0
-#define SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA        0xffe1
-
-/* New non-experimental openly spec'ed versions of those cipher suites. */
-#define SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA      0xfeff
-#define SSL_RSA_FIPS_WITH_DES_CBC_SHA           0xfefe
-
-/* DTLS-SRTP cipher suites from RFC 5764 */
-/* If you modify this, also modify MAX_DTLS_SRTP_CIPHER_SUITES in sslimpl.h */
-#define SRTP_AES128_CM_HMAC_SHA1_80             0x0001
-#define SRTP_AES128_CM_HMAC_SHA1_32             0x0002
-#define SRTP_NULL_HMAC_SHA1_80                  0x0005
-#define SRTP_NULL_HMAC_SHA1_32                  0x0006
-
-/* clang-format on */
-
-#endif /* __sslproto_h_ */
diff --git a/net/third_party/nss/ssl/sslreveal.c b/net/third_party/nss/ssl/sslreveal.c
deleted file mode 100644
index 4c124a1d..0000000
--- a/net/third_party/nss/ssl/sslreveal.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Accessor functions for SSLSocket private members.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "cert.h"
-#include "ssl.h"
-#include "certt.h"
-#include "sslimpl.h"
-
-/* given PRFileDesc, returns a copy of certificate associated with the socket
- * the caller should delete the cert when done with SSL_DestroyCertificate
- */
-CERTCertificate *
-SSL_RevealCert(PRFileDesc *fd)
-{
-    CERTCertificate *cert = NULL;
-    sslSocket *sslsocket = NULL;
-
-    sslsocket = ssl_FindSocket(fd);
-
-    /* CERT_DupCertificate increases reference count and returns pointer to
-     * the same cert
-     */
-    if (sslsocket && sslsocket->sec.peerCert)
-        cert = CERT_DupCertificate(sslsocket->sec.peerCert);
-
-    return cert;
-}
-
-/* given PRFileDesc, returns a pointer to PinArg associated with the socket
- */
-void *
-SSL_RevealPinArg(PRFileDesc *fd)
-{
-    sslSocket *sslsocket = NULL;
-    void *PinArg = NULL;
-
-    sslsocket = ssl_FindSocket(fd);
-
-    /* is pkcs11PinArg part of the sslSocket or sslSecurityInfo ? */
-    if (sslsocket)
-        PinArg = sslsocket->pkcs11PinArg;
-
-    return PinArg;
-}
-
-/* given PRFileDesc, returns a pointer to the URL associated with the socket
- * the caller should free url when done
- */
-char *
-SSL_RevealURL(PRFileDesc *fd)
-{
-    sslSocket *sslsocket = NULL;
-    char *url = NULL;
-
-    sslsocket = ssl_FindSocket(fd);
-
-    if (sslsocket && sslsocket->url)
-        url = PL_strdup(sslsocket->url);
-
-    return url;
-}
-
-/* given PRFileDesc, returns status information related to extensions
- * negotiated with peer during the handshake.
- */
-
-SECStatus
-SSL_HandshakeNegotiatedExtension(PRFileDesc *socket,
-                                 SSLExtensionType extId,
-                                 PRBool *pYes)
-{
-    /* some decisions derived from SSL_GetChannelInfo */
-    sslSocket *sslsocket = NULL;
-
-    if (!pYes) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    sslsocket = ssl_FindSocket(socket);
-    if (!sslsocket) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in HandshakeNegotiatedExtension",
-                 SSL_GETPID(), socket));
-        return SECFailure;
-    }
-
-    *pYes = PR_FALSE;
-
-    /* according to public API SSL_GetChannelInfo, this doesn't need a lock */
-    if (sslsocket->opt.useSecurity) {
-        if (sslsocket->ssl3.initialized) { /* SSL3 and TLS */
-            /* now we know this socket went through ssl3_InitState() and
-             * ss->xtnData got initialized, which is the only member accessed by
-             * ssl3_ExtensionNegotiated();
-             * Member xtnData appears to get accessed in functions that handle
-             * the handshake (hello messages and extension sending),
-             * therefore the handshake lock should be sufficient.
-             */
-            ssl_GetSSL3HandshakeLock(sslsocket);
-            *pYes = ssl3_ExtensionNegotiated(sslsocket, extId);
-            ssl_ReleaseSSL3HandshakeLock(sslsocket);
-        }
-    }
-
-    return SECSuccess;
-}
diff --git a/net/third_party/nss/ssl/sslsecur.c b/net/third_party/nss/ssl/sslsecur.c
deleted file mode 100644
index 129f1f3..0000000
--- a/net/third_party/nss/ssl/sslsecur.c
+++ /dev/null
@@ -1,1739 +0,0 @@
-/*
- * Various SSL functions.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "cert.h"
-#include "secitem.h"
-#include "keyhi.h"
-#include "ssl.h"
-#include "sslimpl.h"
-#include "sslproto.h"
-#include "secoid.h"   /* for SECOID_GetALgorithmTag */
-#include "pk11func.h" /* for PK11_GenerateRandom */
-#include "nss.h"      /* for NSS_RegisterShutdown */
-#include "prinit.h"   /* for PR_CallOnceWithArg */
-
-#define MAX_BLOCK_CYPHER_SIZE 32
-
-#define TEST_FOR_FAILURE /* reminder */
-#define SET_ERROR_CODE   /* reminder */
-
-/* Returns a SECStatus: SECSuccess or SECFailure, NOT SECWouldBlock.
- *
- * Currently, the list of functions called through ss->handshake is:
- *
- * In sslsocks.c:
- *  SocksGatherRecord
- *  SocksHandleReply
- *  SocksStartGather
- *
- * In sslcon.c:
- *  ssl_GatherRecord1stHandshake
- *  ssl2_HandleClientSessionKeyMessage
- *  ssl2_HandleMessage
- *  ssl2_HandleVerifyMessage
- *  ssl2_BeginClientHandshake
- *  ssl2_BeginServerHandshake
- *  ssl2_HandleClientHelloMessage
- *  ssl2_HandleServerHelloMessage
- *
- * The ss->handshake function returns SECWouldBlock under these conditions:
- * 1.   ssl_GatherRecord1stHandshake called ssl2_GatherData which read in
- *  the beginning of an SSL v3 hello message and returned SECWouldBlock
- *  to switch to SSL v3 handshake processing.
- *
- * 2.   ssl2_HandleClientHelloMessage discovered version 3.0 in the incoming
- *  v2 client hello msg, and called ssl3_HandleV2ClientHello which
- *  returned SECWouldBlock.
- *
- * 3.   SECWouldBlock was returned by one of the callback functions, via
- *  one of these paths:
- * -    ssl2_HandleMessage() -> ssl2_HandleRequestCertificate() ->
- *  ss->getClientAuthData()
- *
- * -    ssl2_HandleServerHelloMessage() -> ss->handleBadCert()
- *
- * -    ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() ->
- *  ssl3_HandleRecord() -> ssl3_HandleHandshake() ->
- *  ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificate() ->
- *  ss->handleBadCert()
- *
- * -    ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() ->
- *  ssl3_HandleRecord() -> ssl3_HandleHandshake() ->
- *  ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificateRequest() ->
- *  ss->getClientAuthData()
- *
- * Called from: SSL_ForceHandshake  (below),
- *              ssl_SecureRecv      (below) and
- *              ssl_SecureSend      (below)
- *    from: WaitForResponse     in sslsocks.c
- *          ssl_SocksRecv       in sslsocks.c
- *              ssl_SocksSend       in sslsocks.c
- *
- * Caller must hold the (write) handshakeLock.
- */
-int
-ssl_Do1stHandshake(sslSocket *ss)
-{
-    int rv = SECSuccess;
-    int loopCount = 0;
-
-    do {
-        PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-        PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss));
-        PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss));
-        PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss));
-
-        if (ss->handshake == 0) {
-            /* Previous handshake finished. Switch to next one */
-            ss->handshake = ss->nextHandshake;
-            ss->nextHandshake = 0;
-        }
-        if (ss->handshake == 0) {
-            /* Previous handshake finished. Switch to security handshake */
-            ss->handshake = ss->securityHandshake;
-            ss->securityHandshake = 0;
-        }
-        if (ss->handshake == 0) {
-            /* for v3 this is done in ssl3_FinishHandshake */
-            if (!ss->firstHsDone && ss->version < SSL_LIBRARY_VERSION_3_0) {
-                ssl_GetRecvBufLock(ss);
-                ss->gs.recordLen = 0;
-                ssl_FinishHandshake(ss);
-                ssl_ReleaseRecvBufLock(ss);
-            }
-            break;
-        }
-        rv = (*ss->handshake)(ss);
-        ++loopCount;
-        /* This code must continue to loop on SECWouldBlock,
-         * or any positive value.   See XXX_1 comments.
-         */
-    } while (rv != SECFailure); /* was (rv >= 0); XXX_1 */
-
-    PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss));
-
-    if (rv == SECWouldBlock) {
-        PORT_SetError(PR_WOULD_BLOCK_ERROR);
-        rv = SECFailure;
-    }
-    return rv;
-}
-
-void
-ssl_FinishHandshake(sslSocket *ss)
-{
-    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-
-    SSL_TRC(3, ("%d: SSL[%d]: handshake is completed", SSL_GETPID(), ss->fd));
-
-    ss->firstHsDone = PR_TRUE;
-    ss->enoughFirstHsDone = PR_TRUE;
-    ss->gs.writeOffset = 0;
-    ss->gs.readOffset = 0;
-
-    if (ss->handshakeCallback) {
-        PORT_Assert(ss->version < SSL_LIBRARY_VERSION_3_0 ||
-                    (ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
-                        ssl_preinfo_all);
-        (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
-    }
-}
-
-/*
- * Handshake function that blocks.  Used to force a
- * retry on a connection on the next read/write.
- */
-static SECStatus
-ssl3_AlwaysBlock(sslSocket *ss)
-{
-    PORT_SetError(PR_WOULD_BLOCK_ERROR); /* perhaps redundant. */
-    return SECWouldBlock;
-}
-
-/*
- * set the initial handshake state machine to block
- */
-void
-ssl3_SetAlwaysBlock(sslSocket *ss)
-{
-    if (!ss->firstHsDone) {
-        ss->handshake = ssl3_AlwaysBlock;
-        ss->nextHandshake = 0;
-    }
-}
-
-static SECStatus
-ssl_SetTimeout(PRFileDesc *fd, PRIntervalTime timeout)
-{
-    sslSocket *ss;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SetTimeout", SSL_GETPID(), fd));
-        return SECFailure;
-    }
-    SSL_LOCK_READER(ss);
-    ss->rTimeout = timeout;
-    if (ss->opt.fdx) {
-        SSL_LOCK_WRITER(ss);
-    }
-    ss->wTimeout = timeout;
-    if (ss->opt.fdx) {
-        SSL_UNLOCK_WRITER(ss);
-    }
-    SSL_UNLOCK_READER(ss);
-    return SECSuccess;
-}
-
-/* Acquires and releases HandshakeLock.
-*/
-SECStatus
-SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
-{
-    sslSocket *ss;
-    SECStatus status;
-    PRNetAddr addr;
-
-    ss = ssl_FindSocket(s);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in ResetHandshake", SSL_GETPID(), s));
-        return SECFailure;
-    }
-
-    /* Don't waste my time */
-    if (!ss->opt.useSecurity)
-        return SECSuccess;
-
-    SSL_LOCK_READER(ss);
-    SSL_LOCK_WRITER(ss);
-
-    /* Reset handshake state */
-    ssl_Get1stHandshakeLock(ss);
-
-    ss->firstHsDone = PR_FALSE;
-    ss->enoughFirstHsDone = PR_FALSE;
-    if (asServer) {
-        ss->handshake = ssl2_BeginServerHandshake;
-        ss->handshaking = sslHandshakingAsServer;
-    } else {
-        ss->handshake = ssl2_BeginClientHandshake;
-        ss->handshaking = sslHandshakingAsClient;
-    }
-    ss->nextHandshake = 0;
-    ss->securityHandshake = 0;
-
-    ssl_GetRecvBufLock(ss);
-    status = ssl_InitGather(&ss->gs);
-    ssl_ReleaseRecvBufLock(ss);
-
-    ssl_GetSSL3HandshakeLock(ss);
-    ss->ssl3.hs.canFalseStart = PR_FALSE;
-    ss->ssl3.hs.restartTarget = NULL;
-
-    /*
-    ** Blow away old security state and get a fresh setup.
-    */
-    ssl_GetXmitBufLock(ss);
-    ssl_ResetSecurityInfo(&ss->sec, PR_TRUE);
-    status = ssl_CreateSecurityInfo(ss);
-    ssl_ReleaseXmitBufLock(ss);
-
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    ssl_Release1stHandshakeLock(ss);
-
-    if (!ss->TCPconnected)
-        ss->TCPconnected = (PR_SUCCESS == ssl_DefGetpeername(ss, &addr));
-
-    SSL_UNLOCK_WRITER(ss);
-    SSL_UNLOCK_READER(ss);
-
-    return status;
-}
-
-/* For SSLv2, does nothing but return an error.
-** For SSLv3, flushes SID cache entry (if requested),
-** and then starts new client hello or hello request.
-** Acquires and releases HandshakeLock.
-*/
-SECStatus
-SSL_ReHandshake(PRFileDesc *fd, PRBool flushCache)
-{
-    sslSocket *ss;
-    SECStatus rv;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in RedoHandshake", SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (!ss->opt.useSecurity)
-        return SECSuccess;
-
-    ssl_Get1stHandshakeLock(ss);
-
-    /* SSL v2 protocol does not support subsequent handshakes. */
-    if (ss->version < SSL_LIBRARY_VERSION_3_0) {
-        PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
-        rv = SECFailure;
-    } else {
-        ssl_GetSSL3HandshakeLock(ss);
-        rv = ssl3_RedoHandshake(ss, flushCache); /* force full handshake. */
-        ssl_ReleaseSSL3HandshakeLock(ss);
-    }
-
-    ssl_Release1stHandshakeLock(ss);
-
-    return rv;
-}
-
-/*
-** Same as above, but with an I/O timeout.
- */
-SSL_IMPORT SECStatus
-SSL_ReHandshakeWithTimeout(PRFileDesc *fd,
-                           PRBool flushCache,
-                           PRIntervalTime timeout)
-{
-    if (SECSuccess != ssl_SetTimeout(fd, timeout)) {
-        return SECFailure;
-    }
-    return SSL_ReHandshake(fd, flushCache);
-}
-
-SECStatus
-SSL_RedoHandshake(PRFileDesc *fd)
-{
-    return SSL_ReHandshake(fd, PR_TRUE);
-}
-
-/* Register an application callback to be called when SSL handshake completes.
-** Acquires and releases HandshakeLock.
-*/
-SECStatus
-SSL_HandshakeCallback(PRFileDesc *fd, SSLHandshakeCallback cb,
-                      void *client_data)
-{
-    sslSocket *ss;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in HandshakeCallback",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (!ss->opt.useSecurity) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    ssl_Get1stHandshakeLock(ss);
-    ssl_GetSSL3HandshakeLock(ss);
-
-    ss->handshakeCallback = cb;
-    ss->handshakeCallbackData = client_data;
-
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    ssl_Release1stHandshakeLock(ss);
-
-    return SECSuccess;
-}
-
-/* Register an application callback to be called when false start may happen.
-** Acquires and releases HandshakeLock.
-*/
-SECStatus
-SSL_SetCanFalseStartCallback(PRFileDesc *fd, SSLCanFalseStartCallback cb,
-                             void *arg)
-{
-    sslSocket *ss;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetCanFalseStartCallback",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (!ss->opt.useSecurity) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    ssl_Get1stHandshakeLock(ss);
-    ssl_GetSSL3HandshakeLock(ss);
-
-    ss->canFalseStartCallback = cb;
-    ss->canFalseStartCallbackData = arg;
-
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    ssl_Release1stHandshakeLock(ss);
-
-    return SECSuccess;
-}
-
-SECStatus
-SSL_RecommendedCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart)
-{
-    sslSocket *ss;
-
-    *canFalseStart = PR_FALSE;
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RecommendedCanFalseStart",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (!ss->ssl3.initialized) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    if (ss->version < SSL_LIBRARY_VERSION_3_0) {
-        PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
-        return SECFailure;
-    }
-
-    /* Require a forward-secret key exchange. */
-    *canFalseStart = ss->ssl3.hs.kea_def->kea == kea_dhe_dss ||
-                     ss->ssl3.hs.kea_def->kea == kea_dhe_rsa ||
-                     ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa ||
-                     ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa;
-
-    return SECSuccess;
-}
-
-/* Try to make progress on an SSL handshake by attempting to read the
-** next handshake from the peer, and sending any responses.
-** For non-blocking sockets, returns PR_ERROR_WOULD_BLOCK  if it cannot
-** read the next handshake from the underlying socket.
-** For SSLv2, returns when handshake is complete or fatal error occurs.
-** For SSLv3, returns when handshake is complete, or application data has
-** arrived that must be taken by application before handshake can continue,
-** or a fatal error occurs.
-** Application should use handshake completion callback to tell which.
-*/
-SECStatus
-SSL_ForceHandshake(PRFileDesc *fd)
-{
-    sslSocket *ss;
-    SECStatus rv = SECFailure;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in ForceHandshake",
-                 SSL_GETPID(), fd));
-        return rv;
-    }
-
-    /* Don't waste my time */
-    if (!ss->opt.useSecurity)
-        return SECSuccess;
-
-    if (!ssl_SocketIsBlocking(ss)) {
-        ssl_GetXmitBufLock(ss);
-        if (ss->pendingBuf.len != 0) {
-            int sent = ssl_SendSavedWriteData(ss);
-            if ((sent < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) {
-                ssl_ReleaseXmitBufLock(ss);
-                return SECFailure;
-            }
-        }
-        ssl_ReleaseXmitBufLock(ss);
-    }
-
-    ssl_Get1stHandshakeLock(ss);
-
-    if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
-        int gatherResult;
-
-        ssl_GetRecvBufLock(ss);
-        gatherResult = ssl3_GatherCompleteHandshake(ss, 0);
-        ssl_ReleaseRecvBufLock(ss);
-        if (gatherResult > 0) {
-            rv = SECSuccess;
-        } else if (gatherResult == 0) {
-            PORT_SetError(PR_END_OF_FILE_ERROR);
-        } else if (gatherResult == SECWouldBlock) {
-            PORT_SetError(PR_WOULD_BLOCK_ERROR);
-        }
-    } else if (!ss->firstHsDone) {
-        rv = ssl_Do1stHandshake(ss);
-    } else {
-        /* tried to force handshake on an SSL 2 socket that has
-        ** already completed the handshake. */
-        rv = SECSuccess; /* just pretend we did it. */
-    }
-
-    ssl_Release1stHandshakeLock(ss);
-
-    return rv;
-}
-
-/*
- ** Same as above, but with an I/O timeout.
- */
-SSL_IMPORT SECStatus
-SSL_ForceHandshakeWithTimeout(PRFileDesc *fd,
-                              PRIntervalTime timeout)
-{
-    if (SECSuccess != ssl_SetTimeout(fd, timeout)) {
-        return SECFailure;
-    }
-    return SSL_ForceHandshake(fd);
-}
-
-/************************************************************************/
-
-/*
-** Grow a buffer to hold newLen bytes of data.
-** Called for both recv buffers and xmit buffers.
-** Caller must hold xmitBufLock or recvBufLock, as appropriate.
-*/
-SECStatus
-sslBuffer_Grow(sslBuffer *b, unsigned int newLen)
-{
-    newLen = PR_MAX(newLen, MAX_FRAGMENT_LENGTH + 2048);
-    if (newLen > b->space) {
-        unsigned char *newBuf;
-        if (b->buf) {
-            newBuf = (unsigned char *)PORT_Realloc(b->buf, newLen);
-        } else {
-            newBuf = (unsigned char *)PORT_Alloc(newLen);
-        }
-        if (!newBuf) {
-            return SECFailure;
-        }
-        SSL_TRC(10, ("%d: SSL: grow buffer from %d to %d",
-                     SSL_GETPID(), b->space, newLen));
-        b->buf = newBuf;
-        b->space = newLen;
-    }
-    return SECSuccess;
-}
-
-SECStatus
-sslBuffer_Append(sslBuffer *b, const void *data, unsigned int len)
-{
-    unsigned int newLen = b->len + len;
-    SECStatus rv;
-
-    rv = sslBuffer_Grow(b, newLen);
-    if (rv != SECSuccess)
-        return rv;
-    PORT_Memcpy(b->buf + b->len, data, len);
-    b->len += len;
-    return SECSuccess;
-}
-
-/*
-** Save away write data that is trying to be written before the security
-** handshake has been completed. When the handshake is completed, we will
-** flush this data out.
-** Caller must hold xmitBufLock
-*/
-SECStatus
-ssl_SaveWriteData(sslSocket *ss, const void *data, unsigned int len)
-{
-    SECStatus rv;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    rv = sslBuffer_Append(&ss->pendingBuf, data, len);
-    SSL_TRC(5, ("%d: SSL[%d]: saving %u bytes of data (%u total saved so far)",
-                SSL_GETPID(), ss->fd, len, ss->pendingBuf.len));
-    return rv;
-}
-
-/*
-** Send saved write data. This will flush out data sent prior to a
-** complete security handshake. Hopefully there won't be too much of it.
-** Returns count of the bytes sent, NOT a SECStatus.
-** Caller must hold xmitBufLock
-*/
-int
-ssl_SendSavedWriteData(sslSocket *ss)
-{
-    int rv = 0;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    if (ss->pendingBuf.len != 0) {
-        SSL_TRC(5, ("%d: SSL[%d]: sending %d bytes of saved data",
-                    SSL_GETPID(), ss->fd, ss->pendingBuf.len));
-        rv = ssl_DefSend(ss, ss->pendingBuf.buf, ss->pendingBuf.len, 0);
-        if (rv < 0) {
-            return rv;
-        }
-        ss->pendingBuf.len -= rv;
-        if (ss->pendingBuf.len > 0 && rv > 0) {
-            /* UGH !! This shifts the whole buffer down by copying it */
-            PORT_Memmove(ss->pendingBuf.buf, ss->pendingBuf.buf + rv,
-                         ss->pendingBuf.len);
-        }
-    }
-    return rv;
-}
-
-/************************************************************************/
-
-/*
-** Receive some application data on a socket.  Reads SSL records from the input
-** stream, decrypts them and then copies them to the output buffer.
-** Called from ssl_SecureRecv() below.
-**
-** Caller does NOT hold 1stHandshakeLock because that handshake is over.
-** Caller doesn't call this until initial handshake is complete.
-** For SSLv2, there is no subsequent handshake.
-** For SSLv3, the call to ssl3_GatherAppDataRecord may encounter handshake
-** messages from a subsequent handshake.
-**
-** This code is similar to, and easily confused with,
-**   ssl_GatherRecord1stHandshake() in sslcon.c
-*/
-static int
-DoRecv(sslSocket *ss, unsigned char *out, int len, int flags)
-{
-    int rv;
-    int amount;
-    int available;
-
-    /* ssl3_GatherAppDataRecord may call ssl_FinishHandshake, which needs the
-     * 1stHandshakeLock. */
-    ssl_Get1stHandshakeLock(ss);
-    ssl_GetRecvBufLock(ss);
-
-    available = ss->gs.writeOffset - ss->gs.readOffset;
-    if (available == 0) {
-        /* Get some more data */
-        if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
-            /* Wait for application data to arrive.  */
-            rv = ssl3_GatherAppDataRecord(ss, 0);
-        } else {
-            /* See if we have a complete record */
-            rv = ssl2_GatherRecord(ss, 0);
-        }
-        if (rv <= 0) {
-            if (rv == 0) {
-                /* EOF */
-                SSL_TRC(10, ("%d: SSL[%d]: ssl_recv EOF",
-                             SSL_GETPID(), ss->fd));
-                goto done;
-            }
-            if ((rv != SECWouldBlock) &&
-                (PR_GetError() != PR_WOULD_BLOCK_ERROR)) {
-                /* Some random error */
-                goto done;
-            }
-
-            /*
-            ** Gather record is blocked waiting for more record data to
-            ** arrive. Try to process what we have already received
-            */
-        } else {
-            /* Gather record has finished getting a complete record */
-        }
-
-        /* See if any clear data is now available */
-        available = ss->gs.writeOffset - ss->gs.readOffset;
-        if (available == 0) {
-            /*
-            ** No partial data is available. Force error code to
-            ** EWOULDBLOCK so that caller will try again later. Note
-            ** that the error code is probably EWOULDBLOCK already,
-            ** but if it isn't (for example, if we received a zero
-            ** length record) then this will force it to be correct.
-            */
-            PORT_SetError(PR_WOULD_BLOCK_ERROR);
-            rv = SECFailure;
-            goto done;
-        }
-        SSL_TRC(30, ("%d: SSL[%d]: partial data ready, available=%d",
-                     SSL_GETPID(), ss->fd, available));
-    }
-
-    if (IS_DTLS(ss) && (len < available)) {
-        /* DTLS does not allow you to do partial reads */
-        SSL_TRC(30, ("%d: SSL[%d]: DTLS short read. len=%d available=%d",
-                     SSL_GETPID(), ss->fd, len, available));
-        ss->gs.readOffset += available;
-        PORT_SetError(SSL_ERROR_RX_SHORT_DTLS_READ);
-        rv = SECFailure;
-        goto done;
-    }
-
-    /* Dole out clear data to reader */
-    amount = PR_MIN(len, available);
-    PORT_Memcpy(out, ss->gs.buf.buf + ss->gs.readOffset, amount);
-    if (!(flags & PR_MSG_PEEK)) {
-        ss->gs.readOffset += amount;
-    }
-    PORT_Assert(ss->gs.readOffset <= ss->gs.writeOffset);
-    rv = amount;
-
-    SSL_TRC(30, ("%d: SSL[%d]: amount=%d available=%d",
-                 SSL_GETPID(), ss->fd, amount, available));
-    PRINT_BUF(4, (ss, "DoRecv receiving plaintext:", out, amount));
-
-done:
-    ssl_ReleaseRecvBufLock(ss);
-    ssl_Release1stHandshakeLock(ss);
-    return rv;
-}
-
-/************************************************************************/
-
-/*
-** Return SSLKEAType derived from cert's Public Key algorithm info.
-*/
-SSLKEAType
-NSS_FindCertKEAType(CERTCertificate *cert)
-{
-    SSLKEAType keaType = kt_null;
-    int tag;
-
-    if (!cert)
-        goto loser;
-
-    tag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));
-
-    switch (tag) {
-        case SEC_OID_X500_RSA_ENCRYPTION:
-        case SEC_OID_PKCS1_RSA_ENCRYPTION:
-            keaType = kt_rsa;
-            break;
-        case SEC_OID_ANSIX9_DSA_SIGNATURE: /* hah, signature, not a key? */
-        case SEC_OID_X942_DIFFIE_HELMAN_KEY:
-            keaType = kt_dh;
-            break;
-#ifndef NSS_DISABLE_ECC
-        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
-            keaType = kt_ecdh;
-            break;
-#endif /* NSS_DISABLE_ECC */
-        default:
-            keaType = kt_null;
-    }
-
-loser:
-
-    return keaType;
-}
-
-static const PRCallOnceType pristineCallOnce;
-static PRCallOnceType setupServerCAListOnce;
-
-static SECStatus
-serverCAListShutdown(void *appData, void *nssData)
-{
-    PORT_Assert(ssl3_server_ca_list);
-    if (ssl3_server_ca_list) {
-        CERT_FreeDistNames(ssl3_server_ca_list);
-        ssl3_server_ca_list = NULL;
-    }
-    setupServerCAListOnce = pristineCallOnce;
-    return SECSuccess;
-}
-
-static PRStatus
-serverCAListSetup(void *arg)
-{
-    CERTCertDBHandle *dbHandle = (CERTCertDBHandle *)arg;
-    SECStatus rv = NSS_RegisterShutdown(serverCAListShutdown, NULL);
-    PORT_Assert(SECSuccess == rv);
-    if (SECSuccess == rv) {
-        ssl3_server_ca_list = CERT_GetSSLCACerts(dbHandle);
-        return PR_SUCCESS;
-    }
-    return PR_FAILURE;
-}
-
-SECStatus
-ssl_ConfigSecureServer(sslSocket *ss, CERTCertificate *cert,
-                       const CERTCertificateList *certChain,
-                       ssl3KeyPair *keyPair, SSLKEAType kea)
-{
-    CERTCertificateList *localCertChain = NULL;
-    sslServerCerts *sc = ss->serverCerts + kea;
-
-    /* load the server certificate */
-    if (sc->serverCert != NULL) {
-        CERT_DestroyCertificate(sc->serverCert);
-        sc->serverCert = NULL;
-        sc->serverKeyBits = 0;
-    }
-    /* load the server cert chain */
-    if (sc->serverCertChain != NULL) {
-        CERT_DestroyCertificateList(sc->serverCertChain);
-        sc->serverCertChain = NULL;
-    }
-    if (cert) {
-        sc->serverCert = CERT_DupCertificate(cert);
-        /* get the size of the cert's public key, and remember it */
-        sc->serverKeyBits = SECKEY_PublicKeyStrengthInBits(keyPair->pubKey);
-        if (!certChain) {
-            localCertChain =
-                CERT_CertChainFromCert(sc->serverCert, certUsageSSLServer,
-                                       PR_TRUE);
-            if (!localCertChain)
-                goto loser;
-        }
-        sc->serverCertChain = (certChain) ? CERT_DupCertList(certChain) :
-                                          localCertChain;
-        if (!sc->serverCertChain) {
-            goto loser;
-        }
-        localCertChain = NULL; /* consumed */
-    }
-
-    /* get keyPair */
-    if (sc->serverKeyPair != NULL) {
-        ssl3_FreeKeyPair(sc->serverKeyPair);
-        sc->serverKeyPair = NULL;
-    }
-    if (keyPair) {
-        SECKEY_CacheStaticFlags(keyPair->privKey);
-        sc->serverKeyPair = ssl3_GetKeyPairRef(keyPair);
-    }
-    if (kea == kt_rsa && cert && sc->serverKeyBits > 512 &&
-        !ss->opt.noStepDown && !ss->stepDownKeyPair) {
-        if (ssl3_CreateRSAStepDownKeys(ss) != SECSuccess) {
-            goto loser;
-        }
-    }
-    if (kea == ssl_kea_dh || kea == ssl_kea_rsa) {
-        if (ssl3_SelectDHParams(ss) != SECSuccess) {
-            goto loser;
-        }
-    }
-    return SECSuccess;
-
-loser:
-    if (localCertChain) {
-        CERT_DestroyCertificateList(localCertChain);
-    }
-    if (sc->serverCert != NULL) {
-        CERT_DestroyCertificate(sc->serverCert);
-        sc->serverCert = NULL;
-    }
-    if (sc->serverCertChain != NULL) {
-        CERT_DestroyCertificateList(sc->serverCertChain);
-        sc->serverCertChain = NULL;
-    }
-    if (sc->serverKeyPair != NULL) {
-        ssl3_FreeKeyPair(sc->serverKeyPair);
-        sc->serverKeyPair = NULL;
-    }
-    return SECFailure;
-}
-
-/* XXX need to protect the data that gets changed here.!! */
-
-SECStatus
-SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert,
-                       SECKEYPrivateKey *key, SSL3KEAType kea)
-{
-
-    return SSL_ConfigSecureServerWithCertChain(fd, cert, NULL, key, kea);
-}
-
-SECStatus
-SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert,
-                                    const CERTCertificateList *certChainOpt,
-                                    SECKEYPrivateKey *key, SSL3KEAType kea)
-{
-    sslSocket *ss;
-    SECKEYPublicKey *pubKey = NULL;
-    ssl3KeyPair *keyPair = NULL;
-    SECStatus rv = SECFailure;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        return SECFailure;
-    }
-
-    /* Both key and cert must have a value or be NULL */
-    /* Passing a value of NULL will turn off key exchange algorithms that were
-     * previously turned on */
-    if (!cert != !key) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    /* make sure the key exchange is recognized */
-    if ((kea >= kt_kea_size) || (kea < kt_null)) {
-        PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
-        return SECFailure;
-    }
-
-    if (kea != NSS_FindCertKEAType(cert)) {
-        PORT_SetError(SSL_ERROR_CERT_KEA_MISMATCH);
-        return SECFailure;
-    }
-
-    if (cert) {
-        /* get the size of the cert's public key, and remember it */
-        pubKey = CERT_ExtractPublicKey(cert);
-        if (!pubKey)
-            return SECFailure;
-    }
-
-    if (key) {
-        SECKEYPrivateKey *keyCopy = NULL;
-        CK_MECHANISM_TYPE keyMech = CKM_INVALID_MECHANISM;
-
-        if (key->pkcs11Slot) {
-            PK11SlotInfo *bestSlot;
-            bestSlot = PK11_ReferenceSlot(key->pkcs11Slot);
-            if (bestSlot) {
-                keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
-                PK11_FreeSlot(bestSlot);
-            }
-        }
-        if (keyCopy == NULL)
-            keyMech = PK11_MapSignKeyType(key->keyType);
-        if (keyMech != CKM_INVALID_MECHANISM) {
-            PK11SlotInfo *bestSlot;
-            /* XXX Maybe should be bestSlotMultiple? */
-            bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */);
-            if (bestSlot) {
-                keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
-                PK11_FreeSlot(bestSlot);
-            }
-        }
-        if (keyCopy == NULL)
-            keyCopy = SECKEY_CopyPrivateKey(key);
-        if (keyCopy == NULL)
-            goto loser;
-        keyPair = ssl3_NewKeyPair(keyCopy, pubKey);
-        if (keyPair == NULL) {
-            SECKEY_DestroyPrivateKey(keyCopy);
-            goto loser;
-        }
-        pubKey = NULL; /* adopted by serverKeyPair */
-    }
-    if (ssl_ConfigSecureServer(ss, cert, certChainOpt,
-                               keyPair, kea) == SECFailure) {
-        goto loser;
-    }
-
-    /* Only do this once because it's global. */
-    if (PR_SUCCESS == PR_CallOnceWithArg(&setupServerCAListOnce,
-                                         &serverCAListSetup,
-                                         (void *)(ss->dbHandle))) {
-        rv = SECSuccess;
-    }
-
-loser:
-    if (keyPair) {
-        ssl3_FreeKeyPair(keyPair);
-    }
-    if (pubKey) {
-        SECKEY_DestroyPublicKey(pubKey);
-        pubKey = NULL;
-    }
-    return rv;
-}
-
-/************************************************************************/
-
-SECStatus
-ssl_CreateSecurityInfo(sslSocket *ss)
-{
-    SECStatus status;
-
-    /* initialize sslv2 socket to send data in the clear. */
-    ssl2_UseClearSendFunc(ss);
-
-    ss->sec.blockSize = 1;
-    ss->sec.blockShift = 0;
-
-    ssl_GetXmitBufLock(ss);
-    status = sslBuffer_Grow(&ss->sec.writeBuf, 4096);
-    ssl_ReleaseXmitBufLock(ss);
-
-    return status;
-}
-
-SECStatus
-ssl_CopySecurityInfo(sslSocket *ss, sslSocket *os)
-{
-    ss->sec.send = os->sec.send;
-    ss->sec.isServer = os->sec.isServer;
-    ss->sec.keyBits = os->sec.keyBits;
-    ss->sec.secretKeyBits = os->sec.secretKeyBits;
-
-    ss->sec.peerCert = CERT_DupCertificate(os->sec.peerCert);
-    if (os->sec.peerCert && !ss->sec.peerCert)
-        goto loser;
-
-    ss->sec.cache = os->sec.cache;
-    ss->sec.uncache = os->sec.uncache;
-
-    /* we don't dup the connection info. */
-
-    ss->sec.sendSequence = os->sec.sendSequence;
-    ss->sec.rcvSequence = os->sec.rcvSequence;
-
-    if (os->sec.hash && os->sec.hashcx) {
-        ss->sec.hash = os->sec.hash;
-        ss->sec.hashcx = os->sec.hash->clone(os->sec.hashcx);
-        if (os->sec.hashcx && !ss->sec.hashcx)
-            goto loser;
-    } else {
-        ss->sec.hash = NULL;
-        ss->sec.hashcx = NULL;
-    }
-
-    if (SECITEM_CopyItem(0, &ss->sec.sendSecret, &os->sec.sendSecret))
-        goto loser;
-    if (SECITEM_CopyItem(0, &ss->sec.rcvSecret, &os->sec.rcvSecret))
-        goto loser;
-
-    /* XXX following code is wrong if either cx != 0 */
-    PORT_Assert(os->sec.readcx == 0);
-    PORT_Assert(os->sec.writecx == 0);
-    ss->sec.readcx = os->sec.readcx;
-    ss->sec.writecx = os->sec.writecx;
-    ss->sec.destroy = 0;
-
-    ss->sec.enc = os->sec.enc;
-    ss->sec.dec = os->sec.dec;
-
-    ss->sec.blockShift = os->sec.blockShift;
-    ss->sec.blockSize = os->sec.blockSize;
-
-    return SECSuccess;
-
-loser:
-    return SECFailure;
-}
-
-/* Reset sec back to its initial state.
-** Caller holds any relevant locks.
-*/
-void
-ssl_ResetSecurityInfo(sslSecurityInfo *sec, PRBool doMemset)
-{
-    /* Destroy MAC */
-    if (sec->hash && sec->hashcx) {
-        (*sec->hash->destroy)(sec->hashcx, PR_TRUE);
-        sec->hashcx = NULL;
-        sec->hash = NULL;
-    }
-    SECITEM_ZfreeItem(&sec->sendSecret, PR_FALSE);
-    SECITEM_ZfreeItem(&sec->rcvSecret, PR_FALSE);
-
-    /* Destroy ciphers */
-    if (sec->destroy) {
-        (*sec->destroy)(sec->readcx, PR_TRUE);
-        (*sec->destroy)(sec->writecx, PR_TRUE);
-        sec->readcx = NULL;
-        sec->writecx = NULL;
-    } else {
-        PORT_Assert(sec->readcx == 0);
-        PORT_Assert(sec->writecx == 0);
-    }
-    sec->readcx = 0;
-    sec->writecx = 0;
-
-    if (sec->localCert) {
-        CERT_DestroyCertificate(sec->localCert);
-        sec->localCert = NULL;
-    }
-    if (sec->peerCert) {
-        CERT_DestroyCertificate(sec->peerCert);
-        sec->peerCert = NULL;
-    }
-    if (sec->peerKey) {
-        SECKEY_DestroyPublicKey(sec->peerKey);
-        sec->peerKey = NULL;
-    }
-
-    /* cleanup the ci */
-    if (sec->ci.sid != NULL) {
-        ssl_FreeSID(sec->ci.sid);
-    }
-    PORT_ZFree(sec->ci.sendBuf.buf, sec->ci.sendBuf.space);
-    if (doMemset) {
-        memset(&sec->ci, 0, sizeof sec->ci);
-    }
-}
-
-/*
-** Called from SSL_ResetHandshake (above), and
-**        from ssl_FreeSocket     in sslsock.c
-** Caller should hold relevant locks (e.g. XmitBufLock)
-*/
-void
-ssl_DestroySecurityInfo(sslSecurityInfo *sec)
-{
-    ssl_ResetSecurityInfo(sec, PR_FALSE);
-
-    PORT_ZFree(sec->writeBuf.buf, sec->writeBuf.space);
-    sec->writeBuf.buf = 0;
-
-    memset(sec, 0, sizeof *sec);
-}
-
-/************************************************************************/
-
-int
-ssl_SecureConnect(sslSocket *ss, const PRNetAddr *sa)
-{
-    PRFileDesc *osfd = ss->fd->lower;
-    int rv;
-
-    if (ss->opt.handshakeAsServer) {
-        ss->securityHandshake = ssl2_BeginServerHandshake;
-        ss->handshaking = sslHandshakingAsServer;
-    } else {
-        ss->securityHandshake = ssl2_BeginClientHandshake;
-        ss->handshaking = sslHandshakingAsClient;
-    }
-
-    /* connect to server */
-    rv = osfd->methods->connect(osfd, sa, ss->cTimeout);
-    if (rv == PR_SUCCESS) {
-        ss->TCPconnected = 1;
-    } else {
-        int err = PR_GetError();
-        SSL_DBG(("%d: SSL[%d]: connect failed, errno=%d",
-                 SSL_GETPID(), ss->fd, err));
-        if (err == PR_IS_CONNECTED_ERROR) {
-            ss->TCPconnected = 1;
-        }
-    }
-
-    SSL_TRC(5, ("%d: SSL[%d]: secure connect completed, rv == %d",
-                SSL_GETPID(), ss->fd, rv));
-    return rv;
-}
-
-/*
- * The TLS 1.2 RFC 5246, Section 7.2.1 says:
- *
- *     Unless some other fatal alert has been transmitted, each party is
- *     required to send a close_notify alert before closing the write side
- *     of the connection.  The other party MUST respond with a close_notify
- *     alert of its own and close down the connection immediately,
- *     discarding any pending writes.  It is not required for the initiator
- *     of the close to wait for the responding close_notify alert before
- *     closing the read side of the connection.
- *
- * The second sentence requires that we send a close_notify alert when we
- * have received a close_notify alert.  In practice, all SSL implementations
- * close the socket immediately after sending a close_notify alert (which is
- * allowed by the third sentence), so responding with a close_notify alert
- * would result in a write failure with the ECONNRESET error.  This is why
- * we don't respond with a close_notify alert.
- *
- * Also, in the unlikely event that the TCP pipe is full and the peer stops
- * reading, the SSL3_SendAlert call in ssl_SecureClose and ssl_SecureShutdown
- * may block indefinitely in blocking mode, and may fail (without retrying)
- * in non-blocking mode.
- */
-
-int
-ssl_SecureClose(sslSocket *ss)
-{
-    int rv;
-
-    if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
-        !(ss->shutdownHow & ssl_SHUTDOWN_SEND) &&
-        ss->firstHsDone &&
-        !ss->recvdCloseNotify &&
-        ss->ssl3.initialized) {
-
-        /* We don't want the final alert to be Nagle delayed. */
-        if (!ss->delayDisabled) {
-            ssl_EnableNagleDelay(ss, PR_FALSE);
-            ss->delayDisabled = 1;
-        }
-
-        (void)SSL3_SendAlert(ss, alert_warning, close_notify);
-    }
-    rv = ssl_DefClose(ss);
-    return rv;
-}
-
-/* Caller handles all locking */
-int
-ssl_SecureShutdown(sslSocket *ss, int nsprHow)
-{
-    PRFileDesc *osfd = ss->fd->lower;
-    int rv;
-    PRIntn sslHow = nsprHow + 1;
-
-    if ((unsigned)nsprHow > PR_SHUTDOWN_BOTH) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return PR_FAILURE;
-    }
-
-    if ((sslHow & ssl_SHUTDOWN_SEND) != 0 &&
-        ss->version >= SSL_LIBRARY_VERSION_3_0 &&
-        !(ss->shutdownHow & ssl_SHUTDOWN_SEND) &&
-        ss->firstHsDone &&
-        !ss->recvdCloseNotify &&
-        ss->ssl3.initialized) {
-
-        (void)SSL3_SendAlert(ss, alert_warning, close_notify);
-    }
-
-    rv = osfd->methods->shutdown(osfd, nsprHow);
-
-    ss->shutdownHow |= sslHow;
-
-    return rv;
-}
-
-/************************************************************************/
-
-int
-ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
-{
-    int rv = 0;
-
-    if (ss->shutdownHow & ssl_SHUTDOWN_RCV) {
-        PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
-        return PR_FAILURE;
-    }
-    if (flags & ~PR_MSG_PEEK) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return PR_FAILURE;
-    }
-
-    if (!ssl_SocketIsBlocking(ss) && !ss->opt.fdx) {
-        ssl_GetXmitBufLock(ss);
-        if (ss->pendingBuf.len != 0) {
-            rv = ssl_SendSavedWriteData(ss);
-            if ((rv < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) {
-                ssl_ReleaseXmitBufLock(ss);
-                return SECFailure;
-            }
-        }
-        ssl_ReleaseXmitBufLock(ss);
-    }
-
-    rv = 0;
-    /* If any of these is non-zero, the initial handshake is not done. */
-    if (!ss->firstHsDone) {
-        ssl_Get1stHandshakeLock(ss);
-        if (ss->handshake || ss->nextHandshake || ss->securityHandshake) {
-            rv = ssl_Do1stHandshake(ss);
-        }
-        ssl_Release1stHandshakeLock(ss);
-    }
-    if (rv < 0) {
-        return rv;
-    }
-
-    if (len == 0)
-        return 0;
-
-    rv = DoRecv(ss, (unsigned char *)buf, len, flags);
-    SSL_TRC(2, ("%d: SSL[%d]: recving %d bytes securely (errno=%d)",
-                SSL_GETPID(), ss->fd, rv, PORT_GetError()));
-    return rv;
-}
-
-int
-ssl_SecureRead(sslSocket *ss, unsigned char *buf, int len)
-{
-    return ssl_SecureRecv(ss, buf, len, 0);
-}
-
-/* Caller holds the SSL Socket's write lock. SSL_LOCK_WRITER(ss) */
-int
-ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
-{
-    int rv = 0;
-
-    SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes",
-                SSL_GETPID(), ss->fd, len));
-
-    if (ss->shutdownHow & ssl_SHUTDOWN_SEND) {
-        PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
-        rv = PR_FAILURE;
-        goto done;
-    }
-    if (flags) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        rv = PR_FAILURE;
-        goto done;
-    }
-
-    ssl_GetXmitBufLock(ss);
-    if (ss->pendingBuf.len != 0) {
-        PORT_Assert(ss->pendingBuf.len > 0);
-        rv = ssl_SendSavedWriteData(ss);
-        if (rv >= 0 && ss->pendingBuf.len != 0) {
-            PORT_Assert(ss->pendingBuf.len > 0);
-            PORT_SetError(PR_WOULD_BLOCK_ERROR);
-            rv = SECFailure;
-        }
-    }
-    ssl_ReleaseXmitBufLock(ss);
-    if (rv < 0) {
-        goto done;
-    }
-
-    if (len > 0)
-        ss->writerThread = PR_GetCurrentThread();
-    /* If any of these is non-zero, the initial handshake is not done. */
-    if (!ss->firstHsDone) {
-        PRBool falseStart = PR_FALSE;
-        ssl_Get1stHandshakeLock(ss);
-        if (ss->opt.enableFalseStart &&
-            ss->version >= SSL_LIBRARY_VERSION_3_0) {
-            ssl_GetSSL3HandshakeLock(ss);
-            falseStart = ss->ssl3.hs.canFalseStart;
-            ssl_ReleaseSSL3HandshakeLock(ss);
-        }
-        if (!falseStart &&
-            (ss->handshake || ss->nextHandshake || ss->securityHandshake)) {
-            rv = ssl_Do1stHandshake(ss);
-        }
-        ssl_Release1stHandshakeLock(ss);
-    }
-    if (rv < 0) {
-        ss->writerThread = NULL;
-        goto done;
-    }
-
-    /* Check for zero length writes after we do housekeeping so we make forward
-     * progress.
-     */
-    if (len == 0) {
-        rv = 0;
-        goto done;
-    }
-    PORT_Assert(buf != NULL);
-    if (!buf) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        rv = PR_FAILURE;
-        goto done;
-    }
-
-    if (!ss->firstHsDone) {
-        PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_3_0);
-#ifdef DEBUG
-        ssl_GetSSL3HandshakeLock(ss);
-        PORT_Assert(ss->ssl3.hs.canFalseStart);
-        ssl_ReleaseSSL3HandshakeLock(ss);
-#endif
-        SSL_TRC(3, ("%d: SSL[%d]: SecureSend: sending data due to false start",
-                    SSL_GETPID(), ss->fd));
-    }
-
-    /* Send out the data using one of these functions:
-     *  ssl2_SendClear, ssl2_SendStream, ssl2_SendBlock,
-     *  ssl3_SendApplicationData
-     */
-    ssl_GetXmitBufLock(ss);
-    rv = (*ss->sec.send)(ss, buf, len, flags);
-    ssl_ReleaseXmitBufLock(ss);
-    ss->writerThread = NULL;
-done:
-    if (rv < 0) {
-        SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count, error %d",
-                    SSL_GETPID(), ss->fd, rv, PORT_GetError()));
-    } else {
-        SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count",
-                    SSL_GETPID(), ss->fd, rv));
-    }
-    return rv;
-}
-
-int
-ssl_SecureWrite(sslSocket *ss, const unsigned char *buf, int len)
-{
-    return ssl_SecureSend(ss, buf, len, 0);
-}
-
-SECStatus
-SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f, void *arg)
-{
-    sslSocket *ss;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSLBadCertHook",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    ss->handleBadCert = f;
-    ss->badCertArg = arg;
-
-    return SECSuccess;
-}
-
-/*
- * Allow the application to pass the url or hostname into the SSL library
- * so that we can do some checking on it. It will be used for the value in
- * SNI extension of client hello message.
- */
-SECStatus
-SSL_SetURL(PRFileDesc *fd, const char *url)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-    SECStatus rv = SECSuccess;
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSLSetURL",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-    ssl_Get1stHandshakeLock(ss);
-    ssl_GetSSL3HandshakeLock(ss);
-
-    if (ss->url) {
-        PORT_Free((void *)ss->url); /* CONST */
-    }
-
-    ss->url = (const char *)PORT_Strdup(url);
-    if (ss->url == NULL) {
-        rv = SECFailure;
-    }
-
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    ssl_Release1stHandshakeLock(ss);
-
-    return rv;
-}
-
-/*
- * Allow the application to pass the set of trust anchors
- */
-SECStatus
-SSL_SetTrustAnchors(PRFileDesc *fd, CERTCertList *certList)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-    CERTDistNames *names = NULL;
-
-    if (!certList) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetTrustAnchors",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    names = CERT_DistNamesFromCertList(certList);
-    if (names == NULL) {
-        return SECFailure;
-    }
-    ssl_Get1stHandshakeLock(ss);
-    ssl_GetSSL3HandshakeLock(ss);
-    if (ss->ssl3.ca_list) {
-        CERT_FreeDistNames(ss->ssl3.ca_list);
-    }
-    ss->ssl3.ca_list = names;
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    ssl_Release1stHandshakeLock(ss);
-
-    return SECSuccess;
-}
-
-/*
-** Returns Negative number on error, zero or greater on success.
-** Returns the amount of data immediately available to be read.
-*/
-int
-SSL_DataPending(PRFileDesc *fd)
-{
-    sslSocket *ss;
-    int rv = 0;
-
-    ss = ssl_FindSocket(fd);
-
-    if (ss && ss->opt.useSecurity) {
-        ssl_GetRecvBufLock(ss);
-        rv = ss->gs.writeOffset - ss->gs.readOffset;
-        ssl_ReleaseRecvBufLock(ss);
-    }
-
-    return rv;
-}
-
-SECStatus
-SSL_InvalidateSession(PRFileDesc *fd)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-    SECStatus rv = SECFailure;
-
-    if (ss) {
-        ssl_Get1stHandshakeLock(ss);
-        ssl_GetSSL3HandshakeLock(ss);
-
-        if (ss->sec.ci.sid && ss->sec.uncache) {
-            ss->sec.uncache(ss->sec.ci.sid);
-            rv = SECSuccess;
-        }
-
-        ssl_ReleaseSSL3HandshakeLock(ss);
-        ssl_Release1stHandshakeLock(ss);
-    }
-    return rv;
-}
-
-static void
-ssl3_CacheSessionUnlocked(sslSocket *ss)
-{
-    PORT_Assert(!ss->sec.isServer);
-
-    if (ss->ssl3.hs.cacheSID) {
-        ss->sec.cache(ss->sec.ci.sid);
-        ss->ssl3.hs.cacheSID = PR_FALSE;
-    }
-}
-
-SECStatus
-SSL_CacheSession(PRFileDesc *fd)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-    SECStatus rv = SECFailure;
-
-    if (ss) {
-        ssl_Get1stHandshakeLock(ss);
-        ssl_GetSSL3HandshakeLock(ss);
-
-        ssl3_CacheSessionUnlocked(ss);
-        rv = SECSuccess;
-
-        ssl_ReleaseSSL3HandshakeLock(ss);
-        ssl_Release1stHandshakeLock(ss);
-    }
-    return rv;
-}
-
-SECStatus
-SSL_CacheSessionUnlocked(PRFileDesc *fd)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-    SECStatus rv = SECFailure;
-
-    if (ss) {
-        ssl3_CacheSessionUnlocked(ss);
-        rv = SECSuccess;
-    }
-    return rv;
-}
-
-SECItem *
-SSL_GetSessionID(PRFileDesc *fd)
-{
-    sslSocket *ss;
-    SECItem *item = NULL;
-
-    ss = ssl_FindSocket(fd);
-    if (ss) {
-        ssl_Get1stHandshakeLock(ss);
-        ssl_GetSSL3HandshakeLock(ss);
-
-        if (ss->opt.useSecurity && ss->firstHsDone && ss->sec.ci.sid) {
-            item = (SECItem *)PORT_Alloc(sizeof(SECItem));
-            if (item) {
-                sslSessionID *sid = ss->sec.ci.sid;
-                if (sid->version < SSL_LIBRARY_VERSION_3_0) {
-                    item->len = SSL2_SESSIONID_BYTES;
-                    item->data = (unsigned char *)PORT_Alloc(item->len);
-                    PORT_Memcpy(item->data, sid->u.ssl2.sessionID, item->len);
-                } else {
-                    item->len = sid->u.ssl3.sessionIDLength;
-                    item->data = (unsigned char *)PORT_Alloc(item->len);
-                    PORT_Memcpy(item->data, sid->u.ssl3.sessionID, item->len);
-                }
-            }
-        }
-
-        ssl_ReleaseSSL3HandshakeLock(ss);
-        ssl_Release1stHandshakeLock(ss);
-    }
-    return item;
-}
-
-SECStatus
-SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHandle)
-{
-    sslSocket *ss;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss)
-        return SECFailure;
-    if (!dbHandle) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-    ss->dbHandle = dbHandle;
-    return SECSuccess;
-}
-
-/*
- * attempt to restart the handshake after asynchronously handling
- * a request for the client's certificate.
- *
- * inputs:  
- *	cert	Client cert chosen by application.
- *		Note: ssl takes this reference, and does not bump the 
- *		reference count.  The caller should drop its reference
- *		without calling CERT_DestroyCertificate after calling this
- *		function.
- *
- *	key	Private key associated with cert.  This function takes
- *		ownership of the private key, so the caller should drop its
- *		reference without destroying the private key after this
- *		function returns.
- *
- *	certChain  Chain of signers for cert.  
- *		Note: ssl takes this reference, and does not copy the chain.
- *		The caller should drop its reference without destroying the 
- *		chain.  SSL will free the chain when it is done with it.
- *
- * Return value: XXX
- *
- * XXX This code only works on the initial handshake on a connection, XXX
- *     It does not work on a subsequent handshake (redo).
-   */
-SECStatus
-SSL_RestartHandshakeAfterCertReq(PRFileDesc *fd,
-                                 CERTCertificate *cert,
-                                 SECKEYPrivateKey *key,
-                                 CERTCertificateList *certChain)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-    SECStatus ret;
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RestartHandshakeAfterCertReq",
-                 SSL_GETPID(), fd));
-        if (cert) {
-            CERT_DestroyCertificate(cert);
-        }
-        if (key) {
-            SECKEY_DestroyPrivateKey(key);
-        }
-        if (certChain) {
-            CERT_DestroyCertificateList(certChain);
-        }
-        return SECFailure;
-    }
-
-    ssl_Get1stHandshakeLock(ss); /************************************/
-
-    if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
-        ret = ssl3_RestartHandshakeAfterCertReq(ss, cert, key, certChain);
-    } else {
-        if (certChain != NULL) {
-            CERT_DestroyCertificateList(certChain);
-        }
-        PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
-        ret = SECFailure;
-    }
-
-    ssl_Release1stHandshakeLock(ss); /************************************/
-    return ret;
-}
-
-SECStatus
-SSL_RestartHandshakeAfterChannelIDReq(PRFileDesc *fd,
-                                      SECKEYPublicKey *channelIDPub,
-                                      SECKEYPrivateKey *channelID)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-    SECStatus ret;
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in"
-                 " SSL_RestartHandshakeAfterChannelIDReq",
-                 SSL_GETPID(), fd));
-        goto loser;
-    }
-
-    ssl_Get1stHandshakeLock(ss);
-
-    if (ss->version < SSL_LIBRARY_VERSION_3_0) {
-        PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
-        ssl_Release1stHandshakeLock(ss);
-        goto loser;
-    }
-
-    ret = ssl3_RestartHandshakeAfterChannelIDReq(ss, channelIDPub,
-                                                 channelID);
-    ssl_Release1stHandshakeLock(ss);
-
-    return ret;
-
-loser:
-    SECKEY_DestroyPublicKey(channelIDPub);
-    SECKEY_DestroyPrivateKey(channelID);
-    return SECFailure;
-}
-
-/* DO NOT USE. This function was exported in ssl.def with the wrong signature;
- * this implementation exists to maintain link-time compatibility.
- */
-int
-SSL_RestartHandshakeAfterServerCert(sslSocket *ss)
-{
-    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
-    return -1;
-}
-
-/* See documentation in ssl.h */
-SECStatus
-SSL_AuthCertificateComplete(PRFileDesc *fd, PRErrorCode error)
-{
-    SECStatus rv;
-    sslSocket *ss = ssl_FindSocket(fd);
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_AuthCertificateComplete",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    ssl_Get1stHandshakeLock(ss);
-
-    if (!ss->ssl3.initialized) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        rv = SECFailure;
-    } else if (ss->version < SSL_LIBRARY_VERSION_3_0) {
-        PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
-        rv = SECFailure;
-    } else {
-        rv = ssl3_AuthCertificateComplete(ss, error);
-    }
-
-    ssl_Release1stHandshakeLock(ss);
-
-    return rv;
-}
-
-/* For more info see ssl.h */
-SECStatus
-SSL_SNISocketConfigHook(PRFileDesc *fd, SSLSNISocketConfig func,
-                        void *arg)
-{
-    sslSocket *ss;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SNISocketConfigHook",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    ss->sniSocketConfig = func;
-    ss->sniSocketConfigArg = arg;
-    return SECSuccess;
-}
diff --git a/net/third_party/nss/ssl/sslsnce.c b/net/third_party/nss/ssl/sslsnce.c
deleted file mode 100644
index e3f749e5..0000000
--- a/net/third_party/nss/ssl/sslsnce.c
+++ /dev/null
@@ -1,2204 +0,0 @@
-/* This file implements the SERVER Session ID cache.
- * NOTE:  The contents of this file are NOT used by the client.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Note: ssl_FreeSID() in sslnonce.c gets used for both client and server
- * cache sids!
- *
- * About record locking among different server processes:
- *
- * All processes that are part of the same conceptual server (serving on
- * the same address and port) MUST share a common SSL session cache.
- * This code makes the content of the shared cache accessible to all
- * processes on the same "server".  This code works on Unix and Win32 only.
- *
- * We use NSPR anonymous shared memory and move data to & from shared memory.
- * We must do explicit locking of the records for all reads and writes.
- * The set of Cache entries are divided up into "sets" of 128 entries.
- * Each set is protected by a lock.  There may be one or more sets protected
- * by each lock.  That is, locks to sets are 1:N.
- * There is one lock for the entire cert cache.
- * There is one lock for the set of wrapped sym wrap keys.
- *
- * The anonymous shared memory is laid out as if it were declared like this:
- *
- * struct {
- *     cacheDescriptor          desc;
- *     sidCacheLock             sidCacheLocks[ numSIDCacheLocks];
- *     sidCacheLock             keyCacheLock;
- *     sidCacheLock             certCacheLock;
- *     sidCacheSet              sidCacheSets[ numSIDCacheSets ];
- *     sidCacheEntry            sidCacheData[ numSIDCacheEntries];
- *     certCacheEntry           certCacheData[numCertCacheEntries];
- *     SSLWrappedSymWrappingKey keyCacheData[kt_kea_size][SSL_NUM_WRAP_MECHS];
- *     PRUint8                  keyNameSuffix[SESS_TICKET_KEY_VAR_NAME_LEN]
- *     encKeyCacheEntry         ticketEncKey; // Wrapped in non-bypass mode
- *     encKeyCacheEntry         ticketMacKey; // Wrapped in non-bypass mode
- *     PRBool                   ticketKeysValid;
- *     sidCacheLock             srvNameCacheLock;
- *     srvNameCacheEntry        srvNameData[ numSrvNameCacheEntries ];
- * } cacheMemCacheData;
- */
-#include "seccomon.h"
-
-#if defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_OS2) || defined(XP_BEOS)
-
-#include "cert.h"
-#include "ssl.h"
-#include "sslimpl.h"
-#include "sslproto.h"
-#include "pk11func.h"
-#include "base64.h"
-#include "keyhi.h"
-#ifdef NO_PKCS11_BYPASS
-#include "blapit.h"
-#include "sechash.h"
-#else
-#include "blapi.h"
-#endif
-
-#include <stdio.h>
-
-#if defined(XP_UNIX) || defined(XP_BEOS)
-
-#include <syslog.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include "unix_err.h"
-
-#else
-
-#ifdef XP_WIN32
-#include <wtypes.h>
-#include "win32err.h"
-#endif
-
-#endif
-#include <sys/types.h>
-
-#define SET_ERROR_CODE /* reminder */
-
-#include "nspr.h"
-#include "sslmutex.h"
-
-/*
-** Format of a cache entry in the shared memory.
-*/
-struct sidCacheEntryStr {
-    /* 16 */ PRIPv6Addr addr; /* client's IP address */
-    /*  4 */ PRUint32 creationTime;
-    /*  4 */ PRUint32 lastAccessTime;
-    /*  4 */ PRUint32 expirationTime;
-    /*  2 */ PRUint16 version;
-    /*  1 */ PRUint8 valid;
-    /*  1 */ PRUint8 sessionIDLength;
-    /* 32 */ PRUint8 sessionID[SSL3_SESSIONID_BYTES];
-    /*  2 */ PRUint16 authAlgorithm;
-    /*  2 */ PRUint16 authKeyBits;
-    /*  2 */ PRUint16 keaType;
-    /*  2 */ PRUint16 keaKeyBits;
-    /* 72  - common header total */
-
-    union {
-        struct {
-            /* 64 */ PRUint8 masterKey[SSL_MAX_MASTER_KEY_BYTES];
-            /* 32 */ PRUint8 cipherArg[SSL_MAX_CYPHER_ARG_BYTES];
-
-            /*  1 */ PRUint8 cipherType;
-            /*  1 */ PRUint8 masterKeyLen;
-            /*  1 */ PRUint8 keyBits;
-            /*  1 */ PRUint8 secretKeyBits;
-            /*  1 */ PRUint8 cipherArgLen;
-/*101 */} ssl2;
-
-struct {
-    /*  2 */ ssl3CipherSuite cipherSuite;
-    /*  2 */ PRUint16 compression; /* SSLCompressionMethod */
-
-    /* 54 */ ssl3SidKeys keys; /* keys, wrapped as needed. */
-
-    /*  4 */ PRUint32 masterWrapMech;
-    /*  4 */ SSL3KEAType exchKeyType;
-    /*  4 */ PRInt32 certIndex;
-    /*  4 */ PRInt32 srvNameIndex;
-    /* 32 */ PRUint8 srvNameHash[SHA256_LENGTH]; /* SHA256 name hash */
-/*108 */} ssl3;
-
-/* force sizeof(sidCacheEntry) to be a multiple of cache line size */
-struct {
-    /*120 */ PRUint8 filler[120]; /* 72+120==192, a multiple of 16 */
-} forceSize;
-    } u;
-};
-typedef struct sidCacheEntryStr sidCacheEntry;
-
-/* The length of this struct is supposed to be a power of 2, e.g. 4KB */
-struct certCacheEntryStr {
-    PRUint16 certLength;                     /*    2 */
-    PRUint16 sessionIDLength;                /*    2 */
-    PRUint8 sessionID[SSL3_SESSIONID_BYTES]; /*   32 */
-    PRUint8 cert[SSL_MAX_CACHED_CERT_LEN];   /* 4060 */
-};                                           /* total   4096 */
-typedef struct certCacheEntryStr certCacheEntry;
-
-struct sidCacheLockStr {
-    PRUint32 timeStamp;
-    sslMutex mutex;
-    sslPID pid;
-};
-typedef struct sidCacheLockStr sidCacheLock;
-
-struct sidCacheSetStr {
-    PRIntn next;
-};
-typedef struct sidCacheSetStr sidCacheSet;
-
-struct encKeyCacheEntryStr {
-    PRUint8 bytes[512];
-    PRInt32 length;
-};
-typedef struct encKeyCacheEntryStr encKeyCacheEntry;
-
-#define SSL_MAX_DNS_HOST_NAME 1024
-
-struct srvNameCacheEntryStr {
-    PRUint16 type;                            /*    2 */
-    PRUint16 nameLen;                         /*    2 */
-    PRUint8 name[SSL_MAX_DNS_HOST_NAME + 12]; /* 1034 */
-    PRUint8 nameHash[SHA256_LENGTH];          /*   32 */
-                                              /* 1072 */
-};
-typedef struct srvNameCacheEntryStr srvNameCacheEntry;
-
-struct cacheDescStr {
-
-    PRUint32 cacheMemSize;
-
-    PRUint32 numSIDCacheLocks;
-    PRUint32 numSIDCacheSets;
-    PRUint32 numSIDCacheSetsPerLock;
-
-    PRUint32 numSIDCacheEntries;
-    PRUint32 sidCacheSize;
-
-    PRUint32 numCertCacheEntries;
-    PRUint32 certCacheSize;
-
-    PRUint32 numKeyCacheEntries;
-    PRUint32 keyCacheSize;
-
-    PRUint32 numSrvNameCacheEntries;
-    PRUint32 srvNameCacheSize;
-
-    PRUint32 ssl2Timeout;
-    PRUint32 ssl3Timeout;
-
-    PRUint32 numSIDCacheLocksInitialized;
-
-    /* These values are volatile, and are accessed through sharedCache-> */
-    PRUint32 nextCertCacheEntry; /* certCacheLock protects */
-    PRBool stopPolling;
-    PRBool everInherited;
-
-    /* The private copies of these values are pointers into shared mem */
-    /* The copies of these values in shared memory are merely offsets */
-    sidCacheLock *sidCacheLocks;
-    sidCacheLock *keyCacheLock;
-    sidCacheLock *certCacheLock;
-    sidCacheLock *srvNameCacheLock;
-    sidCacheSet *sidCacheSets;
-    sidCacheEntry *sidCacheData;
-    certCacheEntry *certCacheData;
-    SSLWrappedSymWrappingKey *keyCacheData;
-    PRUint8 *ticketKeyNameSuffix;
-    encKeyCacheEntry *ticketEncKey;
-    encKeyCacheEntry *ticketMacKey;
-    PRUint32 *ticketKeysValid;
-    srvNameCacheEntry *srvNameCacheData;
-
-    /* Only the private copies of these pointers are valid */
-    char *cacheMem;
-    struct cacheDescStr *sharedCache; /* shared copy of this struct */
-    PRFileMap *cacheMemMap;
-    PRThread *poller;
-    PRUint32 mutexTimeout;
-    PRBool shared;
-};
-typedef struct cacheDescStr cacheDesc;
-
-static cacheDesc globalCache;
-
-static const char envVarName[] = { SSL_ENV_VAR_NAME };
-
-static PRBool isMultiProcess = PR_FALSE;
-
-#define DEF_SID_CACHE_ENTRIES 10000
-#define DEF_CERT_CACHE_ENTRIES 250
-#define MIN_CERT_CACHE_ENTRIES 125 /* the effective size in old releases. */
-#define DEF_KEY_CACHE_ENTRIES 250
-#define DEF_NAME_CACHE_ENTRIES 1000
-
-#define SID_CACHE_ENTRIES_PER_SET 128
-#define SID_ALIGNMENT 16
-
-#define DEF_SSL2_TIMEOUT 100 /* seconds */
-#define MAX_SSL2_TIMEOUT 100 /* seconds */
-#define MIN_SSL2_TIMEOUT 5   /* seconds */
-
-#define DEF_SSL3_TIMEOUT 86400L /* 24 hours */
-#define MAX_SSL3_TIMEOUT 86400L /* 24 hours */
-#define MIN_SSL3_TIMEOUT 5      /* seconds  */
-
-#if defined(AIX) || defined(LINUX) || defined(NETBSD) || defined(OPENBSD)
-#define MAX_SID_CACHE_LOCKS 8 /* two FDs per lock */
-#elif defined(OSF1)
-#define MAX_SID_CACHE_LOCKS 16 /* one FD per lock */
-#else
-#define MAX_SID_CACHE_LOCKS 256
-#endif
-
-#define SID_HOWMANY(val, size) (((val) + ((size)-1)) / (size))
-#define SID_ROUNDUP(val, size) ((size)*SID_HOWMANY((val), (size)))
-
-static sslPID myPid;
-static PRUint32 ssl_max_sid_cache_locks = MAX_SID_CACHE_LOCKS;
-
-/* forward static function declarations */
-static PRUint32 SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s,
-                         unsigned nl);
-static SECStatus LaunchLockPoller(cacheDesc *cache);
-static SECStatus StopLockPoller(cacheDesc *cache);
-
-struct inheritanceStr {
-    PRUint32 cacheMemSize;
-    PRUint32 fmStrLen;
-};
-
-typedef struct inheritanceStr inheritance;
-
-#if defined(_WIN32) || defined(XP_OS2)
-
-#define DEFAULT_CACHE_DIRECTORY "\\temp"
-
-#endif /* _win32 */
-
-#if defined(XP_UNIX) || defined(XP_BEOS)
-
-#define DEFAULT_CACHE_DIRECTORY "/tmp"
-
-#endif /* XP_UNIX || XP_BEOS */
-
-/************************************************************************/
-
-static PRUint32
-LockSidCacheLock(sidCacheLock *lock, PRUint32 now)
-{
-    SECStatus rv = sslMutex_Lock(&lock->mutex);
-    if (rv != SECSuccess)
-        return 0;
-    if (!now)
-        now = ssl_Time();
-    lock->timeStamp = now;
-    lock->pid = myPid;
-    return now;
-}
-
-static SECStatus
-UnlockSidCacheLock(sidCacheLock *lock)
-{
-    SECStatus rv;
-
-    lock->pid = 0;
-    rv = sslMutex_Unlock(&lock->mutex);
-    return rv;
-}
-
-/* returns the value of ssl_Time on success, zero on failure. */
-static PRUint32
-LockSet(cacheDesc *cache, PRUint32 set, PRUint32 now)
-{
-    PRUint32 lockNum = set % cache->numSIDCacheLocks;
-    sidCacheLock *lock = cache->sidCacheLocks + lockNum;
-
-    return LockSidCacheLock(lock, now);
-}
-
-static SECStatus
-UnlockSet(cacheDesc *cache, PRUint32 set)
-{
-    PRUint32 lockNum = set % cache->numSIDCacheLocks;
-    sidCacheLock *lock = cache->sidCacheLocks + lockNum;
-
-    return UnlockSidCacheLock(lock);
-}
-
-/************************************************************************/
-
-/* Put a certificate in the cache.  Update the cert index in the sce.
-*/
-static PRUint32
-CacheCert(cacheDesc *cache, CERTCertificate *cert, sidCacheEntry *sce)
-{
-    PRUint32 now;
-    certCacheEntry cce;
-
-    if ((cert->derCert.len > SSL_MAX_CACHED_CERT_LEN) ||
-        (cert->derCert.len <= 0) ||
-        (cert->derCert.data == NULL)) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return 0;
-    }
-
-    cce.sessionIDLength = sce->sessionIDLength;
-    PORT_Memcpy(cce.sessionID, sce->sessionID, cce.sessionIDLength);
-
-    cce.certLength = cert->derCert.len;
-    PORT_Memcpy(cce.cert, cert->derCert.data, cce.certLength);
-
-    /* get lock on cert cache */
-    now = LockSidCacheLock(cache->certCacheLock, 0);
-    if (now) {
-
-        /* Find where to place the next cert cache entry. */
-        cacheDesc *sharedCache = cache->sharedCache;
-        PRUint32 ndx = sharedCache->nextCertCacheEntry;
-
-        /* write the entry */
-        cache->certCacheData[ndx] = cce;
-
-        /* remember where we put it. */
-        sce->u.ssl3.certIndex = ndx;
-
-        /* update the "next" cache entry index */
-        sharedCache->nextCertCacheEntry =
-            (ndx + 1) % cache->numCertCacheEntries;
-
-        UnlockSidCacheLock(cache->certCacheLock);
-    }
-    return now;
-}
-
-/* Server configuration hash tables need to account the SECITEM.type
- * field as well. These functions accomplish that. */
-static PLHashNumber
-Get32BitNameHash(const SECItem *name)
-{
-    PLHashNumber rv = SECITEM_Hash(name);
-
-    PRUint8 *rvc = (PRUint8 *)&rv;
-    rvc[name->len % sizeof(rv)] ^= name->type;
-
-    return rv;
-}
-
-/* Put a name in the cache.  Update the cert index in the sce.
-*/
-static PRUint32
-CacheSrvName(cacheDesc *cache, SECItem *name, sidCacheEntry *sce)
-{
-    PRUint32 now;
-    PRUint32 ndx;
-    srvNameCacheEntry snce;
-
-    if (!name || name->len <= 0 ||
-        name->len > SSL_MAX_DNS_HOST_NAME) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return 0;
-    }
-
-    snce.type = name->type;
-    snce.nameLen = name->len;
-    PORT_Memcpy(snce.name, name->data, snce.nameLen);
-#ifdef NO_PKCS11_BYPASS
-    HASH_HashBuf(HASH_AlgSHA256, snce.nameHash, name->data, name->len);
-#else
-    SHA256_HashBuf(snce.nameHash, (unsigned char *)name->data,
-                   name->len);
-#endif
-    /* get index of the next name */
-    ndx = Get32BitNameHash(name);
-    /* get lock on cert cache */
-    now = LockSidCacheLock(cache->srvNameCacheLock, 0);
-    if (now) {
-        if (cache->numSrvNameCacheEntries > 0) {
-            /* Fit the index into array */
-            ndx %= cache->numSrvNameCacheEntries;
-            /* write the entry */
-            cache->srvNameCacheData[ndx] = snce;
-            /* remember where we put it. */
-            sce->u.ssl3.srvNameIndex = ndx;
-            /* Copy hash into sid hash */
-            PORT_Memcpy(sce->u.ssl3.srvNameHash, snce.nameHash, SHA256_LENGTH);
-        }
-        UnlockSidCacheLock(cache->srvNameCacheLock);
-    }
-    return now;
-}
-
-/*
-** Convert local SID to shared memory one
-*/
-static void
-ConvertFromSID(sidCacheEntry *to, sslSessionID *from)
-{
-    to->valid = 1;
-    to->version = from->version;
-    to->addr = from->addr;
-    to->creationTime = from->creationTime;
-    to->lastAccessTime = from->lastAccessTime;
-    to->expirationTime = from->expirationTime;
-    to->authAlgorithm = from->authAlgorithm;
-    to->authKeyBits = from->authKeyBits;
-    to->keaType = from->keaType;
-    to->keaKeyBits = from->keaKeyBits;
-
-    if (from->version < SSL_LIBRARY_VERSION_3_0) {
-        if ((from->u.ssl2.masterKey.len > SSL_MAX_MASTER_KEY_BYTES) ||
-            (from->u.ssl2.cipherArg.len > SSL_MAX_CYPHER_ARG_BYTES)) {
-            SSL_DBG(("%d: SSL: masterKeyLen=%d cipherArgLen=%d",
-                     myPid, from->u.ssl2.masterKey.len,
-                     from->u.ssl2.cipherArg.len));
-            to->valid = 0;
-            return;
-        }
-
-        to->u.ssl2.cipherType = from->u.ssl2.cipherType;
-        to->u.ssl2.masterKeyLen = from->u.ssl2.masterKey.len;
-        to->u.ssl2.cipherArgLen = from->u.ssl2.cipherArg.len;
-        to->u.ssl2.keyBits = from->u.ssl2.keyBits;
-        to->u.ssl2.secretKeyBits = from->u.ssl2.secretKeyBits;
-        to->sessionIDLength = SSL2_SESSIONID_BYTES;
-        PORT_Memcpy(to->sessionID, from->u.ssl2.sessionID, SSL2_SESSIONID_BYTES);
-        PORT_Memcpy(to->u.ssl2.masterKey, from->u.ssl2.masterKey.data,
-                    from->u.ssl2.masterKey.len);
-        PORT_Memcpy(to->u.ssl2.cipherArg, from->u.ssl2.cipherArg.data,
-                    from->u.ssl2.cipherArg.len);
-#ifdef DEBUG
-        PORT_Memset(to->u.ssl2.masterKey + from->u.ssl2.masterKey.len, 0,
-                    sizeof(to->u.ssl2.masterKey) - from->u.ssl2.masterKey.len);
-        PORT_Memset(to->u.ssl2.cipherArg + from->u.ssl2.cipherArg.len, 0,
-                    sizeof(to->u.ssl2.cipherArg) - from->u.ssl2.cipherArg.len);
-#endif
-        SSL_TRC(8, ("%d: SSL: ConvertSID: masterKeyLen=%d cipherArgLen=%d "
-                    "time=%d addr=0x%08x%08x%08x%08x cipherType=%d",
-                    myPid,
-                    to->u.ssl2.masterKeyLen, to->u.ssl2.cipherArgLen,
-                    to->creationTime, to->addr.pr_s6_addr32[0],
-                    to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2],
-                    to->addr.pr_s6_addr32[3], to->u.ssl2.cipherType));
-    } else {
-        /* This is an SSL v3 session */
-
-        to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite;
-        to->u.ssl3.compression = (PRUint16)from->u.ssl3.compression;
-        to->u.ssl3.keys = from->u.ssl3.keys;
-        to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech;
-        to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType;
-        to->sessionIDLength = from->u.ssl3.sessionIDLength;
-        to->u.ssl3.certIndex = -1;
-        to->u.ssl3.srvNameIndex = -1;
-        PORT_Memcpy(to->sessionID, from->u.ssl3.sessionID,
-                    to->sessionIDLength);
-
-        SSL_TRC(8, ("%d: SSL3: ConvertSID: time=%d addr=0x%08x%08x%08x%08x "
-                    "cipherSuite=%d",
-                    myPid, to->creationTime, to->addr.pr_s6_addr32[0],
-                    to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2],
-                    to->addr.pr_s6_addr32[3], to->u.ssl3.cipherSuite));
-    }
-}
-
-/*
-** Convert shared memory cache-entry to local memory based one
-** This is only called from ServerSessionIDLookup().
-*/
-static sslSessionID *
-ConvertToSID(sidCacheEntry *from,
-             certCacheEntry *pcce,
-             srvNameCacheEntry *psnce,
-             CERTCertDBHandle *dbHandle)
-{
-    sslSessionID *to;
-    PRUint16 version = from->version;
-
-    to = PORT_ZNew(sslSessionID);
-    if (!to) {
-        return 0;
-    }
-
-    if (version < SSL_LIBRARY_VERSION_3_0) {
-        /* This is an SSL v2 session */
-        to->u.ssl2.masterKey.data =
-            (unsigned char *)PORT_Alloc(from->u.ssl2.masterKeyLen);
-        if (!to->u.ssl2.masterKey.data) {
-            goto loser;
-        }
-        if (from->u.ssl2.cipherArgLen) {
-            to->u.ssl2.cipherArg.data =
-                (unsigned char *)PORT_Alloc(from->u.ssl2.cipherArgLen);
-            if (!to->u.ssl2.cipherArg.data) {
-                goto loser;
-            }
-            PORT_Memcpy(to->u.ssl2.cipherArg.data, from->u.ssl2.cipherArg,
-                        from->u.ssl2.cipherArgLen);
-        }
-
-        to->u.ssl2.cipherType = from->u.ssl2.cipherType;
-        to->u.ssl2.masterKey.len = from->u.ssl2.masterKeyLen;
-        to->u.ssl2.cipherArg.len = from->u.ssl2.cipherArgLen;
-        to->u.ssl2.keyBits = from->u.ssl2.keyBits;
-        to->u.ssl2.secretKeyBits = from->u.ssl2.secretKeyBits;
-        /*  to->sessionIDLength      = SSL2_SESSIONID_BYTES; */
-        PORT_Memcpy(to->u.ssl2.sessionID, from->sessionID, SSL2_SESSIONID_BYTES);
-        PORT_Memcpy(to->u.ssl2.masterKey.data, from->u.ssl2.masterKey,
-                    from->u.ssl2.masterKeyLen);
-
-        SSL_TRC(8, ("%d: SSL: ConvertToSID: masterKeyLen=%d cipherArgLen=%d "
-                    "time=%d addr=0x%08x%08x%08x%08x cipherType=%d",
-                    myPid, to->u.ssl2.masterKey.len,
-                    to->u.ssl2.cipherArg.len, to->creationTime,
-                    to->addr.pr_s6_addr32[0], to->addr.pr_s6_addr32[1],
-                    to->addr.pr_s6_addr32[2], to->addr.pr_s6_addr32[3],
-                    to->u.ssl2.cipherType));
-    } else {
-        /* This is an SSL v3 session */
-
-        to->u.ssl3.sessionIDLength = from->sessionIDLength;
-        to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite;
-        to->u.ssl3.compression = (SSLCompressionMethod)from->u.ssl3.compression;
-        to->u.ssl3.keys = from->u.ssl3.keys;
-        to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech;
-        to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType;
-        if (from->u.ssl3.srvNameIndex != -1 && psnce) {
-            SECItem name;
-            SECStatus rv;
-            name.type = psnce->type;
-            name.len = psnce->nameLen;
-            name.data = psnce->name;
-            rv = SECITEM_CopyItem(NULL, &to->u.ssl3.srvName, &name);
-            if (rv != SECSuccess) {
-                goto loser;
-            }
-        }
-
-        PORT_Memcpy(to->u.ssl3.sessionID, from->sessionID, from->sessionIDLength);
-
-        /* the portions of the SID that are only restored on the client
-         * are set to invalid values on the server.
-         */
-        to->u.ssl3.clientWriteKey = NULL;
-        to->u.ssl3.serverWriteKey = NULL;
-
-        to->urlSvrName = NULL;
-
-        to->u.ssl3.masterModuleID = (SECMODModuleID)-1; /* invalid value */
-        to->u.ssl3.masterSlotID = (CK_SLOT_ID)-1;       /* invalid value */
-        to->u.ssl3.masterWrapIndex = 0;
-        to->u.ssl3.masterWrapSeries = 0;
-        to->u.ssl3.masterValid = PR_FALSE;
-
-        to->u.ssl3.clAuthModuleID = (SECMODModuleID)-1; /* invalid value */
-        to->u.ssl3.clAuthSlotID = (CK_SLOT_ID)-1;       /* invalid value */
-        to->u.ssl3.clAuthSeries = 0;
-        to->u.ssl3.clAuthValid = PR_FALSE;
-
-        if (from->u.ssl3.certIndex != -1 && pcce) {
-            SECItem derCert;
-
-            derCert.len = pcce->certLength;
-            derCert.data = pcce->cert;
-
-            to->peerCert = CERT_NewTempCertificate(dbHandle, &derCert, NULL,
-                                                   PR_FALSE, PR_TRUE);
-            if (to->peerCert == NULL)
-                goto loser;
-        }
-    }
-
-    to->version = from->version;
-    to->creationTime = from->creationTime;
-    to->lastAccessTime = from->lastAccessTime;
-    to->expirationTime = from->expirationTime;
-    to->cached = in_server_cache;
-    to->addr = from->addr;
-    to->references = 1;
-    to->authAlgorithm = from->authAlgorithm;
-    to->authKeyBits = from->authKeyBits;
-    to->keaType = from->keaType;
-    to->keaKeyBits = from->keaKeyBits;
-
-    return to;
-
-loser:
-    if (to) {
-        if (version < SSL_LIBRARY_VERSION_3_0) {
-            if (to->u.ssl2.masterKey.data)
-                PORT_Free(to->u.ssl2.masterKey.data);
-            if (to->u.ssl2.cipherArg.data)
-                PORT_Free(to->u.ssl2.cipherArg.data);
-        } else {
-            SECITEM_FreeItem(&to->u.ssl3.srvName, PR_FALSE);
-        }
-        PORT_Free(to);
-    }
-    return NULL;
-}
-
-/*
-** Perform some mumbo jumbo on the ip-address and the session-id value to
-** compute a hash value.
-*/
-static PRUint32
-SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s, unsigned nl)
-{
-    PRUint32 rv;
-    PRUint32 x[8];
-
-    memset(x, 0, sizeof x);
-    if (nl > sizeof x)
-        nl = sizeof x;
-    memcpy(x, s, nl);
-
-    rv = (addr->pr_s6_addr32[0] ^ addr->pr_s6_addr32[1] ^
-          addr->pr_s6_addr32[2] ^ addr->pr_s6_addr32[3] ^
-          x[0] ^ x[1] ^ x[2] ^ x[3] ^ x[4] ^ x[5] ^ x[6] ^ x[7]) %
-         cache->numSIDCacheSets;
-    return rv;
-}
-
-/*
-** Look something up in the cache. This will invalidate old entries
-** in the process. Caller has locked the cache set!
-** Returns PR_TRUE if found a valid match.  PR_FALSE otherwise.
-*/
-static sidCacheEntry *
-FindSID(cacheDesc *cache, PRUint32 setNum, PRUint32 now,
-        const PRIPv6Addr *addr, unsigned char *sessionID,
-        unsigned sessionIDLength)
-{
-    PRUint32 ndx = cache->sidCacheSets[setNum].next;
-    int i;
-
-    sidCacheEntry *set = cache->sidCacheData +
-                         (setNum * SID_CACHE_ENTRIES_PER_SET);
-
-    for (i = SID_CACHE_ENTRIES_PER_SET; i > 0; --i) {
-        sidCacheEntry *sce;
-
-        ndx = (ndx - 1) % SID_CACHE_ENTRIES_PER_SET;
-        sce = set + ndx;
-
-        if (!sce->valid)
-            continue;
-
-        if (now > sce->expirationTime) {
-            /* SessionID has timed out. Invalidate the entry. */
-            SSL_TRC(7, ("%d: timed out sid entry addr=%08x%08x%08x%08x now=%x "
-                        "time+=%x",
-                        myPid, sce->addr.pr_s6_addr32[0],
-                        sce->addr.pr_s6_addr32[1], sce->addr.pr_s6_addr32[2],
-                        sce->addr.pr_s6_addr32[3], now,
-                        sce->expirationTime));
-            sce->valid = 0;
-            continue;
-        }
-
-        /*
-        ** Next, examine specific session-id/addr data to see if the cache
-        ** entry matches our addr+session-id value
-        */
-        if (sessionIDLength == sce->sessionIDLength &&
-            !memcmp(&sce->addr, addr, sizeof(PRIPv6Addr)) &&
-            !memcmp(sce->sessionID, sessionID, sessionIDLength)) {
-            /* Found it */
-            return sce;
-        }
-    }
-
-    PORT_SetError(SSL_ERROR_SESSION_NOT_FOUND);
-    return NULL;
-}
-
-/************************************************************************/
-
-/* This is the primary function for finding entries in the server's sid cache.
- * Although it is static, this function is called via the global function
- * pointer ssl_sid_lookup.
- */
-static sslSessionID *
-ServerSessionIDLookup(const PRIPv6Addr *addr,
-                      unsigned char *sessionID,
-                      unsigned int sessionIDLength,
-                      CERTCertDBHandle *dbHandle)
-{
-    sslSessionID *sid = 0;
-    sidCacheEntry *psce;
-    certCacheEntry *pcce = 0;
-    srvNameCacheEntry *psnce = 0;
-    cacheDesc *cache = &globalCache;
-    PRUint32 now;
-    PRUint32 set;
-    PRInt32 cndx;
-    sidCacheEntry sce;
-    certCacheEntry cce;
-    srvNameCacheEntry snce;
-
-    set = SIDindex(cache, addr, sessionID, sessionIDLength);
-    now = LockSet(cache, set, 0);
-    if (!now)
-        return NULL;
-
-    psce = FindSID(cache, set, now, addr, sessionID, sessionIDLength);
-    if (psce) {
-        if (psce->version >= SSL_LIBRARY_VERSION_3_0) {
-            if ((cndx = psce->u.ssl3.certIndex) != -1) {
-
-                PRUint32 gotLock = LockSidCacheLock(cache->certCacheLock, now);
-                if (gotLock) {
-                    pcce = &cache->certCacheData[cndx];
-
-                    /* See if the cert's session ID matches the sce cache. */
-                    if ((pcce->sessionIDLength == psce->sessionIDLength) &&
-                        !PORT_Memcmp(pcce->sessionID, psce->sessionID,
-                                     pcce->sessionIDLength)) {
-                        cce = *pcce;
-                    } else {
-                        /* The cert doesen't match the SID cache entry,
-                        ** so invalidate the SID cache entry.
-                        */
-                        psce->valid = 0;
-                        psce = 0;
-                        pcce = 0;
-                    }
-                    UnlockSidCacheLock(cache->certCacheLock);
-                } else {
-                    /* what the ??.  Didn't get the cert cache lock.
-                    ** Don't invalidate the SID cache entry, but don't find it.
-                    */
-                    PORT_Assert(!("Didn't get cert Cache Lock!"));
-                    psce = 0;
-                    pcce = 0;
-                }
-            }
-            if (psce && ((cndx = psce->u.ssl3.srvNameIndex) != -1)) {
-                PRUint32 gotLock = LockSidCacheLock(cache->srvNameCacheLock,
-                                                    now);
-                if (gotLock) {
-                    psnce = &cache->srvNameCacheData[cndx];
-
-                    if (!PORT_Memcmp(psnce->nameHash, psce->u.ssl3.srvNameHash,
-                                     SHA256_LENGTH)) {
-                        snce = *psnce;
-                    } else {
-                        /* The name doesen't match the SID cache entry,
-                        ** so invalidate the SID cache entry.
-                        */
-                        psce->valid = 0;
-                        psce = 0;
-                        psnce = 0;
-                    }
-                    UnlockSidCacheLock(cache->srvNameCacheLock);
-                } else {
-                    /* what the ??.  Didn't get the cert cache lock.
-                    ** Don't invalidate the SID cache entry, but don't find it.
-                    */
-                    PORT_Assert(!("Didn't get name Cache Lock!"));
-                    psce = 0;
-                    psnce = 0;
-                }
-            }
-        }
-        if (psce) {
-            psce->lastAccessTime = now;
-            sce = *psce; /* grab a copy while holding the lock */
-        }
-    }
-    UnlockSet(cache, set);
-    if (psce) {
-        /* sce conains a copy of the cache entry.
-        ** Convert shared memory format to local format
-        */
-        sid = ConvertToSID(&sce, pcce ? &cce : 0, psnce ? &snce : 0, dbHandle);
-    }
-    return sid;
-}
-
-/*
-** Place a sid into the cache, if it isn't already there.
-*/
-static void
-ServerSessionIDCache(sslSessionID *sid)
-{
-    sidCacheEntry sce;
-    PRUint32 now = 0;
-    PRUint16 version = sid->version;
-    cacheDesc *cache = &globalCache;
-
-    if ((version >= SSL_LIBRARY_VERSION_3_0) &&
-        (sid->u.ssl3.sessionIDLength == 0)) {
-        return;
-    }
-
-    if (sid->cached == never_cached || sid->cached == invalid_cache) {
-        PRUint32 set;
-
-        PORT_Assert(sid->creationTime != 0);
-        if (!sid->creationTime)
-            sid->lastAccessTime = sid->creationTime = ssl_Time();
-        if (version < SSL_LIBRARY_VERSION_3_0) {
-            /* override caller's expiration time, which uses client timeout
-             * duration, not server timeout duration.
-             */
-            sid->expirationTime = sid->creationTime + cache->ssl2Timeout;
-            SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
-                        "cipher=%d",
-                        myPid, sid->cached,
-                        sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
-                        sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
-                        sid->creationTime, sid->u.ssl2.cipherType));
-            PRINT_BUF(8, (0, "sessionID:", sid->u.ssl2.sessionID,
-                          SSL2_SESSIONID_BYTES));
-            PRINT_BUF(8, (0, "masterKey:", sid->u.ssl2.masterKey.data,
-                          sid->u.ssl2.masterKey.len));
-            PRINT_BUF(8, (0, "cipherArg:", sid->u.ssl2.cipherArg.data,
-                          sid->u.ssl2.cipherArg.len));
-        } else {
-            /* override caller's expiration time, which uses client timeout
-             * duration, not server timeout duration.
-             */
-            sid->expirationTime = sid->creationTime + cache->ssl3Timeout;
-            SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
-                        "cipherSuite=%d",
-                        myPid, sid->cached,
-                        sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
-                        sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
-                        sid->creationTime, sid->u.ssl3.cipherSuite));
-            PRINT_BUF(8, (0, "sessionID:", sid->u.ssl3.sessionID,
-                          sid->u.ssl3.sessionIDLength));
-        }
-
-        ConvertFromSID(&sce, sid);
-
-        if (version >= SSL_LIBRARY_VERSION_3_0) {
-            SECItem *name = &sid->u.ssl3.srvName;
-            if (name->len && name->data) {
-                now = CacheSrvName(cache, name, &sce);
-            }
-            if (sid->peerCert != NULL) {
-                now = CacheCert(cache, sid->peerCert, &sce);
-            }
-        }
-
-        set = SIDindex(cache, &sce.addr, sce.sessionID, sce.sessionIDLength);
-        now = LockSet(cache, set, now);
-        if (now) {
-            PRUint32 next = cache->sidCacheSets[set].next;
-            PRUint32 ndx = set * SID_CACHE_ENTRIES_PER_SET + next;
-
-            /* Write out new cache entry */
-            cache->sidCacheData[ndx] = sce;
-
-            cache->sidCacheSets[set].next =
-                (next + 1) % SID_CACHE_ENTRIES_PER_SET;
-
-            UnlockSet(cache, set);
-            sid->cached = in_server_cache;
-        }
-    }
-}
-
-/*
-** Although this is static, it is called from ssl via global function pointer
-**  ssl_sid_uncache.  This invalidates the referenced cache entry.
-*/
-static void
-ServerSessionIDUncache(sslSessionID *sid)
-{
-    cacheDesc *cache = &globalCache;
-    PRUint8 *sessionID;
-    unsigned int sessionIDLength;
-    PRErrorCode err;
-    PRUint32 set;
-    PRUint32 now;
-    sidCacheEntry *psce;
-
-    if (sid == NULL)
-        return;
-
-    /* Uncaching a SID should never change the error code.
-    ** So save it here and restore it before exiting.
-    */
-    err = PR_GetError();
-
-    if (sid->version < SSL_LIBRARY_VERSION_3_0) {
-        sessionID = sid->u.ssl2.sessionID;
-        sessionIDLength = SSL2_SESSIONID_BYTES;
-        SSL_TRC(8, ("%d: SSL: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
-                    "cipher=%d",
-                    myPid, sid->cached,
-                    sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
-                    sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
-                    sid->creationTime, sid->u.ssl2.cipherType));
-        PRINT_BUF(8, (0, "sessionID:", sessionID, sessionIDLength));
-        PRINT_BUF(8, (0, "masterKey:", sid->u.ssl2.masterKey.data,
-                      sid->u.ssl2.masterKey.len));
-        PRINT_BUF(8, (0, "cipherArg:", sid->u.ssl2.cipherArg.data,
-                      sid->u.ssl2.cipherArg.len));
-    } else {
-        sessionID = sid->u.ssl3.sessionID;
-        sessionIDLength = sid->u.ssl3.sessionIDLength;
-        SSL_TRC(8, ("%d: SSL3: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
-                    "cipherSuite=%d",
-                    myPid, sid->cached,
-                    sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
-                    sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
-                    sid->creationTime, sid->u.ssl3.cipherSuite));
-        PRINT_BUF(8, (0, "sessionID:", sessionID, sessionIDLength));
-    }
-    set = SIDindex(cache, &sid->addr, sessionID, sessionIDLength);
-    now = LockSet(cache, set, 0);
-    if (now) {
-        psce = FindSID(cache, set, now, &sid->addr, sessionID, sessionIDLength);
-        if (psce) {
-            psce->valid = 0;
-        }
-        UnlockSet(cache, set);
-    }
-    sid->cached = invalid_cache;
-    PORT_SetError(err);
-}
-
-#ifdef XP_OS2
-
-#define INCL_DOSPROCESS
-#include <os2.h>
-
-long
-gettid(void)
-{
-    PTIB ptib;
-    PPIB ppib;
-    DosGetInfoBlocks(&ptib, &ppib);
-    return ((long)ptib->tib_ordinal); /* thread id */
-}
-#endif
-
-static void
-CloseCache(cacheDesc *cache)
-{
-    int locks_initialized = cache->numSIDCacheLocksInitialized;
-
-    if (cache->cacheMem) {
-        if (cache->sharedCache) {
-            sidCacheLock *pLock = cache->sidCacheLocks;
-            for (; locks_initialized > 0; --locks_initialized, ++pLock) {
-                /* If everInherited is true, this shared cache was (and may
-                ** still be) in use by multiple processes.  We do not wish to
-                ** destroy the mutexes while they are still in use, but we do
-                ** want to free mutex resources associated with this process.
-                */
-                sslMutex_Destroy(&pLock->mutex,
-                                 cache->sharedCache->everInherited);
-            }
-        }
-        if (cache->shared) {
-            PR_MemUnmap(cache->cacheMem, cache->cacheMemSize);
-        } else {
-            PORT_Free(cache->cacheMem);
-        }
-        cache->cacheMem = NULL;
-    }
-    if (cache->cacheMemMap) {
-        PR_CloseFileMap(cache->cacheMemMap);
-        cache->cacheMemMap = NULL;
-    }
-    memset(cache, 0, sizeof *cache);
-}
-
-static SECStatus
-InitCache(cacheDesc *cache, int maxCacheEntries, int maxCertCacheEntries,
-          int maxSrvNameCacheEntries, PRUint32 ssl2_timeout,
-          PRUint32 ssl3_timeout, const char *directory, PRBool shared)
-{
-    ptrdiff_t ptr;
-    sidCacheLock *pLock;
-    char *cacheMem;
-    PRFileMap *cacheMemMap;
-    char *cfn = NULL; /* cache file name */
-    int locks_initialized = 0;
-    int locks_to_initialize = 0;
-    PRUint32 init_time;
-
-    if ((!cache) || (maxCacheEntries < 0) || (!directory)) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    if (cache->cacheMem) {
-        /* Already done */
-        return SECSuccess;
-    }
-
-    /* make sure loser can clean up properly */
-    cache->shared = shared;
-    cache->cacheMem = cacheMem = NULL;
-    cache->cacheMemMap = cacheMemMap = NULL;
-    cache->sharedCache = (cacheDesc *)0;
-
-    cache->numSIDCacheLocksInitialized = 0;
-    cache->nextCertCacheEntry = 0;
-    cache->stopPolling = PR_FALSE;
-    cache->everInherited = PR_FALSE;
-    cache->poller = NULL;
-    cache->mutexTimeout = 0;
-
-    cache->numSIDCacheEntries = maxCacheEntries ? maxCacheEntries
-                                                : DEF_SID_CACHE_ENTRIES;
-    cache->numSIDCacheSets =
-        SID_HOWMANY(cache->numSIDCacheEntries, SID_CACHE_ENTRIES_PER_SET);
-
-    cache->numSIDCacheEntries =
-        cache->numSIDCacheSets * SID_CACHE_ENTRIES_PER_SET;
-
-    cache->numSIDCacheLocks =
-        PR_MIN(cache->numSIDCacheSets, ssl_max_sid_cache_locks);
-
-    cache->numSIDCacheSetsPerLock =
-        SID_HOWMANY(cache->numSIDCacheSets, cache->numSIDCacheLocks);
-
-    cache->numCertCacheEntries = (maxCertCacheEntries > 0) ? maxCertCacheEntries
-                                                           : 0;
-    cache->numSrvNameCacheEntries = (maxSrvNameCacheEntries >= 0) ? maxSrvNameCacheEntries
-                                                                  : DEF_NAME_CACHE_ENTRIES;
-
-    /* compute size of shared memory, and offsets of all pointers */
-    ptr = 0;
-    cache->cacheMem = (char *)ptr;
-    ptr += SID_ROUNDUP(sizeof(cacheDesc), SID_ALIGNMENT);
-
-    cache->sidCacheLocks = (sidCacheLock *)ptr;
-    cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks;
-    cache->certCacheLock = cache->keyCacheLock + 1;
-    cache->srvNameCacheLock = cache->certCacheLock + 1;
-    ptr = (ptrdiff_t)(cache->srvNameCacheLock + 1);
-    ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
-    cache->sidCacheSets = (sidCacheSet *)ptr;
-    ptr = (ptrdiff_t)(cache->sidCacheSets + cache->numSIDCacheSets);
-    ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
-    cache->sidCacheData = (sidCacheEntry *)ptr;
-    ptr = (ptrdiff_t)(cache->sidCacheData + cache->numSIDCacheEntries);
-    ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
-    cache->certCacheData = (certCacheEntry *)ptr;
-    cache->sidCacheSize =
-        (char *)cache->certCacheData - (char *)cache->sidCacheData;
-
-    if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES) {
-        /* This is really a poor way to computer this! */
-        cache->numCertCacheEntries = cache->sidCacheSize / sizeof(certCacheEntry);
-        if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES)
-            cache->numCertCacheEntries = MIN_CERT_CACHE_ENTRIES;
-    }
-    ptr = (ptrdiff_t)(cache->certCacheData + cache->numCertCacheEntries);
-    ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
-    cache->keyCacheData = (SSLWrappedSymWrappingKey *)ptr;
-    cache->certCacheSize =
-        (char *)cache->keyCacheData - (char *)cache->certCacheData;
-
-    cache->numKeyCacheEntries = kt_kea_size * SSL_NUM_WRAP_MECHS;
-    ptr = (ptrdiff_t)(cache->keyCacheData + cache->numKeyCacheEntries);
-    ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
-    cache->keyCacheSize = (char *)ptr - (char *)cache->keyCacheData;
-
-    cache->ticketKeyNameSuffix = (PRUint8 *)ptr;
-    ptr = (ptrdiff_t)(cache->ticketKeyNameSuffix +
-                      SESS_TICKET_KEY_VAR_NAME_LEN);
-    ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
-    cache->ticketEncKey = (encKeyCacheEntry *)ptr;
-    ptr = (ptrdiff_t)(cache->ticketEncKey + 1);
-    ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
-    cache->ticketMacKey = (encKeyCacheEntry *)ptr;
-    ptr = (ptrdiff_t)(cache->ticketMacKey + 1);
-    ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
-    cache->ticketKeysValid = (PRUint32 *)ptr;
-    ptr = (ptrdiff_t)(cache->ticketKeysValid + 1);
-    ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
-    cache->srvNameCacheData = (srvNameCacheEntry *)ptr;
-    cache->srvNameCacheSize =
-        cache->numSrvNameCacheEntries * sizeof(srvNameCacheEntry);
-    ptr = (ptrdiff_t)(cache->srvNameCacheData + cache->numSrvNameCacheEntries);
-    ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
-    cache->cacheMemSize = ptr;
-
-    if (ssl2_timeout) {
-        if (ssl2_timeout > MAX_SSL2_TIMEOUT) {
-            ssl2_timeout = MAX_SSL2_TIMEOUT;
-        }
-        if (ssl2_timeout < MIN_SSL2_TIMEOUT) {
-            ssl2_timeout = MIN_SSL2_TIMEOUT;
-        }
-        cache->ssl2Timeout = ssl2_timeout;
-    } else {
-        cache->ssl2Timeout = DEF_SSL2_TIMEOUT;
-    }
-
-    if (ssl3_timeout) {
-        if (ssl3_timeout > MAX_SSL3_TIMEOUT) {
-            ssl3_timeout = MAX_SSL3_TIMEOUT;
-        }
-        if (ssl3_timeout < MIN_SSL3_TIMEOUT) {
-            ssl3_timeout = MIN_SSL3_TIMEOUT;
-        }
-        cache->ssl3Timeout = ssl3_timeout;
-    } else {
-        cache->ssl3Timeout = DEF_SSL3_TIMEOUT;
-    }
-
-    if (shared) {
-    /* Create file names */
-#if defined(XP_UNIX) || defined(XP_BEOS)
-        /* there's some confusion here about whether PR_OpenAnonFileMap wants
-        ** a directory name or a file name for its first argument.
-        cfn = PR_smprintf("%s/.sslsvrcache.%d", directory, myPid);
-        */
-        cfn = PR_smprintf("%s", directory);
-#elif defined(XP_WIN32)
-        cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid,
-                          GetCurrentThreadId());
-#elif defined(XP_OS2)
-        cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid,
-                          gettid());
-#else
-#error "Don't know how to create file name for this platform!"
-#endif
-        if (!cfn) {
-            goto loser;
-        }
-
-        /* Create cache */
-        cacheMemMap = PR_OpenAnonFileMap(cfn, cache->cacheMemSize,
-                                         PR_PROT_READWRITE);
-
-        PR_smprintf_free(cfn);
-        if (!cacheMemMap) {
-            goto loser;
-        }
-
-        cacheMem = PR_MemMap(cacheMemMap, 0, cache->cacheMemSize);
-    } else {
-        cacheMem = PORT_Alloc(cache->cacheMemSize);
-    }
-
-    if (!cacheMem) {
-        goto loser;
-    }
-
-    /* Initialize shared memory. This may not be necessary on all platforms */
-    memset(cacheMem, 0, cache->cacheMemSize);
-
-    /* Copy cache descriptor header into shared memory */
-    memcpy(cacheMem, cache, sizeof *cache);
-
-    /* save private copies of these values */
-    cache->cacheMemMap = cacheMemMap;
-    cache->cacheMem = cacheMem;
-    cache->sharedCache = (cacheDesc *)cacheMem;
-
-    /* Fix pointers in our private copy of cache descriptor to point to
-    ** spaces in shared memory
-    */
-    cache->sidCacheLocks = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->sidCacheLocks);
-    cache->keyCacheLock = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->keyCacheLock);
-    cache->certCacheLock = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->certCacheLock);
-    cache->srvNameCacheLock = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->srvNameCacheLock);
-    cache->sidCacheSets = (sidCacheSet *)(cache->cacheMem + (ptrdiff_t)cache->sidCacheSets);
-    cache->sidCacheData = (sidCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->sidCacheData);
-    cache->certCacheData = (certCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->certCacheData);
-    cache->keyCacheData = (SSLWrappedSymWrappingKey *)(cache->cacheMem + (ptrdiff_t)cache->keyCacheData);
-    cache->ticketKeyNameSuffix = (PRUint8 *)(cache->cacheMem + (ptrdiff_t)cache->ticketKeyNameSuffix);
-    cache->ticketEncKey = (encKeyCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->ticketEncKey);
-    cache->ticketMacKey = (encKeyCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->ticketMacKey);
-    cache->ticketKeysValid = (PRUint32 *)(cache->cacheMem + (ptrdiff_t)cache->ticketKeysValid);
-    cache->srvNameCacheData = (srvNameCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->srvNameCacheData);
-
-    /* initialize the locks */
-    init_time = ssl_Time();
-    pLock = cache->sidCacheLocks;
-    for (locks_to_initialize = cache->numSIDCacheLocks + 3;
-         locks_initialized < locks_to_initialize;
-         ++locks_initialized, ++pLock) {
-
-        SECStatus err = sslMutex_Init(&pLock->mutex, shared);
-        if (err) {
-            cache->numSIDCacheLocksInitialized = locks_initialized;
-            goto loser;
-        }
-        pLock->timeStamp = init_time;
-        pLock->pid = 0;
-    }
-    cache->numSIDCacheLocksInitialized = locks_initialized;
-
-    return SECSuccess;
-
-loser:
-    CloseCache(cache);
-    return SECFailure;
-}
-
-PRUint32
-SSL_GetMaxServerCacheLocks(void)
-{
-    return ssl_max_sid_cache_locks + 2;
-    /* The extra two are the cert cache lock and the key cache lock. */
-}
-
-SECStatus
-SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)
-{
-    /* Minimum is 1 sid cache lock, 1 cert cache lock and 1 key cache lock.
-    ** We'd like to test for a maximum value, but not all platforms' header
-    ** files provide a symbol or function or other means of determining
-    ** the maximum, other than trial and error.
-    */
-    if (maxLocks < 3) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-    ssl_max_sid_cache_locks = maxLocks - 2;
-    /* The extra two are the cert cache lock and the key cache lock. */
-    return SECSuccess;
-}
-
-static SECStatus
-ssl_ConfigServerSessionIDCacheInstanceWithOpt(cacheDesc *cache,
-                                              PRUint32 ssl2_timeout,
-                                              PRUint32 ssl3_timeout,
-                                              const char *directory,
-                                              PRBool shared,
-                                              int maxCacheEntries,
-                                              int maxCertCacheEntries,
-                                              int maxSrvNameCacheEntries)
-{
-    SECStatus rv;
-
-    PORT_Assert(sizeof(sidCacheEntry) == 192);
-    PORT_Assert(sizeof(certCacheEntry) == 4096);
-    PORT_Assert(sizeof(srvNameCacheEntry) == 1072);
-
-    rv = ssl_Init();
-    if (rv != SECSuccess) {
-        return rv;
-    }
-
-    myPid = SSL_GETPID();
-    if (!directory) {
-        directory = DEFAULT_CACHE_DIRECTORY;
-    }
-    rv = InitCache(cache, maxCacheEntries, maxCertCacheEntries,
-                   maxSrvNameCacheEntries, ssl2_timeout, ssl3_timeout,
-                   directory, shared);
-    if (rv) {
-        SET_ERROR_CODE
-        return SECFailure;
-    }
-
-    ssl_sid_lookup = ServerSessionIDLookup;
-    ssl_sid_cache = ServerSessionIDCache;
-    ssl_sid_uncache = ServerSessionIDUncache;
-    return SECSuccess;
-}
-
-SECStatus
-SSL_ConfigServerSessionIDCacheInstance(cacheDesc *cache,
-                                       int maxCacheEntries,
-                                       PRUint32 ssl2_timeout,
-                                       PRUint32 ssl3_timeout,
-                                       const char *directory, PRBool shared)
-{
-    return ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache,
-                                                         ssl2_timeout,
-                                                         ssl3_timeout,
-                                                         directory,
-                                                         shared,
-                                                         maxCacheEntries,
-                                                         -1, -1);
-}
-
-SECStatus
-SSL_ConfigServerSessionIDCache(int maxCacheEntries,
-                               PRUint32 ssl2_timeout,
-                               PRUint32 ssl3_timeout,
-                               const char *directory)
-{
-    ssl_InitSessionCacheLocks();
-    return SSL_ConfigServerSessionIDCacheInstance(&globalCache,
-                                                  maxCacheEntries, ssl2_timeout, ssl3_timeout, directory, PR_FALSE);
-}
-
-SECStatus
-SSL_ShutdownServerSessionIDCacheInstance(cacheDesc *cache)
-{
-    CloseCache(cache);
-    return SECSuccess;
-}
-
-SECStatus
-SSL_ShutdownServerSessionIDCache(void)
-{
-#if defined(XP_UNIX) || defined(XP_BEOS)
-    /* Stop the thread that polls cache for expired locks on Unix */
-    StopLockPoller(&globalCache);
-#endif
-    SSL3_ShutdownServerCache();
-    return SSL_ShutdownServerSessionIDCacheInstance(&globalCache);
-}
-
-/* Use this function, instead of SSL_ConfigServerSessionIDCache,
- * if the cache will be shared by multiple processes.
- */
-static SECStatus
-ssl_ConfigMPServerSIDCacheWithOpt(PRUint32 ssl2_timeout,
-                                  PRUint32 ssl3_timeout,
-                                  const char *directory,
-                                  int maxCacheEntries,
-                                  int maxCertCacheEntries,
-                                  int maxSrvNameCacheEntries)
-{
-    char *envValue;
-    char *inhValue;
-    cacheDesc *cache = &globalCache;
-    PRUint32 fmStrLen;
-    SECStatus result;
-    PRStatus prStatus;
-    SECStatus putEnvFailed;
-    inheritance inherit;
-    char fmString[PR_FILEMAP_STRING_BUFSIZE];
-
-    isMultiProcess = PR_TRUE;
-    result = ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache,
-                                                           ssl2_timeout, ssl3_timeout, directory, PR_TRUE,
-                                                           maxCacheEntries, maxCacheEntries, maxSrvNameCacheEntries);
-    if (result != SECSuccess)
-        return result;
-
-    prStatus = PR_ExportFileMapAsString(cache->cacheMemMap,
-                                        sizeof fmString, fmString);
-    if ((prStatus != PR_SUCCESS) || !(fmStrLen = strlen(fmString))) {
-        SET_ERROR_CODE
-        return SECFailure;
-    }
-
-    inherit.cacheMemSize = cache->cacheMemSize;
-    inherit.fmStrLen = fmStrLen;
-
-    inhValue = BTOA_DataToAscii((unsigned char *)&inherit, sizeof inherit);
-    if (!inhValue || !strlen(inhValue)) {
-        SET_ERROR_CODE
-        return SECFailure;
-    }
-    envValue = PR_smprintf("%s,%s", inhValue, fmString);
-    if (!envValue || !strlen(envValue)) {
-        SET_ERROR_CODE
-        return SECFailure;
-    }
-    PORT_Free(inhValue);
-
-    putEnvFailed = (SECStatus)NSS_PutEnv(envVarName, envValue);
-    PR_smprintf_free(envValue);
-    if (putEnvFailed) {
-        SET_ERROR_CODE
-        result = SECFailure;
-    }
-
-#if defined(XP_UNIX) || defined(XP_BEOS)
-    /* Launch thread to poll cache for expired locks on Unix */
-    LaunchLockPoller(cache);
-#endif
-    return result;
-}
-
-/* Use this function, instead of SSL_ConfigServerSessionIDCache,
- * if the cache will be shared by multiple processes.
- */
-SECStatus
-SSL_ConfigMPServerSIDCache(int maxCacheEntries,
-                           PRUint32 ssl2_timeout,
-                           PRUint32 ssl3_timeout,
-                           const char *directory)
-{
-    return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout,
-                                             ssl3_timeout,
-                                             directory,
-                                             maxCacheEntries,
-                                             -1, -1);
-}
-
-SECStatus
-SSL_ConfigServerSessionIDCacheWithOpt(
-    PRUint32 ssl2_timeout,
-    PRUint32 ssl3_timeout,
-    const char *directory,
-    int maxCacheEntries,
-    int maxCertCacheEntries,
-    int maxSrvNameCacheEntries,
-    PRBool enableMPCache)
-{
-    if (!enableMPCache) {
-        ssl_InitSessionCacheLocks();
-        return ssl_ConfigServerSessionIDCacheInstanceWithOpt(&globalCache,
-                                                             ssl2_timeout, ssl3_timeout, directory, PR_FALSE,
-                                                             maxCacheEntries, maxCertCacheEntries, maxSrvNameCacheEntries);
-    } else {
-        return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout, ssl3_timeout,
-                                                 directory, maxCacheEntries, maxCertCacheEntries,
-                                                 maxSrvNameCacheEntries);
-    }
-}
-
-SECStatus
-SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char *envString)
-{
-    unsigned char *decoString = NULL;
-    char *fmString = NULL;
-    char *myEnvString = NULL;
-    unsigned int decoLen;
-    inheritance inherit;
-    cacheDesc my;
-#ifdef WINNT
-    sidCacheLock *newLocks;
-    int locks_initialized = 0;
-    int locks_to_initialize = 0;
-#endif
-    SECStatus status = ssl_Init();
-
-    if (status != SECSuccess) {
-        return status;
-    }
-
-    myPid = SSL_GETPID();
-
-    /* If this child was created by fork(), and not by exec() on unix,
-    ** then isMultiProcess will already be set.
-    ** If not, we'll set it below.
-    */
-    if (isMultiProcess) {
-        if (cache && cache->sharedCache) {
-            cache->sharedCache->everInherited = PR_TRUE;
-        }
-        return SECSuccess; /* already done. */
-    }
-
-    ssl_InitSessionCacheLocks();
-
-    ssl_sid_lookup = ServerSessionIDLookup;
-    ssl_sid_cache = ServerSessionIDCache;
-    ssl_sid_uncache = ServerSessionIDUncache;
-
-    if (!envString) {
-        envString = PR_GetEnvSecure(envVarName);
-        if (!envString) {
-            SET_ERROR_CODE
-            return SECFailure;
-        }
-    }
-    myEnvString = PORT_Strdup(envString);
-    if (!myEnvString)
-        return SECFailure;
-    fmString = strchr(myEnvString, ',');
-    if (!fmString)
-        goto loser;
-    *fmString++ = 0;
-
-    decoString = ATOB_AsciiToData(myEnvString, &decoLen);
-    if (!decoString) {
-        SET_ERROR_CODE
-        goto loser;
-    }
-    if (decoLen != sizeof inherit) {
-        SET_ERROR_CODE
-        goto loser;
-    }
-
-    PORT_Memcpy(&inherit, decoString, sizeof inherit);
-
-    if (strlen(fmString) != inherit.fmStrLen) {
-        goto loser;
-    }
-
-    memset(cache, 0, sizeof *cache);
-    cache->cacheMemSize = inherit.cacheMemSize;
-
-    /* Create cache */
-    cache->cacheMemMap = PR_ImportFileMapFromString(fmString);
-    if (!cache->cacheMemMap) {
-        goto loser;
-    }
-    cache->cacheMem = PR_MemMap(cache->cacheMemMap, 0, cache->cacheMemSize);
-    if (!cache->cacheMem) {
-        goto loser;
-    }
-    cache->sharedCache = (cacheDesc *)cache->cacheMem;
-
-    if (cache->sharedCache->cacheMemSize != cache->cacheMemSize) {
-        SET_ERROR_CODE
-        goto loser;
-    }
-
-    /* We're now going to overwrite the local cache instance with the
-    ** shared copy of the cache struct, then update several values in
-    ** the local cache using the values for cache->cacheMemMap and
-    ** cache->cacheMem computed just above.  So, we copy cache into
-    ** the automatic variable "my", to preserve the variables while
-    ** cache is overwritten.
-    */
-    my = *cache;                                      /* save values computed above. */
-    memcpy(cache, cache->sharedCache, sizeof *cache); /* overwrite */
-
-    /* Fix pointers in our private copy of cache descriptor to point to
-    ** spaces in shared memory, whose address is now in "my".
-    */
-    cache->sidCacheLocks = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->sidCacheLocks);
-    cache->keyCacheLock = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->keyCacheLock);
-    cache->certCacheLock = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->certCacheLock);
-    cache->srvNameCacheLock = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->srvNameCacheLock);
-    cache->sidCacheSets = (sidCacheSet *)(my.cacheMem + (ptrdiff_t)cache->sidCacheSets);
-    cache->sidCacheData = (sidCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->sidCacheData);
-    cache->certCacheData = (certCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->certCacheData);
-    cache->keyCacheData = (SSLWrappedSymWrappingKey *)(my.cacheMem + (ptrdiff_t)cache->keyCacheData);
-    cache->ticketKeyNameSuffix = (PRUint8 *)(my.cacheMem + (ptrdiff_t)cache->ticketKeyNameSuffix);
-    cache->ticketEncKey = (encKeyCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->ticketEncKey);
-    cache->ticketMacKey = (encKeyCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->ticketMacKey);
-    cache->ticketKeysValid = (PRUint32 *)(my.cacheMem + (ptrdiff_t)cache->ticketKeysValid);
-    cache->srvNameCacheData = (srvNameCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->srvNameCacheData);
-
-    cache->cacheMemMap = my.cacheMemMap;
-    cache->cacheMem = my.cacheMem;
-    cache->sharedCache = (cacheDesc *)cache->cacheMem;
-
-#ifdef WINNT
-    /*  On Windows NT we need to "fix" the sidCacheLocks here to support fibers
-    **  When NT fibers are used in a multi-process server, a second level of
-    **  locking is needed to prevent a deadlock, in case a fiber acquires the
-    **  cross-process mutex, yields, and another fiber is later scheduled on
-    **  the same native thread and tries to acquire the cross-process mutex.
-    **  We do this by using a PRLock in the sslMutex. However, it is stored in
-    **  shared memory as part of sidCacheLocks, and we don't want to overwrite
-    **  the PRLock of the parent process. So we need to make new, private
-    **  copies of sidCacheLocks before modifying the sslMutex with our own
-    **  PRLock
-    */
-
-    /* note from jpierre : this should be free'd in child processes when
-    ** a function is added to delete the SSL session cache in the future.
-    */
-    locks_to_initialize = cache->numSIDCacheLocks + 3;
-    newLocks = PORT_NewArray(sidCacheLock, locks_to_initialize);
-    if (!newLocks)
-        goto loser;
-    /* copy the old locks */
-    memcpy(newLocks, cache->sidCacheLocks,
-           locks_to_initialize * sizeof(sidCacheLock));
-    cache->sidCacheLocks = newLocks;
-    /* fix the locks */
-    for (; locks_initialized < locks_to_initialize; ++locks_initialized) {
-        /* now, make a local PRLock in this sslMutex for this child process */
-        SECStatus err;
-        err = sslMutex_2LevelInit(&newLocks[locks_initialized].mutex);
-        if (err != SECSuccess) {
-            cache->numSIDCacheLocksInitialized = locks_initialized;
-            goto loser;
-        }
-    }
-    cache->numSIDCacheLocksInitialized = locks_initialized;
-
-    /* also fix the key and cert cache which use the last 2 lock entries */
-    cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks;
-    cache->certCacheLock = cache->keyCacheLock + 1;
-    cache->srvNameCacheLock = cache->certCacheLock + 1;
-#endif
-
-    PORT_Free(myEnvString);
-    PORT_Free(decoString);
-
-    /* mark that we have inherited this. */
-    cache->sharedCache->everInherited = PR_TRUE;
-    isMultiProcess = PR_TRUE;
-
-    return SECSuccess;
-
-loser:
-    PORT_Free(myEnvString);
-    if (decoString)
-        PORT_Free(decoString);
-    CloseCache(cache);
-    return SECFailure;
-}
-
-SECStatus
-SSL_InheritMPServerSIDCache(const char *envString)
-{
-    return SSL_InheritMPServerSIDCacheInstance(&globalCache, envString);
-}
-
-#if defined(XP_UNIX) || defined(XP_BEOS)
-
-#define SID_LOCK_EXPIRATION_TIMEOUT 30 /* seconds */
-
-static void
-LockPoller(void *arg)
-{
-    cacheDesc *cache = (cacheDesc *)arg;
-    cacheDesc *sharedCache = cache->sharedCache;
-    sidCacheLock *pLock;
-    PRIntervalTime timeout;
-    PRUint32 now;
-    PRUint32 then;
-    int locks_polled = 0;
-    int locks_to_poll = cache->numSIDCacheLocks + 2;
-    PRUint32 expiration = cache->mutexTimeout;
-
-    timeout = PR_SecondsToInterval(expiration);
-    while (!sharedCache->stopPolling) {
-        PR_Sleep(timeout);
-        if (sharedCache->stopPolling)
-            break;
-
-        now = ssl_Time();
-        then = now - expiration;
-        for (pLock = cache->sidCacheLocks, locks_polled = 0;
-             locks_to_poll > locks_polled && !sharedCache->stopPolling;
-             ++locks_polled, ++pLock) {
-            pid_t pid;
-
-            if (pLock->timeStamp < then &&
-                pLock->timeStamp != 0 &&
-                (pid = pLock->pid) != 0) {
-
-                /* maybe we should try the lock? */
-                int result = kill(pid, 0);
-                if (result < 0 && errno == ESRCH) {
-                    SECStatus rv;
-                    /* No process exists by that pid any more.
-                    ** Treat this mutex as abandoned.
-                    */
-                    pLock->timeStamp = now;
-                    pLock->pid = 0;
-                    rv = sslMutex_Unlock(&pLock->mutex);
-                    if (rv != SECSuccess) {
-                        /* Now what? */
-                    }
-                }
-            }
-        } /* end of loop over locks */
-    }     /* end of entire polling loop */
-}
-
-/* Launch thread to poll cache for expired locks */
-static SECStatus
-LaunchLockPoller(cacheDesc *cache)
-{
-    const char *timeoutString;
-    PRThread *pollerThread;
-
-    cache->mutexTimeout = SID_LOCK_EXPIRATION_TIMEOUT;
-    timeoutString = PR_GetEnvSecure("NSS_SSL_SERVER_CACHE_MUTEX_TIMEOUT");
-    if (timeoutString) {
-        long newTime = strtol(timeoutString, 0, 0);
-        if (newTime == 0)
-            return SECSuccess; /* application doesn't want poller thread */
-        if (newTime > 0)
-            cache->mutexTimeout = (PRUint32)newTime;
-        /* if error (newTime < 0) ignore it and use default */
-    }
-
-    pollerThread =
-        PR_CreateThread(PR_USER_THREAD, LockPoller, cache, PR_PRIORITY_NORMAL,
-                        PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
-    if (!pollerThread) {
-        return SECFailure;
-    }
-    cache->poller = pollerThread;
-    return SECSuccess;
-}
-
-/* Stop the thread that polls cache for expired locks */
-static SECStatus
-StopLockPoller(cacheDesc *cache)
-{
-    if (!cache->poller) {
-        return SECSuccess;
-    }
-    cache->sharedCache->stopPolling = PR_TRUE;
-    if (PR_Interrupt(cache->poller) != PR_SUCCESS) {
-        return SECFailure;
-    }
-    if (PR_JoinThread(cache->poller) != PR_SUCCESS) {
-        return SECFailure;
-    }
-    cache->poller = NULL;
-    return SECSuccess;
-}
-#endif
-
-/************************************************************************
- *  Code dealing with shared wrapped symmetric wrapping keys below      *
- ************************************************************************/
-
-/* If now is zero, it implies that the lock is not held, and must be
-** aquired here.
-*/
-static PRBool
-getSvrWrappingKey(PRInt32 symWrapMechIndex,
-                  SSL3KEAType exchKeyType,
-                  SSLWrappedSymWrappingKey *wswk,
-                  cacheDesc *cache,
-                  PRUint32 lockTime)
-{
-    PRUint32 ndx = (exchKeyType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex;
-    SSLWrappedSymWrappingKey *pwswk = cache->keyCacheData + ndx;
-    PRUint32 now = 0;
-    PRBool rv = PR_FALSE;
-
-    if (!cache->cacheMem) { /* cache is uninitialized */
-        PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);
-        return rv;
-    }
-    if (!lockTime) {
-        lockTime = now = LockSidCacheLock(cache->keyCacheLock, now);
-        if (!lockTime) {
-            return rv;
-        }
-    }
-    if (pwswk->exchKeyType == exchKeyType &&
-        pwswk->symWrapMechIndex == symWrapMechIndex &&
-        pwswk->wrappedSymKeyLen != 0) {
-        *wswk = *pwswk;
-        rv = PR_TRUE;
-    }
-    if (now) {
-        UnlockSidCacheLock(cache->keyCacheLock);
-    }
-    return rv;
-}
-
-PRBool
-ssl_GetWrappingKey(PRInt32 symWrapMechIndex,
-                   SSL3KEAType exchKeyType,
-                   SSLWrappedSymWrappingKey *wswk)
-{
-    PRBool rv;
-
-    PORT_Assert((unsigned)exchKeyType < kt_kea_size);
-    PORT_Assert((unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS);
-    if ((unsigned)exchKeyType < kt_kea_size &&
-        (unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS) {
-        rv = getSvrWrappingKey(symWrapMechIndex, exchKeyType, wswk,
-                               &globalCache, 0);
-    } else {
-        rv = PR_FALSE;
-    }
-
-    return rv;
-}
-
-/* Wrap and cache a session ticket key. */
-static PRBool
-WrapTicketKey(SECKEYPublicKey *svrPubKey, PK11SymKey *symKey,
-              const char *keyName, encKeyCacheEntry *cacheEntry)
-{
-    SECItem wrappedKey = { siBuffer, NULL, 0 };
-
-    wrappedKey.len = SECKEY_PublicKeyStrength(svrPubKey);
-    PORT_Assert(wrappedKey.len <= sizeof(cacheEntry->bytes));
-    if (wrappedKey.len > sizeof(cacheEntry->bytes))
-        return PR_FALSE;
-    wrappedKey.data = cacheEntry->bytes;
-
-    if (PK11_PubWrapSymKey(CKM_RSA_PKCS, svrPubKey, symKey, &wrappedKey) !=
-        SECSuccess) {
-        SSL_DBG(("%d: SSL[%s]: Unable to wrap session ticket %s.",
-                 SSL_GETPID(), "unknown", keyName));
-        return PR_FALSE;
-    }
-    cacheEntry->length = wrappedKey.len;
-    return PR_TRUE;
-}
-
-static PRBool
-GenerateTicketKeys(void *pwArg, unsigned char *keyName, PK11SymKey **aesKey,
-                   PK11SymKey **macKey)
-{
-    PK11SlotInfo *slot;
-    CK_MECHANISM_TYPE mechanismArray[2];
-    PK11SymKey *aesKeyTmp = NULL;
-    PK11SymKey *macKeyTmp = NULL;
-    cacheDesc *cache = &globalCache;
-    PRUint8 ticketKeyNameSuffixLocal[SESS_TICKET_KEY_VAR_NAME_LEN];
-    PRUint8 *ticketKeyNameSuffix;
-
-    if (!cache->cacheMem) {
-        /* cache is not initalized. Use stack buffer */
-        ticketKeyNameSuffix = ticketKeyNameSuffixLocal;
-    } else {
-        ticketKeyNameSuffix = cache->ticketKeyNameSuffix;
-    }
-
-    if (PK11_GenerateRandom(ticketKeyNameSuffix,
-                            SESS_TICKET_KEY_VAR_NAME_LEN) !=
-        SECSuccess) {
-        SSL_DBG(("%d: SSL[%s]: Unable to generate random key name bytes.",
-                 SSL_GETPID(), "unknown"));
-        goto loser;
-    }
-
-    mechanismArray[0] = CKM_AES_CBC;
-    mechanismArray[1] = CKM_SHA256_HMAC;
-
-    slot = PK11_GetBestSlotMultiple(mechanismArray, 2, pwArg);
-    if (slot) {
-        aesKeyTmp = PK11_KeyGen(slot, mechanismArray[0], NULL,
-                                AES_256_KEY_LENGTH, pwArg);
-        macKeyTmp = PK11_KeyGen(slot, mechanismArray[1], NULL,
-                                SHA256_LENGTH, pwArg);
-        PK11_FreeSlot(slot);
-    }
-
-    if (aesKeyTmp == NULL || macKeyTmp == NULL) {
-        SSL_DBG(("%d: SSL[%s]: Unable to generate session ticket keys.",
-                 SSL_GETPID(), "unknown"));
-        goto loser;
-    }
-    PORT_Memcpy(keyName, ticketKeyNameSuffix, SESS_TICKET_KEY_VAR_NAME_LEN);
-    *aesKey = aesKeyTmp;
-    *macKey = macKeyTmp;
-    return PR_TRUE;
-
-loser:
-    if (aesKeyTmp)
-        PK11_FreeSymKey(aesKeyTmp);
-    if (macKeyTmp)
-        PK11_FreeSymKey(macKeyTmp);
-    return PR_FALSE;
-}
-
-static PRBool
-GenerateAndWrapTicketKeys(SECKEYPublicKey *svrPubKey, void *pwArg,
-                          unsigned char *keyName, PK11SymKey **aesKey,
-                          PK11SymKey **macKey)
-{
-    PK11SymKey *aesKeyTmp = NULL;
-    PK11SymKey *macKeyTmp = NULL;
-    cacheDesc *cache = &globalCache;
-
-    if (!GenerateTicketKeys(pwArg, keyName, &aesKeyTmp, &macKeyTmp)) {
-        goto loser;
-    }
-
-    if (cache->cacheMem) {
-        /* Export the keys to the shared cache in wrapped form. */
-        if (!WrapTicketKey(svrPubKey, aesKeyTmp, "enc key", cache->ticketEncKey))
-            goto loser;
-        if (!WrapTicketKey(svrPubKey, macKeyTmp, "mac key", cache->ticketMacKey))
-            goto loser;
-    }
-    *aesKey = aesKeyTmp;
-    *macKey = macKeyTmp;
-    return PR_TRUE;
-
-loser:
-    if (aesKeyTmp)
-        PK11_FreeSymKey(aesKeyTmp);
-    if (macKeyTmp)
-        PK11_FreeSymKey(macKeyTmp);
-    return PR_FALSE;
-}
-
-static PRBool
-UnwrapCachedTicketKeys(SECKEYPrivateKey *svrPrivKey, unsigned char *keyName,
-                       PK11SymKey **aesKey, PK11SymKey **macKey)
-{
-    SECItem wrappedKey = { siBuffer, NULL, 0 };
-    PK11SymKey *aesKeyTmp = NULL;
-    PK11SymKey *macKeyTmp = NULL;
-    cacheDesc *cache = &globalCache;
-
-    wrappedKey.data = cache->ticketEncKey->bytes;
-    wrappedKey.len = cache->ticketEncKey->length;
-    PORT_Assert(wrappedKey.len <= sizeof(cache->ticketEncKey->bytes));
-    aesKeyTmp = PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey,
-                                     CKM_AES_CBC, CKA_DECRYPT, 0);
-
-    wrappedKey.data = cache->ticketMacKey->bytes;
-    wrappedKey.len = cache->ticketMacKey->length;
-    PORT_Assert(wrappedKey.len <= sizeof(cache->ticketMacKey->bytes));
-    macKeyTmp = PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey,
-                                     CKM_SHA256_HMAC, CKA_SIGN, 0);
-
-    if (aesKeyTmp == NULL || macKeyTmp == NULL) {
-        SSL_DBG(("%d: SSL[%s]: Unable to unwrap session ticket keys.",
-                 SSL_GETPID(), "unknown"));
-        goto loser;
-    }
-    SSL_DBG(("%d: SSL[%s]: Successfully unwrapped session ticket keys.",
-             SSL_GETPID(), "unknown"));
-
-    PORT_Memcpy(keyName, cache->ticketKeyNameSuffix,
-                SESS_TICKET_KEY_VAR_NAME_LEN);
-    *aesKey = aesKeyTmp;
-    *macKey = macKeyTmp;
-    return PR_TRUE;
-
-loser:
-    if (aesKeyTmp)
-        PK11_FreeSymKey(aesKeyTmp);
-    if (macKeyTmp)
-        PK11_FreeSymKey(macKeyTmp);
-    return PR_FALSE;
-}
-
-PRBool
-ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey *svrPrivKey,
-                               SECKEYPublicKey *svrPubKey, void *pwArg,
-                               unsigned char *keyName, PK11SymKey **aesKey,
-                               PK11SymKey **macKey)
-{
-    PRUint32 now = 0;
-    PRBool rv = PR_FALSE;
-    PRBool keysGenerated = PR_FALSE;
-    cacheDesc *cache = &globalCache;
-
-    if (!cache->cacheMem) {
-        /* cache is uninitialized. Generate keys and return them
-         * without caching. */
-        return GenerateTicketKeys(pwArg, keyName, aesKey, macKey);
-    }
-
-    now = LockSidCacheLock(cache->keyCacheLock, now);
-    if (!now)
-        return rv;
-
-    if (!*(cache->ticketKeysValid)) {
-        /* Keys do not exist, create them. */
-        if (!GenerateAndWrapTicketKeys(svrPubKey, pwArg, keyName,
-                                       aesKey, macKey))
-            goto loser;
-        keysGenerated = PR_TRUE;
-        *(cache->ticketKeysValid) = 1;
-    }
-
-    rv = PR_TRUE;
-
-loser:
-    UnlockSidCacheLock(cache->keyCacheLock);
-    if (rv && !keysGenerated)
-        rv = UnwrapCachedTicketKeys(svrPrivKey, keyName, aesKey, macKey);
-    return rv;
-}
-
-PRBool
-ssl_GetSessionTicketKeys(unsigned char *keyName, unsigned char *encKey,
-                         unsigned char *macKey)
-{
-    PRBool rv = PR_FALSE;
-    PRUint32 now = 0;
-    cacheDesc *cache = &globalCache;
-    PRUint8 ticketMacKey[SHA256_LENGTH], ticketEncKey[AES_256_KEY_LENGTH];
-    PRUint8 ticketKeyNameSuffixLocal[SESS_TICKET_KEY_VAR_NAME_LEN];
-    PRUint8 *ticketMacKeyPtr, *ticketEncKeyPtr, *ticketKeyNameSuffix;
-    PRBool cacheIsEnabled = PR_TRUE;
-
-    if (!cache->cacheMem) { /* cache is uninitialized */
-        cacheIsEnabled = PR_FALSE;
-        ticketKeyNameSuffix = ticketKeyNameSuffixLocal;
-        ticketEncKeyPtr = ticketEncKey;
-        ticketMacKeyPtr = ticketMacKey;
-    } else {
-        /* these values have constant memory locations in the cache.
-         * Ok to reference them without holding the lock. */
-        ticketKeyNameSuffix = cache->ticketKeyNameSuffix;
-        ticketEncKeyPtr = cache->ticketEncKey->bytes;
-        ticketMacKeyPtr = cache->ticketMacKey->bytes;
-    }
-
-    if (cacheIsEnabled) {
-        /* Grab lock if initialized. */
-        now = LockSidCacheLock(cache->keyCacheLock, now);
-        if (!now)
-            return rv;
-    }
-    /* Going to regenerate keys on every call if cache was not
-     * initialized. */
-    if (!cacheIsEnabled || !*(cache->ticketKeysValid)) {
-        if (PK11_GenerateRandom(ticketKeyNameSuffix,
-                                SESS_TICKET_KEY_VAR_NAME_LEN) !=
-            SECSuccess)
-            goto loser;
-        if (PK11_GenerateRandom(ticketEncKeyPtr,
-                                AES_256_KEY_LENGTH) != SECSuccess)
-            goto loser;
-        if (PK11_GenerateRandom(ticketMacKeyPtr,
-                                SHA256_LENGTH) != SECSuccess)
-            goto loser;
-        if (cacheIsEnabled) {
-            *(cache->ticketKeysValid) = 1;
-        }
-    }
-
-    rv = PR_TRUE;
-
-loser:
-    if (cacheIsEnabled) {
-        UnlockSidCacheLock(cache->keyCacheLock);
-    }
-    if (rv) {
-        PORT_Memcpy(keyName, ticketKeyNameSuffix,
-                    SESS_TICKET_KEY_VAR_NAME_LEN);
-        PORT_Memcpy(encKey, ticketEncKeyPtr, AES_256_KEY_LENGTH);
-        PORT_Memcpy(macKey, ticketMacKeyPtr, SHA256_LENGTH);
-    }
-    return rv;
-}
-
-/* The caller passes in the new value it wants
- * to set.  This code tests the wrapped sym key entry in the shared memory.
- * If it is uninitialized, this function writes the caller's value into
- * the disk entry, and returns false.
- * Otherwise, it overwrites the caller's wswk with the value obtained from
- * the disk, and returns PR_TRUE.
- * This is all done while holding the locks/mutexes necessary to make
- * the operation atomic.
- */
-PRBool
-ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk)
-{
-    cacheDesc *cache = &globalCache;
-    PRBool rv = PR_FALSE;
-    SSL3KEAType exchKeyType = wswk->exchKeyType;
-    /* type of keys used to wrap SymWrapKey*/
-    PRInt32 symWrapMechIndex = wswk->symWrapMechIndex;
-    PRUint32 ndx;
-    PRUint32 now = 0;
-    SSLWrappedSymWrappingKey myWswk;
-
-    if (!cache->cacheMem) { /* cache is uninitialized */
-        PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);
-        return 0;
-    }
-
-    PORT_Assert((unsigned)exchKeyType < kt_kea_size);
-    if ((unsigned)exchKeyType >= kt_kea_size)
-        return 0;
-
-    PORT_Assert((unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS);
-    if ((unsigned)symWrapMechIndex >= SSL_NUM_WRAP_MECHS)
-        return 0;
-
-    ndx = (exchKeyType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex;
-    PORT_Memset(&myWswk, 0, sizeof myWswk); /* eliminate UMRs. */
-
-    now = LockSidCacheLock(cache->keyCacheLock, now);
-    if (now) {
-        rv = getSvrWrappingKey(wswk->symWrapMechIndex, wswk->exchKeyType,
-                               &myWswk, cache, now);
-        if (rv) {
-            /* we found it on disk, copy it out to the caller. */
-            PORT_Memcpy(wswk, &myWswk, sizeof *wswk);
-        } else {
-            /* Wasn't on disk, and we're still holding the lock, so write it. */
-            cache->keyCacheData[ndx] = *wswk;
-        }
-        UnlockSidCacheLock(cache->keyCacheLock);
-    }
-    return rv;
-}
-
-#else /* MAC version or other platform */
-
-#include "seccomon.h"
-#include "cert.h"
-#include "ssl.h"
-#include "sslimpl.h"
-
-SECStatus
-SSL_ConfigServerSessionIDCache(int maxCacheEntries,
-                               PRUint32 ssl2_timeout,
-                               PRUint32 ssl3_timeout,
-                               const char *directory)
-{
-    PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigServerSessionIDCache)");
-    return SECFailure;
-}
-
-SECStatus
-SSL_ConfigMPServerSIDCache(int maxCacheEntries,
-                           PRUint32 ssl2_timeout,
-                           PRUint32 ssl3_timeout,
-                           const char *directory)
-{
-    PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigMPServerSIDCache)");
-    return SECFailure;
-}
-
-SECStatus
-SSL_InheritMPServerSIDCache(const char *envString)
-{
-    PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_InheritMPServerSIDCache)");
-    return SECFailure;
-}
-
-PRBool
-ssl_GetWrappingKey(PRInt32 symWrapMechIndex,
-                   SSL3KEAType exchKeyType,
-                   SSLWrappedSymWrappingKey *wswk)
-{
-    PRBool rv = PR_FALSE;
-    PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_GetWrappingKey)");
-    return rv;
-}
-
-/* This is a kind of test-and-set.  The caller passes in the new value it wants
- * to set.  This code tests the wrapped sym key entry in the shared memory.
- * If it is uninitialized, this function writes the caller's value into
- * the disk entry, and returns false.
- * Otherwise, it overwrites the caller's wswk with the value obtained from
- * the disk, and returns PR_TRUE.
- * This is all done while holding the locks/mutexes necessary to make
- * the operation atomic.
- */
-PRBool
-ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk)
-{
-    PRBool rv = PR_FALSE;
-    PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_SetWrappingKey)");
-    return rv;
-}
-
-PRUint32
-SSL_GetMaxServerCacheLocks(void)
-{
-    PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_GetMaxServerCacheLocks)");
-    return -1;
-}
-
-SECStatus
-SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)
-{
-    PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_SetMaxServerCacheLocks)");
-    return SECFailure;
-}
-
-#endif /* XP_UNIX || XP_WIN32 */
diff --git a/net/third_party/nss/ssl/sslsock.c b/net/third_party/nss/ssl/sslsock.c
deleted file mode 100644
index e82c916..0000000
--- a/net/third_party/nss/ssl/sslsock.c
+++ /dev/null
@@ -1,3715 +0,0 @@
-/*
- * vtables (and methods that call through them) for the 4 types of
- * SSLSockets supported.  Only one type is still supported.
- * Various other functions.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "seccomon.h"
-#include "cert.h"
-#include "keyhi.h"
-#include "ssl.h"
-#include "sslimpl.h"
-#include "sslproto.h"
-#include "nspr.h"
-#include "private/pprio.h"
-#ifndef NO_PKCS11_BYPASS
-#include "blapi.h"
-#endif
-#include "nss.h"
-#include "pk11pqg.h"
-
-#define SET_ERROR_CODE /* reminder */
-
-static const sslSocketOps ssl_default_ops = { /* No SSL. */
-                                              ssl_DefConnect,
-                                              NULL,
-                                              ssl_DefBind,
-                                              ssl_DefListen,
-                                              ssl_DefShutdown,
-                                              ssl_DefClose,
-                                              ssl_DefRecv,
-                                              ssl_DefSend,
-                                              ssl_DefRead,
-                                              ssl_DefWrite,
-                                              ssl_DefGetpeername,
-                                              ssl_DefGetsockname
-};
-
-static const sslSocketOps ssl_secure_ops = { /* SSL. */
-                                             ssl_SecureConnect,
-                                             NULL,
-                                             ssl_DefBind,
-                                             ssl_DefListen,
-                                             ssl_SecureShutdown,
-                                             ssl_SecureClose,
-                                             ssl_SecureRecv,
-                                             ssl_SecureSend,
-                                             ssl_SecureRead,
-                                             ssl_SecureWrite,
-                                             ssl_DefGetpeername,
-                                             ssl_DefGetsockname
-};
-
-/*
-** default settings for socket enables
-*/
-static sslOptions ssl_defaults = {
-    { siBuffer, NULL, 0 }, /* nextProtoNego */
-    PR_TRUE,               /* useSecurity        */
-    PR_FALSE,              /* useSocks           */
-    PR_FALSE,              /* requestCertificate */
-    2,                     /* requireCertificate */
-    PR_FALSE,              /* handshakeAsClient  */
-    PR_FALSE,              /* handshakeAsServer  */
-    PR_FALSE,
-    /* enableSSL2         */ /* now defaults to off in NSS 3.13 */
-    PR_FALSE,                /* unusedBit9         */
-    PR_FALSE,                /* unusedBit10        */
-    PR_FALSE,                /* noCache            */
-    PR_FALSE,                /* fdx                */
-    PR_FALSE,
-    /* v2CompatibleHello  */ /* now defaults to off in NSS 3.13 */
-    PR_TRUE,                 /* detectRollBack     */
-    PR_FALSE,                /* noStepDown         */
-    PR_FALSE,                /* bypassPKCS11       */
-    PR_FALSE,                /* noLocks            */
-    PR_FALSE,                /* enableSessionTickets */
-    PR_FALSE,                /* enableDeflate      */
-    2,                       /* enableRenegotiation (default: requires extension) */
-    PR_FALSE,                /* requireSafeNegotiation */
-    PR_FALSE,                /* enableFalseStart   */
-    PR_TRUE,                 /* cbcRandomIV        */
-    PR_FALSE,                /* enableOCSPStapling */
-    PR_TRUE,                 /* enableNPN          */
-    PR_FALSE,                /* enableALPN         */
-    PR_TRUE,                 /* reuseServerECDHEKey */
-    PR_FALSE,                /* enableFallbackSCSV */
-    PR_TRUE,                 /* enableServerDhe */
-    PR_FALSE,                /* enableExtendedMS    */
-    PR_FALSE,                /* enableSignedCertTimestamps */
-};
-
-/*
- * default range of enabled SSL/TLS protocols
- */
-static SSLVersionRange versions_defaults_stream = {
-    SSL_LIBRARY_VERSION_TLS_1_0,
-    SSL_LIBRARY_VERSION_TLS_1_2
-};
-
-static SSLVersionRange versions_defaults_datagram = {
-    SSL_LIBRARY_VERSION_TLS_1_1,
-    SSL_LIBRARY_VERSION_TLS_1_2
-};
-
-#define VERSIONS_DEFAULTS(variant)                               \
-    (variant == ssl_variant_stream ? &versions_defaults_stream : \
-                                   &versions_defaults_datagram)
-#define VERSIONS_POLICY_MIN(variant)                              \
-    (variant == ssl_variant_stream ? NSS_TLS_VERSION_MIN_POLICY : \
-                                   NSS_DTLS_VERSION_MIN_POLICY)
-#define VERSIONS_POLICY_MAX(variant)                              \
-    (variant == ssl_variant_stream ? NSS_TLS_VERSION_MAX_POLICY : \
-                                   NSS_DTLS_VERSION_MAX_POLICY)
-
-sslSessionIDLookupFunc ssl_sid_lookup;
-sslSessionIDCacheFunc ssl_sid_cache;
-sslSessionIDUncacheFunc ssl_sid_uncache;
-
-static PRBool ssl_inited = PR_FALSE;
-static PRDescIdentity ssl_layer_id;
-
-PRBool locksEverDisabled; /* implicitly PR_FALSE */
-PRBool ssl_force_locks;   /* implicitly PR_FALSE */
-int ssl_lock_readers = 1; /* default true. */
-char ssl_debug;
-char ssl_trace;
-FILE *ssl_trace_iob;
-FILE *ssl_keylog_iob;
-char lockStatus[] = "Locks are ENABLED.  ";
-#define LOCKSTATUS_OFFSET 10 /* offset of ENABLED */
-
-/* SRTP_NULL_HMAC_SHA1_80 and SRTP_NULL_HMAC_SHA1_32 are not implemented. */
-static const PRUint16 srtpCiphers[] = {
-    SRTP_AES128_CM_HMAC_SHA1_80,
-    SRTP_AES128_CM_HMAC_SHA1_32,
-    0
-};
-
-/* forward declarations. */
-static sslSocket *ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant variant);
-static SECStatus ssl_MakeLocks(sslSocket *ss);
-static void ssl_SetDefaultsFromEnvironment(void);
-static PRStatus ssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack,
-                                PRDescIdentity id);
-
-/************************************************************************/
-
-/*
-** Lookup a socket structure from a file descriptor.
-** Only functions called through the PRIOMethods table should use this.
-** Other app-callable functions should use ssl_FindSocket.
-*/
-static sslSocket *
-ssl_GetPrivate(PRFileDesc *fd)
-{
-    sslSocket *ss;
-
-    PORT_Assert(fd != NULL);
-    PORT_Assert(fd->methods->file_type == PR_DESC_LAYERED);
-    PORT_Assert(fd->identity == ssl_layer_id);
-
-    if (fd->methods->file_type != PR_DESC_LAYERED ||
-        fd->identity != ssl_layer_id) {
-        PORT_SetError(PR_BAD_DESCRIPTOR_ERROR);
-        return NULL;
-    }
-
-    ss = (sslSocket *)fd->secret;
-    /* Set ss->fd lazily. We can't rely on the value of ss->fd set by
-     * ssl_PushIOLayer because another PR_PushIOLayer call will switch the
-     * contents of the PRFileDesc pointed by ss->fd and the new layer.
-     * See bug 807250.
-     */
-    ss->fd = fd;
-    return ss;
-}
-
-/* This function tries to find the SSL layer in the stack.
- * It searches for the first SSL layer at or below the argument fd,
- * and failing that, it searches for the nearest SSL layer above the
- * argument fd.  It returns the private sslSocket from the found layer.
- */
-sslSocket *
-ssl_FindSocket(PRFileDesc *fd)
-{
-    PRFileDesc *layer;
-    sslSocket *ss;
-
-    PORT_Assert(fd != NULL);
-    PORT_Assert(ssl_layer_id != 0);
-
-    layer = PR_GetIdentitiesLayer(fd, ssl_layer_id);
-    if (layer == NULL) {
-        PORT_SetError(PR_BAD_DESCRIPTOR_ERROR);
-        return NULL;
-    }
-
-    ss = (sslSocket *)layer->secret;
-    /* Set ss->fd lazily. We can't rely on the value of ss->fd set by
-     * ssl_PushIOLayer because another PR_PushIOLayer call will switch the
-     * contents of the PRFileDesc pointed by ss->fd and the new layer.
-     * See bug 807250.
-     */
-    ss->fd = layer;
-    return ss;
-}
-
-static sslSocket *
-ssl_DupSocket(sslSocket *os)
-{
-    sslSocket *ss;
-    SECStatus rv;
-
-    ss = ssl_NewSocket((PRBool)(!os->opt.noLocks), os->protocolVariant);
-    if (ss) {
-        ss->opt = os->opt;
-        ss->opt.useSocks = PR_FALSE;
-        ss->vrange = os->vrange;
-
-        ss->peerID = !os->peerID ? NULL : PORT_Strdup(os->peerID);
-        ss->url = !os->url ? NULL : PORT_Strdup(os->url);
-
-        ss->ops = os->ops;
-        ss->rTimeout = os->rTimeout;
-        ss->wTimeout = os->wTimeout;
-        ss->cTimeout = os->cTimeout;
-        ss->dbHandle = os->dbHandle;
-
-        /* copy ssl2&3 policy & prefs, even if it's not selected (yet) */
-        ss->allowedByPolicy = os->allowedByPolicy;
-        ss->maybeAllowedByPolicy = os->maybeAllowedByPolicy;
-        ss->chosenPreference = os->chosenPreference;
-        PORT_Memcpy(ss->cipherSuites, os->cipherSuites, sizeof os->cipherSuites);
-        PORT_Memcpy(ss->ssl3.dtlsSRTPCiphers, os->ssl3.dtlsSRTPCiphers,
-                    sizeof(PRUint16) * os->ssl3.dtlsSRTPCipherCount);
-        ss->ssl3.dtlsSRTPCipherCount = os->ssl3.dtlsSRTPCipherCount;
-        PORT_Memcpy(ss->ssl3.signatureAlgorithms, os->ssl3.signatureAlgorithms,
-                    sizeof(ss->ssl3.signatureAlgorithms[0]) *
-                        os->ssl3.signatureAlgorithmCount);
-        ss->ssl3.signatureAlgorithmCount = os->ssl3.signatureAlgorithmCount;
-        ss->ssl3.downgradeCheckVersion = os->ssl3.downgradeCheckVersion;
-
-        ss->ssl3.dheWeakGroupEnabled = os->ssl3.dheWeakGroupEnabled;
-        ss->ssl3.numDHEGroups = os->ssl3.numDHEGroups;
-        if (os->ssl3.dheGroups) {
-            ss->ssl3.dheGroups = PORT_NewArray(SSLDHEGroupType,
-                                               os->ssl3.numDHEGroups);
-            if (!ss->ssl3.dheGroups) {
-                goto loser;
-            }
-            PORT_Memcpy(ss->ssl3.dheGroups, os->ssl3.dheGroups,
-                        sizeof(SSLDHEGroupType) * os->ssl3.numDHEGroups);
-        } else {
-            ss->ssl3.dheGroups = NULL;
-        }
-
-        if (os->cipherSpecs) {
-            ss->cipherSpecs = (unsigned char *)PORT_Alloc(os->sizeCipherSpecs);
-            if (ss->cipherSpecs)
-                PORT_Memcpy(ss->cipherSpecs, os->cipherSpecs,
-                            os->sizeCipherSpecs);
-            ss->sizeCipherSpecs = os->sizeCipherSpecs;
-            ss->preferredCipher = os->preferredCipher;
-        } else {
-            ss->cipherSpecs = NULL; /* produced lazily */
-            ss->sizeCipherSpecs = 0;
-            ss->preferredCipher = NULL;
-        }
-        if (ss->opt.useSecurity) {
-            /* This int should be SSLKEAType, but CC on Irix complains,
-             * during the for loop.
-             */
-            int i;
-            sslServerCerts *oc = os->serverCerts;
-            sslServerCerts *sc = ss->serverCerts;
-
-            for (i = kt_null; i < kt_kea_size; i++, oc++, sc++) {
-                if (oc->serverCert && oc->serverCertChain) {
-                    sc->serverCert = CERT_DupCertificate(oc->serverCert);
-                    sc->serverCertChain = CERT_DupCertList(oc->serverCertChain);
-                    if (!sc->serverCertChain)
-                        goto loser;
-                } else {
-                    sc->serverCert = NULL;
-                    sc->serverCertChain = NULL;
-                }
-                sc->serverKeyPair = oc->serverKeyPair ? ssl3_GetKeyPairRef(oc->serverKeyPair)
-                                                      : NULL;
-                if (oc->serverKeyPair && !sc->serverKeyPair)
-                    goto loser;
-                sc->serverKeyBits = oc->serverKeyBits;
-                ss->certStatusArray[i] = !os->certStatusArray[i] ? NULL : SECITEM_DupArray(NULL, os->certStatusArray[i]);
-            }
-            ss->stepDownKeyPair = !os->stepDownKeyPair ? NULL : ssl3_GetKeyPairRef(os->stepDownKeyPair);
-            ss->ephemeralECDHKeyPair = !os->ephemeralECDHKeyPair ? NULL : ssl3_GetKeyPairRef(os->ephemeralECDHKeyPair);
-            ss->dheKeyPair = !os->dheKeyPair ? NULL : ssl3_GetKeyPairRef(os->dheKeyPair);
-            ss->dheParams = os->dheParams;
-
-            /*
-             * XXX the preceding CERT_ and SECKEY_ functions can fail and return NULL.
-             * XXX We should detect this, and not just march on with NULL pointers.
-             */
-            ss->authCertificate = os->authCertificate;
-            ss->authCertificateArg = os->authCertificateArg;
-            ss->getClientAuthData = os->getClientAuthData;
-            ss->getClientAuthDataArg = os->getClientAuthDataArg;
-            ss->sniSocketConfig = os->sniSocketConfig;
-            ss->sniSocketConfigArg = os->sniSocketConfigArg;
-            ss->handleBadCert = os->handleBadCert;
-            ss->badCertArg = os->badCertArg;
-            ss->handshakeCallback = os->handshakeCallback;
-            ss->handshakeCallbackData = os->handshakeCallbackData;
-            ss->canFalseStartCallback = os->canFalseStartCallback;
-            ss->canFalseStartCallbackData = os->canFalseStartCallbackData;
-            ss->pkcs11PinArg = os->pkcs11PinArg;
-            ss->getChannelID = os->getChannelID;
-            ss->getChannelIDArg = os->getChannelIDArg;
-
-            /* Create security data */
-            rv = ssl_CopySecurityInfo(ss, os);
-            if (rv != SECSuccess) {
-                goto loser;
-            }
-        }
-    }
-    return ss;
-
-loser:
-    ssl_FreeSocket(ss);
-    return NULL;
-}
-
-static void
-ssl_DestroyLocks(sslSocket *ss)
-{
-    /* Destroy locks. */
-    if (ss->firstHandshakeLock) {
-        PZ_DestroyMonitor(ss->firstHandshakeLock);
-        ss->firstHandshakeLock = NULL;
-    }
-    if (ss->ssl3HandshakeLock) {
-        PZ_DestroyMonitor(ss->ssl3HandshakeLock);
-        ss->ssl3HandshakeLock = NULL;
-    }
-    if (ss->specLock) {
-        NSSRWLock_Destroy(ss->specLock);
-        ss->specLock = NULL;
-    }
-
-    if (ss->recvLock) {
-        PZ_DestroyLock(ss->recvLock);
-        ss->recvLock = NULL;
-    }
-    if (ss->sendLock) {
-        PZ_DestroyLock(ss->sendLock);
-        ss->sendLock = NULL;
-    }
-    if (ss->xmitBufLock) {
-        PZ_DestroyMonitor(ss->xmitBufLock);
-        ss->xmitBufLock = NULL;
-    }
-    if (ss->recvBufLock) {
-        PZ_DestroyMonitor(ss->recvBufLock);
-        ss->recvBufLock = NULL;
-    }
-}
-
-/* Caller holds any relevant locks */
-static void
-ssl_DestroySocketContents(sslSocket *ss)
-{
-    /* "i" should be of type SSLKEAType, but CC on IRIX complains during
-     * the for loop.
-     */
-    int i;
-
-    /* Free up socket */
-    ssl_DestroySecurityInfo(&ss->sec);
-
-    ssl3_DestroySSL3Info(ss);
-
-    PORT_Free(ss->saveBuf.buf);
-    PORT_Free(ss->pendingBuf.buf);
-    ssl_DestroyGather(&ss->gs);
-
-    if (ss->peerID != NULL)
-        PORT_Free(ss->peerID);
-    if (ss->url != NULL)
-        PORT_Free((void *)ss->url); /* CONST */
-    if (ss->cipherSpecs) {
-        PORT_Free(ss->cipherSpecs);
-        ss->cipherSpecs = NULL;
-        ss->sizeCipherSpecs = 0;
-    }
-
-    /* Clean up server configuration */
-    for (i = kt_null; i < kt_kea_size; i++) {
-        sslServerCerts *sc = ss->serverCerts + i;
-        if (sc->serverCert != NULL)
-            CERT_DestroyCertificate(sc->serverCert);
-        if (sc->serverCertChain != NULL)
-            CERT_DestroyCertificateList(sc->serverCertChain);
-        if (sc->serverKeyPair != NULL)
-            ssl3_FreeKeyPair(sc->serverKeyPair);
-        if (ss->certStatusArray[i] != NULL) {
-            SECITEM_FreeArray(ss->certStatusArray[i], PR_TRUE);
-            ss->certStatusArray[i] = NULL;
-        }
-        if (ss->signedCertTimestamps[i].data) {
-            SECITEM_FreeItem(&ss->signedCertTimestamps[i], PR_FALSE);
-        }
-    }
-    if (ss->stepDownKeyPair) {
-        ssl3_FreeKeyPair(ss->stepDownKeyPair);
-        ss->stepDownKeyPair = NULL;
-    }
-    if (ss->ephemeralECDHKeyPair) {
-        ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair);
-        ss->ephemeralECDHKeyPair = NULL;
-    }
-    if (ss->dheKeyPair) {
-        ssl3_FreeKeyPair(ss->dheKeyPair);
-        ss->dheKeyPair = NULL;
-    }
-    SECITEM_FreeItem(&ss->opt.nextProtoNego, PR_FALSE);
-    if (ss->xtnData.sniNameArr) {
-        PORT_Free(ss->xtnData.sniNameArr);
-        ss->xtnData.sniNameArr = NULL;
-    }
-}
-
-/*
- * free an sslSocket struct, and all the stuff that hangs off of it
- */
-void
-ssl_FreeSocket(sslSocket *ss)
-{
-    /* Get every lock you can imagine!
-    ** Caller already holds these:
-    **  SSL_LOCK_READER(ss);
-    **  SSL_LOCK_WRITER(ss);
-    */
-    ssl_Get1stHandshakeLock(ss);
-    ssl_GetRecvBufLock(ss);
-    ssl_GetSSL3HandshakeLock(ss);
-    ssl_GetXmitBufLock(ss);
-    ssl_GetSpecWriteLock(ss);
-
-    ssl_DestroySocketContents(ss);
-
-    /* Release all the locks acquired above.  */
-    SSL_UNLOCK_READER(ss);
-    SSL_UNLOCK_WRITER(ss);
-    ssl_Release1stHandshakeLock(ss);
-    ssl_ReleaseRecvBufLock(ss);
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    ssl_ReleaseXmitBufLock(ss);
-    ssl_ReleaseSpecWriteLock(ss);
-
-    ssl_DestroyLocks(ss);
-
-#ifdef DEBUG
-    PORT_Memset(ss, 0x1f, sizeof *ss);
-#endif
-    PORT_Free(ss);
-    return;
-}
-
-/************************************************************************/
-SECStatus
-ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled)
-{
-    PRFileDesc *osfd = ss->fd->lower;
-    SECStatus rv = SECFailure;
-    PRSocketOptionData opt;
-
-    opt.option = PR_SockOpt_NoDelay;
-    opt.value.no_delay = (PRBool)!enabled;
-
-    if (osfd->methods->setsocketoption) {
-        rv = (SECStatus)osfd->methods->setsocketoption(osfd, &opt);
-    } else {
-        PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
-    }
-
-    return rv;
-}
-
-static void
-ssl_ChooseOps(sslSocket *ss)
-{
-    ss->ops = ss->opt.useSecurity ? &ssl_secure_ops : &ssl_default_ops;
-}
-
-/* Called from SSL_Enable (immediately below) */
-static SECStatus
-PrepareSocket(sslSocket *ss)
-{
-    SECStatus rv = SECSuccess;
-
-    ssl_ChooseOps(ss);
-    return rv;
-}
-
-SECStatus
-SSL_Enable(PRFileDesc *fd, int which, PRBool on)
-{
-    return SSL_OptionSet(fd, which, on);
-}
-
-#ifndef NO_PKCS11_BYPASS
-static const PRCallOnceType pristineCallOnce;
-static PRCallOnceType setupBypassOnce;
-
-static SECStatus
-SSL_BypassShutdown(void *appData, void *nssData)
-{
-    /* unload freeBL shared library from memory */
-    BL_Unload();
-    setupBypassOnce = pristineCallOnce;
-    return SECSuccess;
-}
-
-static PRStatus
-SSL_BypassRegisterShutdown(void)
-{
-    SECStatus rv = NSS_RegisterShutdown(SSL_BypassShutdown, NULL);
-    PORT_Assert(SECSuccess == rv);
-    return SECSuccess == rv ? PR_SUCCESS : PR_FAILURE;
-}
-#endif
-
-static PRStatus
-SSL_BypassSetup(void)
-{
-#ifdef NO_PKCS11_BYPASS
-    /* Guarantee binary compatibility */
-    return PR_SUCCESS;
-#else
-    return PR_CallOnce(&setupBypassOnce, &SSL_BypassRegisterShutdown);
-#endif
-}
-
-static PRBool ssl_VersionIsSupportedByPolicy(
-    SSLProtocolVariant protocolVariant, SSL3ProtocolVersion version);
-
-/* Implements the semantics for SSL_OptionSet(SSL_ENABLE_TLS, on) described in
- * ssl.h in the section "SSL version range setting API".
- */
-static void
-ssl_EnableTLS(SSLVersionRange *vrange, PRBool on)
-{
-    if (on) {
-        /* don't turn it on if tls1.0 disallowed by by policy */
-        if (!ssl_VersionIsSupportedByPolicy(ssl_variant_stream,
-                                            SSL_LIBRARY_VERSION_TLS_1_0)) {
-            return;
-        }
-    }
-    if (SSL3_ALL_VERSIONS_DISABLED(vrange)) {
-        if (on) {
-            vrange->min = SSL_LIBRARY_VERSION_TLS_1_0;
-            vrange->max = SSL_LIBRARY_VERSION_TLS_1_0;
-        } /* else don't change anything */
-        return;
-    }
-
-    if (on) {
-        /* Expand the range of enabled version to include TLS 1.0 */
-        vrange->min = PR_MIN(vrange->min, SSL_LIBRARY_VERSION_TLS_1_0);
-        vrange->max = PR_MAX(vrange->max, SSL_LIBRARY_VERSION_TLS_1_0);
-    } else {
-        /* Disable all TLS versions, leaving only SSL 3.0 if it was enabled */
-        if (vrange->min == SSL_LIBRARY_VERSION_3_0) {
-            vrange->max = SSL_LIBRARY_VERSION_3_0;
-        } else {
-            /* Only TLS was enabled, so now no versions are. */
-            vrange->min = SSL_LIBRARY_VERSION_NONE;
-            vrange->max = SSL_LIBRARY_VERSION_NONE;
-        }
-    }
-}
-
-/* Implements the semantics for SSL_OptionSet(SSL_ENABLE_SSL3, on) described in
- * ssl.h in the section "SSL version range setting API".
- */
-static void
-ssl_EnableSSL3(SSLVersionRange *vrange, PRBool on)
-{
-    if (on) {
-        /* don't turn it on if ssl3 disallowed by by policy */
-        if (!ssl_VersionIsSupportedByPolicy(ssl_variant_stream,
-                                            SSL_LIBRARY_VERSION_3_0)) {
-            return;
-        }
-    }
-    if (SSL3_ALL_VERSIONS_DISABLED(vrange)) {
-        if (on) {
-            vrange->min = SSL_LIBRARY_VERSION_3_0;
-            vrange->max = SSL_LIBRARY_VERSION_3_0;
-        } /* else don't change anything */
-        return;
-    }
-
-    if (on) {
-        /* Expand the range of enabled versions to include SSL 3.0. We know
-         * SSL 3.0 or some version of TLS is already enabled at this point, so
-         * we don't need to change vrange->max.
-         */
-        vrange->min = SSL_LIBRARY_VERSION_3_0;
-    } else {
-        /* Disable SSL 3.0, leaving TLS unaffected. */
-        if (vrange->max > SSL_LIBRARY_VERSION_3_0) {
-            vrange->min = PR_MAX(vrange->min, SSL_LIBRARY_VERSION_TLS_1_0);
-        } else {
-            /* Only SSL 3.0 was enabled, so now no versions are. */
-            vrange->min = SSL_LIBRARY_VERSION_NONE;
-            vrange->max = SSL_LIBRARY_VERSION_NONE;
-        }
-    }
-}
-
-SECStatus
-SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-    SECStatus rv = SECSuccess;
-    PRBool holdingLocks;
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in Enable", SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    holdingLocks = (!ss->opt.noLocks);
-    ssl_Get1stHandshakeLock(ss);
-    ssl_GetSSL3HandshakeLock(ss);
-
-    switch (which) {
-        case SSL_SOCKS:
-            ss->opt.useSocks = PR_FALSE;
-            rv = PrepareSocket(ss);
-            if (on) {
-                PORT_SetError(SEC_ERROR_INVALID_ARGS);
-                rv = SECFailure;
-            }
-            break;
-
-        case SSL_SECURITY:
-            ss->opt.useSecurity = on;
-            rv = PrepareSocket(ss);
-            break;
-
-        case SSL_REQUEST_CERTIFICATE:
-            ss->opt.requestCertificate = on;
-            break;
-
-        case SSL_REQUIRE_CERTIFICATE:
-            ss->opt.requireCertificate = on;
-            break;
-
-        case SSL_HANDSHAKE_AS_CLIENT:
-            if (ss->opt.handshakeAsServer && on) {
-                PORT_SetError(SEC_ERROR_INVALID_ARGS);
-                rv = SECFailure;
-                break;
-            }
-            ss->opt.handshakeAsClient = on;
-            break;
-
-        case SSL_HANDSHAKE_AS_SERVER:
-            if (ss->opt.handshakeAsClient && on) {
-                PORT_SetError(SEC_ERROR_INVALID_ARGS);
-                rv = SECFailure;
-                break;
-            }
-            ss->opt.handshakeAsServer = on;
-            break;
-
-        case SSL_ENABLE_TLS:
-            if (IS_DTLS(ss)) {
-                if (on) {
-                    PORT_SetError(SEC_ERROR_INVALID_ARGS);
-                    rv = SECFailure; /* not allowed */
-                }
-                break;
-            }
-            ssl_EnableTLS(&ss->vrange, on);
-            ss->preferredCipher = NULL;
-            if (ss->cipherSpecs) {
-                PORT_Free(ss->cipherSpecs);
-                ss->cipherSpecs = NULL;
-                ss->sizeCipherSpecs = 0;
-            }
-            break;
-
-        case SSL_ENABLE_SSL3:
-            if (IS_DTLS(ss)) {
-                if (on) {
-                    PORT_SetError(SEC_ERROR_INVALID_ARGS);
-                    rv = SECFailure; /* not allowed */
-                }
-                break;
-            }
-            ssl_EnableSSL3(&ss->vrange, on);
-            ss->preferredCipher = NULL;
-            if (ss->cipherSpecs) {
-                PORT_Free(ss->cipherSpecs);
-                ss->cipherSpecs = NULL;
-                ss->sizeCipherSpecs = 0;
-            }
-            break;
-
-        case SSL_ENABLE_SSL2:
-            if (IS_DTLS(ss)) {
-                if (on) {
-                    PORT_SetError(SEC_ERROR_INVALID_ARGS);
-                    rv = SECFailure; /* not allowed */
-                }
-                break;
-            }
-            if (on) {
-                /* don't turn it on if ssl2 disallowed by by policy */
-                if (!ssl_VersionIsSupportedByPolicy(ssl_variant_stream,
-                                                    SSL_LIBRARY_VERSION_2)) {
-                    break;
-                }
-            }
-            ss->opt.enableSSL2 = on;
-            if (on) {
-                ss->opt.v2CompatibleHello = on;
-            }
-            ss->preferredCipher = NULL;
-            if (ss->cipherSpecs) {
-                PORT_Free(ss->cipherSpecs);
-                ss->cipherSpecs = NULL;
-                ss->sizeCipherSpecs = 0;
-            }
-            break;
-
-        case SSL_NO_CACHE:
-            ss->opt.noCache = on;
-            break;
-
-        case SSL_ENABLE_FDX:
-            if (on && ss->opt.noLocks) {
-                PORT_SetError(SEC_ERROR_INVALID_ARGS);
-                rv = SECFailure;
-            }
-            ss->opt.fdx = on;
-            break;
-
-        case SSL_V2_COMPATIBLE_HELLO:
-            if (IS_DTLS(ss)) {
-                if (on) {
-                    PORT_SetError(SEC_ERROR_INVALID_ARGS);
-                    rv = SECFailure; /* not allowed */
-                }
-                break;
-            }
-            ss->opt.v2CompatibleHello = on;
-            if (!on) {
-                ss->opt.enableSSL2 = on;
-            }
-            break;
-
-        case SSL_ROLLBACK_DETECTION:
-            ss->opt.detectRollBack = on;
-            break;
-
-        case SSL_NO_STEP_DOWN:
-            ss->opt.noStepDown = on;
-            if (on)
-                SSL_DisableExportCipherSuites(fd);
-            break;
-
-        case SSL_BYPASS_PKCS11:
-            if (ss->handshakeBegun) {
-                PORT_SetError(PR_INVALID_STATE_ERROR);
-                rv = SECFailure;
-            } else {
-                if (PR_FALSE != on) {
-                    if (PR_SUCCESS == SSL_BypassSetup()) {
-#ifdef NO_PKCS11_BYPASS
-                        ss->opt.bypassPKCS11 = PR_FALSE;
-#else
-                        ss->opt.bypassPKCS11 = on;
-#endif
-                    } else {
-                        rv = SECFailure;
-                    }
-                } else {
-                    ss->opt.bypassPKCS11 = PR_FALSE;
-                }
-            }
-            break;
-
-        case SSL_NO_LOCKS:
-            if (on && ss->opt.fdx) {
-                PORT_SetError(SEC_ERROR_INVALID_ARGS);
-                rv = SECFailure;
-            }
-            if (on && ssl_force_locks)
-                on = PR_FALSE; /* silent override */
-            ss->opt.noLocks = on;
-            if (on) {
-                locksEverDisabled = PR_TRUE;
-                strcpy(lockStatus + LOCKSTATUS_OFFSET, "DISABLED.");
-            } else if (!holdingLocks) {
-                rv = ssl_MakeLocks(ss);
-                if (rv != SECSuccess) {
-                    ss->opt.noLocks = PR_TRUE;
-                }
-            }
-            break;
-
-        case SSL_ENABLE_SESSION_TICKETS:
-            ss->opt.enableSessionTickets = on;
-            break;
-
-        case SSL_ENABLE_DEFLATE:
-            ss->opt.enableDeflate = on;
-            break;
-
-        case SSL_ENABLE_RENEGOTIATION:
-            ss->opt.enableRenegotiation = on;
-            break;
-
-        case SSL_REQUIRE_SAFE_NEGOTIATION:
-            ss->opt.requireSafeNegotiation = on;
-            break;
-
-        case SSL_ENABLE_FALSE_START:
-            ss->opt.enableFalseStart = on;
-            break;
-
-        case SSL_CBC_RANDOM_IV:
-            ss->opt.cbcRandomIV = on;
-            break;
-
-        case SSL_ENABLE_OCSP_STAPLING:
-            ss->opt.enableOCSPStapling = on;
-            break;
-
-        case SSL_ENABLE_NPN:
-            ss->opt.enableNPN = on;
-            break;
-
-        case SSL_ENABLE_ALPN:
-            ss->opt.enableALPN = on;
-            break;
-
-        case SSL_REUSE_SERVER_ECDHE_KEY:
-            ss->opt.reuseServerECDHEKey = on;
-            break;
-
-        case SSL_ENABLE_FALLBACK_SCSV:
-            ss->opt.enableFallbackSCSV = on;
-            break;
-
-        case SSL_ENABLE_SERVER_DHE:
-            ss->opt.enableServerDhe = on;
-            break;
-
-        case SSL_ENABLE_EXTENDED_MASTER_SECRET:
-            ss->opt.enableExtendedMS = on;
-            break;
-
-        case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
-            ss->opt.enableSignedCertTimestamps = on;
-            break;
-
-        default:
-            PORT_SetError(SEC_ERROR_INVALID_ARGS);
-            rv = SECFailure;
-    }
-
-    /* We can't use the macros for releasing the locks here,
-     * because ss->opt.noLocks might have changed just above.
-     * We must release these locks (monitors) here, if we aquired them above,
-     * regardless of the current value of ss->opt.noLocks.
-     */
-    if (holdingLocks) {
-        PZ_ExitMonitor((ss)->ssl3HandshakeLock);
-        PZ_ExitMonitor((ss)->firstHandshakeLock);
-    }
-
-    return rv;
-}
-
-SECStatus
-SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-    SECStatus rv = SECSuccess;
-    PRBool on = PR_FALSE;
-
-    if (!pOn) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in Enable", SSL_GETPID(), fd));
-        *pOn = PR_FALSE;
-        return SECFailure;
-    }
-
-    ssl_Get1stHandshakeLock(ss);
-    ssl_GetSSL3HandshakeLock(ss);
-
-    switch (which) {
-        case SSL_SOCKS:
-            on = PR_FALSE;
-            break;
-        case SSL_SECURITY:
-            on = ss->opt.useSecurity;
-            break;
-        case SSL_REQUEST_CERTIFICATE:
-            on = ss->opt.requestCertificate;
-            break;
-        case SSL_REQUIRE_CERTIFICATE:
-            on = ss->opt.requireCertificate;
-            break;
-        case SSL_HANDSHAKE_AS_CLIENT:
-            on = ss->opt.handshakeAsClient;
-            break;
-        case SSL_HANDSHAKE_AS_SERVER:
-            on = ss->opt.handshakeAsServer;
-            break;
-        case SSL_ENABLE_TLS:
-            on = ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_0;
-            break;
-        case SSL_ENABLE_SSL3:
-            on = ss->vrange.min == SSL_LIBRARY_VERSION_3_0;
-            break;
-        case SSL_ENABLE_SSL2:
-            on = ss->opt.enableSSL2;
-            break;
-        case SSL_NO_CACHE:
-            on = ss->opt.noCache;
-            break;
-        case SSL_ENABLE_FDX:
-            on = ss->opt.fdx;
-            break;
-        case SSL_V2_COMPATIBLE_HELLO:
-            on = ss->opt.v2CompatibleHello;
-            break;
-        case SSL_ROLLBACK_DETECTION:
-            on = ss->opt.detectRollBack;
-            break;
-        case SSL_NO_STEP_DOWN:
-            on = ss->opt.noStepDown;
-            break;
-        case SSL_BYPASS_PKCS11:
-            on = ss->opt.bypassPKCS11;
-            break;
-        case SSL_NO_LOCKS:
-            on = ss->opt.noLocks;
-            break;
-        case SSL_ENABLE_SESSION_TICKETS:
-            on = ss->opt.enableSessionTickets;
-            break;
-        case SSL_ENABLE_DEFLATE:
-            on = ss->opt.enableDeflate;
-            break;
-        case SSL_ENABLE_RENEGOTIATION:
-            on = ss->opt.enableRenegotiation;
-            break;
-        case SSL_REQUIRE_SAFE_NEGOTIATION:
-            on = ss->opt.requireSafeNegotiation;
-            break;
-        case SSL_ENABLE_FALSE_START:
-            on = ss->opt.enableFalseStart;
-            break;
-        case SSL_CBC_RANDOM_IV:
-            on = ss->opt.cbcRandomIV;
-            break;
-        case SSL_ENABLE_OCSP_STAPLING:
-            on = ss->opt.enableOCSPStapling;
-            break;
-        case SSL_ENABLE_NPN:
-            on = ss->opt.enableNPN;
-            break;
-        case SSL_ENABLE_ALPN:
-            on = ss->opt.enableALPN;
-            break;
-        case SSL_REUSE_SERVER_ECDHE_KEY:
-            on = ss->opt.reuseServerECDHEKey;
-            break;
-        case SSL_ENABLE_FALLBACK_SCSV:
-            on = ss->opt.enableFallbackSCSV;
-            break;
-        case SSL_ENABLE_SERVER_DHE:
-            on = ss->opt.enableServerDhe;
-            break;
-        case SSL_ENABLE_EXTENDED_MASTER_SECRET:
-            on = ss->opt.enableExtendedMS;
-            break;
-        case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
-            on = ss->opt.enableSignedCertTimestamps;
-            break;
-
-        default:
-            PORT_SetError(SEC_ERROR_INVALID_ARGS);
-            rv = SECFailure;
-    }
-
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    ssl_Release1stHandshakeLock(ss);
-
-    *pOn = on;
-    return rv;
-}
-
-SECStatus
-SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
-{
-    SECStatus rv = SECSuccess;
-    PRBool on = PR_FALSE;
-
-    if (!pOn) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    ssl_SetDefaultsFromEnvironment();
-
-    switch (which) {
-        case SSL_SOCKS:
-            on = PR_FALSE;
-            break;
-        case SSL_SECURITY:
-            on = ssl_defaults.useSecurity;
-            break;
-        case SSL_REQUEST_CERTIFICATE:
-            on = ssl_defaults.requestCertificate;
-            break;
-        case SSL_REQUIRE_CERTIFICATE:
-            on = ssl_defaults.requireCertificate;
-            break;
-        case SSL_HANDSHAKE_AS_CLIENT:
-            on = ssl_defaults.handshakeAsClient;
-            break;
-        case SSL_HANDSHAKE_AS_SERVER:
-            on = ssl_defaults.handshakeAsServer;
-            break;
-        case SSL_ENABLE_TLS:
-            on = versions_defaults_stream.max >= SSL_LIBRARY_VERSION_TLS_1_0;
-            break;
-        case SSL_ENABLE_SSL3:
-            on = versions_defaults_stream.min == SSL_LIBRARY_VERSION_3_0;
-            break;
-        case SSL_ENABLE_SSL2:
-            on = ssl_defaults.enableSSL2;
-            break;
-        case SSL_NO_CACHE:
-            on = ssl_defaults.noCache;
-            break;
-        case SSL_ENABLE_FDX:
-            on = ssl_defaults.fdx;
-            break;
-        case SSL_V2_COMPATIBLE_HELLO:
-            on = ssl_defaults.v2CompatibleHello;
-            break;
-        case SSL_ROLLBACK_DETECTION:
-            on = ssl_defaults.detectRollBack;
-            break;
-        case SSL_NO_STEP_DOWN:
-            on = ssl_defaults.noStepDown;
-            break;
-        case SSL_BYPASS_PKCS11:
-            on = ssl_defaults.bypassPKCS11;
-            break;
-        case SSL_NO_LOCKS:
-            on = ssl_defaults.noLocks;
-            break;
-        case SSL_ENABLE_SESSION_TICKETS:
-            on = ssl_defaults.enableSessionTickets;
-            break;
-        case SSL_ENABLE_DEFLATE:
-            on = ssl_defaults.enableDeflate;
-            break;
-        case SSL_ENABLE_RENEGOTIATION:
-            on = ssl_defaults.enableRenegotiation;
-            break;
-        case SSL_REQUIRE_SAFE_NEGOTIATION:
-            on = ssl_defaults.requireSafeNegotiation;
-            break;
-        case SSL_ENABLE_FALSE_START:
-            on = ssl_defaults.enableFalseStart;
-            break;
-        case SSL_CBC_RANDOM_IV:
-            on = ssl_defaults.cbcRandomIV;
-            break;
-        case SSL_ENABLE_OCSP_STAPLING:
-            on = ssl_defaults.enableOCSPStapling;
-            break;
-        case SSL_ENABLE_NPN:
-            on = ssl_defaults.enableNPN;
-            break;
-        case SSL_ENABLE_ALPN:
-            on = ssl_defaults.enableALPN;
-            break;
-        case SSL_REUSE_SERVER_ECDHE_KEY:
-            on = ssl_defaults.reuseServerECDHEKey;
-            break;
-        case SSL_ENABLE_FALLBACK_SCSV:
-            on = ssl_defaults.enableFallbackSCSV;
-            break;
-        case SSL_ENABLE_SERVER_DHE:
-            on = ssl_defaults.enableServerDhe;
-            break;
-        case SSL_ENABLE_EXTENDED_MASTER_SECRET:
-            on = ssl_defaults.enableExtendedMS;
-            break;
-        case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
-            on = ssl_defaults.enableSignedCertTimestamps;
-            break;
-
-        default:
-            PORT_SetError(SEC_ERROR_INVALID_ARGS);
-            rv = SECFailure;
-    }
-
-    *pOn = on;
-    return rv;
-}
-
-/* XXX Use Global Lock to protect this stuff. */
-SECStatus
-SSL_EnableDefault(int which, PRBool on)
-{
-    return SSL_OptionSetDefault(which, on);
-}
-
-SECStatus
-SSL_OptionSetDefault(PRInt32 which, PRBool on)
-{
-    SECStatus status = ssl_Init();
-
-    if (status != SECSuccess) {
-        return status;
-    }
-
-    ssl_SetDefaultsFromEnvironment();
-
-    switch (which) {
-        case SSL_SOCKS:
-            ssl_defaults.useSocks = PR_FALSE;
-            if (on) {
-                PORT_SetError(SEC_ERROR_INVALID_ARGS);
-                return SECFailure;
-            }
-            break;
-
-        case SSL_SECURITY:
-            ssl_defaults.useSecurity = on;
-            break;
-
-        case SSL_REQUEST_CERTIFICATE:
-            ssl_defaults.requestCertificate = on;
-            break;
-
-        case SSL_REQUIRE_CERTIFICATE:
-            ssl_defaults.requireCertificate = on;
-            break;
-
-        case SSL_HANDSHAKE_AS_CLIENT:
-            if (ssl_defaults.handshakeAsServer && on) {
-                PORT_SetError(SEC_ERROR_INVALID_ARGS);
-                return SECFailure;
-            }
-            ssl_defaults.handshakeAsClient = on;
-            break;
-
-        case SSL_HANDSHAKE_AS_SERVER:
-            if (ssl_defaults.handshakeAsClient && on) {
-                PORT_SetError(SEC_ERROR_INVALID_ARGS);
-                return SECFailure;
-            }
-            ssl_defaults.handshakeAsServer = on;
-            break;
-
-        case SSL_ENABLE_TLS:
-            ssl_EnableTLS(&versions_defaults_stream, on);
-            break;
-
-        case SSL_ENABLE_SSL3:
-            ssl_EnableSSL3(&versions_defaults_stream, on);
-            break;
-
-        case SSL_ENABLE_SSL2:
-            if (on) {
-                /* don't turn it on if ssl2 disallowed by by policy */
-                if (!ssl_VersionIsSupportedByPolicy(ssl_variant_stream,
-                                                    SSL_LIBRARY_VERSION_2)) {
-                    break;
-                }
-            }
-            ssl_defaults.enableSSL2 = on;
-            if (on) {
-                ssl_defaults.v2CompatibleHello = on;
-            }
-            break;
-
-        case SSL_NO_CACHE:
-            ssl_defaults.noCache = on;
-            break;
-
-        case SSL_ENABLE_FDX:
-            if (on && ssl_defaults.noLocks) {
-                PORT_SetError(SEC_ERROR_INVALID_ARGS);
-                return SECFailure;
-            }
-            ssl_defaults.fdx = on;
-            break;
-
-        case SSL_V2_COMPATIBLE_HELLO:
-            ssl_defaults.v2CompatibleHello = on;
-            if (!on) {
-                ssl_defaults.enableSSL2 = on;
-            }
-            break;
-
-        case SSL_ROLLBACK_DETECTION:
-            ssl_defaults.detectRollBack = on;
-            break;
-
-        case SSL_NO_STEP_DOWN:
-            ssl_defaults.noStepDown = on;
-            if (on)
-                SSL_DisableDefaultExportCipherSuites();
-            break;
-
-        case SSL_BYPASS_PKCS11:
-            if (PR_FALSE != on) {
-                if (PR_SUCCESS == SSL_BypassSetup()) {
-#ifdef NO_PKCS11_BYPASS
-                    ssl_defaults.bypassPKCS11 = PR_FALSE;
-#else
-                    ssl_defaults.bypassPKCS11 = on;
-#endif
-                } else {
-                    return SECFailure;
-                }
-            } else {
-                ssl_defaults.bypassPKCS11 = PR_FALSE;
-            }
-            break;
-
-        case SSL_NO_LOCKS:
-            if (on && ssl_defaults.fdx) {
-                PORT_SetError(SEC_ERROR_INVALID_ARGS);
-                return SECFailure;
-            }
-            if (on && ssl_force_locks)
-                on = PR_FALSE; /* silent override */
-            ssl_defaults.noLocks = on;
-            if (on) {
-                locksEverDisabled = PR_TRUE;
-                strcpy(lockStatus + LOCKSTATUS_OFFSET, "DISABLED.");
-            }
-            break;
-
-        case SSL_ENABLE_SESSION_TICKETS:
-            ssl_defaults.enableSessionTickets = on;
-            break;
-
-        case SSL_ENABLE_DEFLATE:
-            ssl_defaults.enableDeflate = on;
-            break;
-
-        case SSL_ENABLE_RENEGOTIATION:
-            ssl_defaults.enableRenegotiation = on;
-            break;
-
-        case SSL_REQUIRE_SAFE_NEGOTIATION:
-            ssl_defaults.requireSafeNegotiation = on;
-            break;
-
-        case SSL_ENABLE_FALSE_START:
-            ssl_defaults.enableFalseStart = on;
-            break;
-
-        case SSL_CBC_RANDOM_IV:
-            ssl_defaults.cbcRandomIV = on;
-            break;
-
-        case SSL_ENABLE_OCSP_STAPLING:
-            ssl_defaults.enableOCSPStapling = on;
-            break;
-
-        case SSL_ENABLE_NPN:
-            ssl_defaults.enableNPN = on;
-            break;
-
-        case SSL_ENABLE_ALPN:
-            ssl_defaults.enableALPN = on;
-            break;
-
-        case SSL_REUSE_SERVER_ECDHE_KEY:
-            ssl_defaults.reuseServerECDHEKey = on;
-            break;
-
-        case SSL_ENABLE_FALLBACK_SCSV:
-            ssl_defaults.enableFallbackSCSV = on;
-            break;
-
-        case SSL_ENABLE_SERVER_DHE:
-            ssl_defaults.enableServerDhe = on;
-            break;
-
-        case SSL_ENABLE_EXTENDED_MASTER_SECRET:
-            ssl_defaults.enableExtendedMS = on;
-            break;
-
-        case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
-            ssl_defaults.enableSignedCertTimestamps = on;
-            break;
-
-        default:
-            PORT_SetError(SEC_ERROR_INVALID_ARGS);
-            return SECFailure;
-    }
-    return SECSuccess;
-}
-
-/* function tells us if the cipher suite is one that we no longer support. */
-static PRBool
-ssl_IsRemovedCipherSuite(PRInt32 suite)
-{
-    switch (suite) {
-        case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
-        case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:
-        case SSL_FORTEZZA_DMS_WITH_RC4_128_SHA:
-            return PR_TRUE;
-        default:
-            return PR_FALSE;
-    }
-}
-
-/* Part of the public NSS API.
- * Since this is a global (not per-socket) setting, we cannot use the
- * HandshakeLock to protect this.  Probably want a global lock.
- */
-SECStatus
-SSL_SetPolicy(long which, int policy)
-{
-    if ((which & 0xfffe) == SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA) {
-        /* one of the two old FIPS ciphers */
-        if (which == SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA)
-            which = SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA;
-        else if (which == SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA)
-            which = SSL_RSA_FIPS_WITH_DES_CBC_SHA;
-    }
-    if (ssl_IsRemovedCipherSuite(which))
-        return SECSuccess;
-    return SSL_CipherPolicySet(which, policy);
-}
-
-SECStatus
-ssl_CipherPolicySet(PRInt32 which, PRInt32 policy)
-{
-    SECStatus rv = SECSuccess;
-
-    if (ssl_IsRemovedCipherSuite(which)) {
-        rv = SECSuccess;
-    } else if (SSL_IS_SSL2_CIPHER(which)) {
-        rv = ssl2_SetPolicy(which, policy);
-    } else {
-        rv = ssl3_SetPolicy((ssl3CipherSuite)which, policy);
-    }
-    return rv;
-}
-SECStatus
-SSL_CipherPolicySet(PRInt32 which, PRInt32 policy)
-{
-    SECStatus rv = ssl_Init();
-
-    if (rv != SECSuccess) {
-        return rv;
-    }
-    return ssl_CipherPolicySet(which, policy);
-}
-
-SECStatus
-SSL_CipherPolicyGet(PRInt32 which, PRInt32 *oPolicy)
-{
-    SECStatus rv;
-
-    if (!oPolicy) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-    if (ssl_IsRemovedCipherSuite(which)) {
-        *oPolicy = SSL_NOT_ALLOWED;
-        rv = SECSuccess;
-    } else if (SSL_IS_SSL2_CIPHER(which)) {
-        rv = ssl2_GetPolicy(which, oPolicy);
-    } else {
-        rv = ssl3_GetPolicy((ssl3CipherSuite)which, oPolicy);
-    }
-    return rv;
-}
-
-/* Part of the public NSS API.
- * Since this is a global (not per-socket) setting, we cannot use the
- * HandshakeLock to protect this.  Probably want a global lock.
- * These changes have no effect on any sslSockets already created.
- */
-SECStatus
-SSL_EnableCipher(long which, PRBool enabled)
-{
-    if ((which & 0xfffe) == SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA) {
-        /* one of the two old FIPS ciphers */
-        if (which == SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA)
-            which = SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA;
-        else if (which == SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA)
-            which = SSL_RSA_FIPS_WITH_DES_CBC_SHA;
-    }
-    if (ssl_IsRemovedCipherSuite(which))
-        return SECSuccess;
-    return SSL_CipherPrefSetDefault(which, enabled);
-}
-
-SECStatus
-ssl_CipherPrefSetDefault(PRInt32 which, PRBool enabled)
-{
-    SECStatus rv = SECSuccess;
-
-    if (ssl_IsRemovedCipherSuite(which))
-        return SECSuccess;
-    if (enabled && ssl_defaults.noStepDown && SSL_IsExportCipherSuite(which)) {
-        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
-        return SECFailure;
-    }
-    if (SSL_IS_SSL2_CIPHER(which)) {
-        rv = ssl2_CipherPrefSetDefault(which, enabled);
-    } else {
-        rv = ssl3_CipherPrefSetDefault((ssl3CipherSuite)which, enabled);
-    }
-    return rv;
-}
-
-SECStatus
-SSL_CipherPrefSetDefault(PRInt32 which, PRBool enabled)
-{
-    SECStatus rv = ssl_Init();
-
-    if (rv != SECSuccess) {
-        return rv;
-    }
-    return ssl_CipherPrefSetDefault(which, enabled);
-}
-
-SECStatus
-SSL_CipherPrefGetDefault(PRInt32 which, PRBool *enabled)
-{
-    SECStatus rv;
-
-    if (!enabled) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-    if (ssl_IsRemovedCipherSuite(which)) {
-        *enabled = PR_FALSE;
-        rv = SECSuccess;
-    } else if (SSL_IS_SSL2_CIPHER(which)) {
-        rv = ssl2_CipherPrefGetDefault(which, enabled);
-    } else {
-        rv = ssl3_CipherPrefGetDefault((ssl3CipherSuite)which, enabled);
-    }
-    return rv;
-}
-
-SECStatus
-SSL_CipherPrefSet(PRFileDesc *fd, PRInt32 which, PRBool enabled)
-{
-    SECStatus rv;
-    sslSocket *ss = ssl_FindSocket(fd);
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in CipherPrefSet", SSL_GETPID(), fd));
-        return SECFailure;
-    }
-    if (ssl_IsRemovedCipherSuite(which))
-        return SECSuccess;
-    if (enabled && ss->opt.noStepDown && SSL_IsExportCipherSuite(which)) {
-        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
-        return SECFailure;
-    }
-    if (SSL_IS_SSL2_CIPHER(which)) {
-        rv = ssl2_CipherPrefSet(ss, which, enabled);
-    } else {
-        rv = ssl3_CipherPrefSet(ss, (ssl3CipherSuite)which, enabled);
-    }
-    return rv;
-}
-
-SECStatus
-SSL_CipherOrderSet(PRFileDesc *fd, const PRUint16 *ciphers, unsigned int len)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in CipherOrderSet", SSL_GETPID(),
-                 fd));
-        return SECFailure;
-    }
-    return ssl3_CipherOrderSet(ss, ciphers, len);
-}
-
-SECStatus
-SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled)
-{
-    SECStatus rv;
-    sslSocket *ss = ssl_FindSocket(fd);
-
-    if (!enabled) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in CipherPrefGet", SSL_GETPID(), fd));
-        *enabled = PR_FALSE;
-        return SECFailure;
-    }
-    if (ssl_IsRemovedCipherSuite(which)) {
-        *enabled = PR_FALSE;
-        rv = SECSuccess;
-    } else if (SSL_IS_SSL2_CIPHER(which)) {
-        rv = ssl2_CipherPrefGet(ss, which, enabled);
-    } else {
-        rv = ssl3_CipherPrefGet(ss, (ssl3CipherSuite)which, enabled);
-    }
-    return rv;
-}
-
-SECStatus
-NSS_SetDomesticPolicy(void)
-{
-    SECStatus status = SECSuccess;
-    const PRUint16 *cipher;
-    SECStatus rv;
-    PRUint32 policy;
-
-    /* If we've already defined some policy oids, skip changing them */
-    rv = NSS_GetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, &policy);
-    if ((rv == SECSuccess) && (policy & NSS_USE_POLICY_IN_SSL)) {
-        return ssl_Init(); /* make sure the policies have bee loaded */
-    }
-
-    for (cipher = SSL_ImplementedCiphers; *cipher != 0; ++cipher) {
-        status = SSL_SetPolicy(*cipher, SSL_ALLOWED);
-        if (status != SECSuccess)
-            break;
-    }
-    return status;
-}
-
-SECStatus
-NSS_SetExportPolicy(void)
-{
-    return NSS_SetDomesticPolicy();
-}
-
-SECStatus
-NSS_SetFrancePolicy(void)
-{
-    return NSS_SetDomesticPolicy();
-}
-
-SECStatus
-SSL_DHEGroupPrefSet(PRFileDesc *fd,
-                    SSLDHEGroupType *groups,
-                    PRUint16 num_groups)
-{
-    sslSocket *ss;
-
-    if ((num_groups && !groups) || (!num_groups && groups)) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_DHEGroupPrefSet", SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (ss->ssl3.dheGroups) {
-        PORT_Free(ss->ssl3.dheGroups);
-        ss->ssl3.dheGroups = NULL;
-        ss->ssl3.numDHEGroups = 0;
-    }
-
-    if (groups) {
-        ss->ssl3.dheGroups = PORT_NewArray(SSLDHEGroupType, num_groups);
-        if (!ss->ssl3.dheGroups) {
-            PORT_SetError(SEC_ERROR_NO_MEMORY);
-            return SECFailure;
-        }
-        PORT_Memcpy(ss->ssl3.dheGroups, groups,
-                    sizeof(SSLDHEGroupType) * num_groups);
-    }
-    return SECSuccess;
-}
-
-PRCallOnceType gWeakDHParamsRegisterOnce;
-int gWeakDHParamsRegisterError;
-
-PRCallOnceType gWeakDHParamsOnce;
-int gWeakDHParamsError;
-/* As our code allocates type PQGParams, we'll keep it around,
- * even though we only make use of it's parameters through gWeakDHParam. */
-static PQGParams *gWeakParamsPQG;
-static ssl3DHParams *gWeakDHParams;
-
-static PRStatus
-ssl3_CreateWeakDHParams(void)
-{
-    PQGVerify *vfy;
-    SECStatus rv, passed;
-
-    PORT_Assert(!gWeakDHParams && !gWeakParamsPQG);
-
-    rv = PK11_PQG_ParamGenV2(1024, 160, 64 /*maximum seed that will work*/,
-                             &gWeakParamsPQG, &vfy);
-    if (rv != SECSuccess) {
-        gWeakDHParamsError = PORT_GetError();
-        return PR_FAILURE;
-    }
-
-    rv = PK11_PQG_VerifyParams(gWeakParamsPQG, vfy, &passed);
-    if (rv != SECSuccess || passed != SECSuccess) {
-        SSL_DBG(("%d: PK11_PQG_VerifyParams failed in ssl3_CreateWeakDHParams",
-                 SSL_GETPID()));
-        gWeakDHParamsError = PORT_GetError();
-        return PR_FAILURE;
-    }
-
-    gWeakDHParams = PORT_ArenaNew(gWeakParamsPQG->arena, ssl3DHParams);
-    if (!gWeakDHParams) {
-        gWeakDHParamsError = PORT_GetError();
-        return PR_FAILURE;
-    }
-
-    gWeakDHParams->prime.data = gWeakParamsPQG->prime.data;
-    gWeakDHParams->prime.len = gWeakParamsPQG->prime.len;
-    gWeakDHParams->base.data = gWeakParamsPQG->base.data;
-    gWeakDHParams->base.len = gWeakParamsPQG->base.len;
-
-    PK11_PQG_DestroyVerify(vfy);
-    return PR_SUCCESS;
-}
-
-static SECStatus
-ssl3_WeakDHParamsShutdown(void *appData, void *nssData)
-{
-    if (gWeakParamsPQG) {
-        PK11_PQG_DestroyParams(gWeakParamsPQG);
-        gWeakParamsPQG = NULL;
-        gWeakDHParams = NULL;
-    }
-    return SECSuccess;
-}
-
-static PRStatus
-ssl3_WeakDHParamsRegisterShutdown(void)
-{
-    SECStatus rv;
-    rv = NSS_RegisterShutdown(ssl3_WeakDHParamsShutdown, NULL);
-    if (rv != SECSuccess) {
-        gWeakDHParamsRegisterError = PORT_GetError();
-    }
-    return (PRStatus)rv;
-}
-
-/* global init strategy inspired by ssl3_CreateECDHEphemeralKeys */
-SECStatus
-SSL_EnableWeakDHEPrimeGroup(PRFileDesc *fd, PRBool enabled)
-{
-    sslSocket *ss;
-    PRStatus status;
-
-    if (enabled) {
-        status = PR_CallOnce(&gWeakDHParamsRegisterOnce,
-                             ssl3_WeakDHParamsRegisterShutdown);
-        if (status != PR_SUCCESS) {
-            PORT_SetError(gWeakDHParamsRegisterError);
-            return SECFailure;
-        }
-
-        status = PR_CallOnce(&gWeakDHParamsOnce, ssl3_CreateWeakDHParams);
-        if (status != PR_SUCCESS) {
-            PORT_SetError(gWeakDHParamsError);
-            return SECFailure;
-        }
-    }
-
-    if (!fd)
-        return SECSuccess;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_DHEGroupPrefSet", SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    ss->ssl3.dheWeakGroupEnabled = enabled;
-    return SECSuccess;
-}
-
-SECStatus
-SSL_GetChannelBinding(PRFileDesc *fd,
-                      SSLChannelBindingType binding_type,
-                      unsigned char *out,
-                      unsigned int *outLen,
-                      unsigned int outLenMax)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelBinding",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (binding_type != SSL_CHANNEL_BINDING_TLS_UNIQUE) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return SECFailure;
-    }
-
-    return ssl3_GetTLSUniqueChannelBinding(ss, out, outLen, outLenMax);
-}
-
-#include "dhe-param.c"
-
-static const SSLDHEGroupType ssl_default_dhe_groups[] = {
-    ssl_ff_dhe_2048_group
-};
-
-/* Keep this array synchronized with the index definitions in SSLDHEGroupType */
-static const ssl3DHParams *all_ssl3DHParams[] = {
-    NULL, /* ssl_dhe_group_none */
-    &ff_dhe_2048,
-    &ff_dhe_3072,
-    &ff_dhe_4096,
-    &ff_dhe_6144,
-    &ff_dhe_8192,
-};
-
-static SSLDHEGroupType
-selectDHEGroup(sslSocket *ss, const SSLDHEGroupType *groups, PRUint16 num_groups)
-{
-    if (!groups || !num_groups)
-        return ssl_dhe_group_none;
-
-    /* We don't have automatic group parameter selection yet
-     * (potentially) based on socket parameters, e.g. key sizes.
-     * For now, we return the first available group from the allowed list. */
-    return groups[0];
-}
-
-/* Ensure DH parameters have been selected */
-SECStatus
-ssl3_SelectDHParams(sslSocket *ss)
-{
-    SSLDHEGroupType selectedGroup = ssl_dhe_group_none;
-
-    if (ss->ssl3.dheWeakGroupEnabled) {
-        ss->dheParams = gWeakDHParams;
-    } else {
-        if (ss->ssl3.dheGroups) {
-            selectedGroup = selectDHEGroup(ss, ss->ssl3.dheGroups,
-                                           ss->ssl3.numDHEGroups);
-        } else {
-            size_t number_of_default_groups = PR_ARRAY_SIZE(ssl_default_dhe_groups);
-            selectedGroup = selectDHEGroup(ss, ssl_default_dhe_groups,
-                                           number_of_default_groups);
-        }
-
-        if (selectedGroup == ssl_dhe_group_none ||
-            selectedGroup >= ssl_dhe_group_max) {
-            return SECFailure;
-        }
-
-        ss->dheParams = all_ssl3DHParams[selectedGroup];
-    }
-
-    return SECSuccess;
-}
-
-/* LOCKS ??? XXX */
-static PRFileDesc *
-ssl_ImportFD(PRFileDesc *model, PRFileDesc *fd, SSLProtocolVariant variant)
-{
-    sslSocket *ns = NULL;
-    PRStatus rv;
-    PRNetAddr addr;
-    SECStatus status = ssl_Init();
-
-    if (status != SECSuccess) {
-        return NULL;
-    }
-
-    if (model == NULL) {
-        /* Just create a default socket if we're given NULL for the model */
-        ns = ssl_NewSocket((PRBool)(!ssl_defaults.noLocks), variant);
-    } else {
-        sslSocket *ss = ssl_FindSocket(model);
-        if (ss == NULL || ss->protocolVariant != variant) {
-            SSL_DBG(("%d: SSL[%d]: bad model socket in ssl_ImportFD",
-                     SSL_GETPID(), model));
-            return NULL;
-        }
-        ns = ssl_DupSocket(ss);
-    }
-    if (ns == NULL)
-        return NULL;
-
-    rv = ssl_PushIOLayer(ns, fd, PR_TOP_IO_LAYER);
-    if (rv != PR_SUCCESS) {
-        ssl_FreeSocket(ns);
-        SET_ERROR_CODE
-        return NULL;
-    }
-#if defined(DEBUG) || defined(FORCE_PR_ASSERT)
-    {
-        sslSocket *ss = ssl_FindSocket(fd);
-        PORT_Assert(ss == ns);
-    }
-#endif
-    ns->TCPconnected = (PR_SUCCESS == ssl_DefGetpeername(ns, &addr));
-    return fd;
-}
-
-PRFileDesc *
-SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd)
-{
-    return ssl_ImportFD(model, fd, ssl_variant_stream);
-}
-
-PRFileDesc *
-DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd)
-{
-    return ssl_ImportFD(model, fd, ssl_variant_datagram);
-}
-
-/* SSL_SetNextProtoCallback is used to select an application protocol
- * for ALPN and NPN.  For ALPN, this runs on the server; for NPN it
- * runs on the client. */
-/* Note: The ALPN version doesn't allow for the use of a default, setting a
- * status of SSL_NEXT_PROTO_NO_OVERLAP is treated as a failure. */
-SECStatus
-SSL_SetNextProtoCallback(PRFileDesc *fd, SSLNextProtoCallback callback,
-                         void *arg)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetNextProtoCallback", SSL_GETPID(),
-                 fd));
-        return SECFailure;
-    }
-
-    ssl_GetSSL3HandshakeLock(ss);
-    ss->nextProtoCallback = callback;
-    ss->nextProtoArg = arg;
-    ssl_ReleaseSSL3HandshakeLock(ss);
-
-    return SECSuccess;
-}
-
-/* ssl_NextProtoNegoCallback is set as an ALPN/NPN callback when
- * SSL_SetNextProtoNego is used.
- */
-static SECStatus
-ssl_NextProtoNegoCallback(void *arg, PRFileDesc *fd,
-                          const unsigned char *protos, unsigned int protos_len,
-                          unsigned char *protoOut, unsigned int *protoOutLen,
-                          unsigned int protoMaxLen)
-{
-    unsigned int i, j;
-    const unsigned char *result;
-    sslSocket *ss = ssl_FindSocket(fd);
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in ssl_NextProtoNegoCallback",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    /* For each protocol in server preference, see if we support it. */
-    for (i = 0; i < protos_len;) {
-        for (j = 0; j < ss->opt.nextProtoNego.len;) {
-            if (protos[i] == ss->opt.nextProtoNego.data[j] &&
-                PORT_Memcmp(&protos[i + 1], &ss->opt.nextProtoNego.data[j + 1],
-                            protos[i]) == 0) {
-                /* We found a match. */
-                ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED;
-                result = &protos[i];
-                goto found;
-            }
-            j += 1 + (unsigned int)ss->opt.nextProtoNego.data[j];
-        }
-        i += 1 + (unsigned int)protos[i];
-    }
-
-    /* The other side supports the extension, and either doesn't have any
-     * protocols configured, or none of its options match ours. In this case we
-     * request our favoured protocol. */
-    /* This will be treated as a failure for ALPN. */
-    ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP;
-    result = ss->opt.nextProtoNego.data;
-
-found:
-    if (protoMaxLen < result[0]) {
-        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
-        return SECFailure;
-    }
-    memcpy(protoOut, result + 1, result[0]);
-    *protoOutLen = result[0];
-    return SECSuccess;
-}
-
-SECStatus
-SSL_SetNextProtoNego(PRFileDesc *fd, const unsigned char *data,
-                     unsigned int length)
-{
-    sslSocket *ss;
-    SECStatus rv;
-    SECItem dataItem = { siBuffer, (unsigned char *)data, length };
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetNextProtoNego",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (ssl3_ValidateNextProtoNego(data, length) != SECSuccess)
-        return SECFailure;
-
-    ssl_GetSSL3HandshakeLock(ss);
-    SECITEM_FreeItem(&ss->opt.nextProtoNego, PR_FALSE);
-    rv = SECITEM_CopyItem(NULL, &ss->opt.nextProtoNego, &dataItem);
-    ssl_ReleaseSSL3HandshakeLock(ss);
-
-    if (rv != SECSuccess)
-        return rv;
-
-    return SSL_SetNextProtoCallback(fd, ssl_NextProtoNegoCallback, NULL);
-}
-
-SECStatus
-SSL_GetNextProto(PRFileDesc *fd, SSLNextProtoState *state, unsigned char *buf,
-                 unsigned int *bufLen, unsigned int bufLenMax)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetNextProto", SSL_GETPID(),
-                 fd));
-        return SECFailure;
-    }
-
-    if (!state || !buf || !bufLen) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    *state = ss->ssl3.nextProtoState;
-
-    if (ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT &&
-        ss->ssl3.nextProto.data) {
-        if (ss->ssl3.nextProto.len > bufLenMax) {
-            PORT_SetError(SEC_ERROR_OUTPUT_LEN);
-            return SECFailure;
-        }
-        PORT_Memcpy(buf, ss->ssl3.nextProto.data, ss->ssl3.nextProto.len);
-        *bufLen = ss->ssl3.nextProto.len;
-    } else {
-        *bufLen = 0;
-    }
-
-    return SECSuccess;
-}
-
-SECStatus
-SSL_SetSRTPCiphers(PRFileDesc *fd,
-                   const PRUint16 *ciphers,
-                   unsigned int numCiphers)
-{
-    sslSocket *ss;
-    unsigned int i;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss || !IS_DTLS(ss)) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetSRTPCiphers",
-                 SSL_GETPID(), fd));
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    if (numCiphers > MAX_DTLS_SRTP_CIPHER_SUITES) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    ss->ssl3.dtlsSRTPCipherCount = 0;
-    for (i = 0; i < numCiphers; i++) {
-        const PRUint16 *srtpCipher = srtpCiphers;
-
-        while (*srtpCipher) {
-            if (ciphers[i] == *srtpCipher)
-                break;
-            srtpCipher++;
-        }
-        if (*srtpCipher) {
-            ss->ssl3.dtlsSRTPCiphers[ss->ssl3.dtlsSRTPCipherCount++] =
-                ciphers[i];
-        } else {
-            SSL_DBG(("%d: SSL[%d]: invalid or unimplemented SRTP cipher "
-                     "suite specified: 0x%04hx",
-                     SSL_GETPID(), fd,
-                     ciphers[i]));
-        }
-    }
-
-    if (ss->ssl3.dtlsSRTPCipherCount == 0) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    return SECSuccess;
-}
-
-SECStatus
-SSL_GetSRTPCipher(PRFileDesc *fd, PRUint16 *cipher)
-{
-    sslSocket *ss;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetSRTPCipher",
-                 SSL_GETPID(), fd));
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    if (!ss->ssl3.dtlsSRTPCipherSuite) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    *cipher = ss->ssl3.dtlsSRTPCipherSuite;
-    return SECSuccess;
-}
-
-PRFileDesc *
-SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
-{
-    sslSocket *sm = NULL, *ss = NULL;
-    int i;
-    sslServerCerts *mc = NULL;
-    sslServerCerts *sc = NULL;
-
-    if (model == NULL) {
-        PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
-        return NULL;
-    }
-    sm = ssl_FindSocket(model);
-    if (sm == NULL) {
-        SSL_DBG(("%d: SSL[%d]: bad model socket in ssl_ReconfigFD",
-                 SSL_GETPID(), model));
-        return NULL;
-    }
-    ss = ssl_FindSocket(fd);
-    PORT_Assert(ss);
-    if (ss == NULL) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return NULL;
-    }
-
-    ss->opt = sm->opt;
-    ss->vrange = sm->vrange;
-    PORT_Memcpy(ss->cipherSuites, sm->cipherSuites, sizeof sm->cipherSuites);
-    PORT_Memcpy(ss->ssl3.dtlsSRTPCiphers, sm->ssl3.dtlsSRTPCiphers,
-                sizeof(PRUint16) * sm->ssl3.dtlsSRTPCipherCount);
-    ss->ssl3.dtlsSRTPCipherCount = sm->ssl3.dtlsSRTPCipherCount;
-    PORT_Memcpy(ss->ssl3.signatureAlgorithms, sm->ssl3.signatureAlgorithms,
-                sizeof(ss->ssl3.signatureAlgorithms[0]) *
-                    sm->ssl3.signatureAlgorithmCount);
-    ss->ssl3.signatureAlgorithmCount = sm->ssl3.signatureAlgorithmCount;
-    ss->ssl3.downgradeCheckVersion = sm->ssl3.downgradeCheckVersion;
-
-    if (!ss->opt.useSecurity) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return NULL;
-    }
-    /* This int should be SSLKEAType, but CC on Irix complains,
-     * during the for loop.
-     */
-    for (i = kt_null; i < kt_kea_size; i++) {
-        mc = &(sm->serverCerts[i]);
-        sc = &(ss->serverCerts[i]);
-        if (mc->serverCert && mc->serverCertChain) {
-            if (sc->serverCert) {
-                CERT_DestroyCertificate(sc->serverCert);
-            }
-            sc->serverCert = CERT_DupCertificate(mc->serverCert);
-            if (sc->serverCertChain) {
-                CERT_DestroyCertificateList(sc->serverCertChain);
-            }
-            sc->serverCertChain = CERT_DupCertList(mc->serverCertChain);
-            if (!sc->serverCertChain)
-                goto loser;
-            if (sm->certStatusArray[i]) {
-                if (ss->certStatusArray[i]) {
-                    SECITEM_FreeArray(ss->certStatusArray[i], PR_TRUE);
-                    ss->certStatusArray[i] = NULL;
-                }
-                ss->certStatusArray[i] = SECITEM_DupArray(NULL, sm->certStatusArray[i]);
-                if (!ss->certStatusArray[i])
-                    goto loser;
-            }
-            if (sm->signedCertTimestamps[i].data) {
-                if (ss->signedCertTimestamps[i].data) {
-                    SECITEM_FreeItem(&ss->signedCertTimestamps[i], PR_FALSE);
-                }
-                if (SECITEM_CopyItem(NULL,
-                                     &ss->signedCertTimestamps[i],
-                                     &sm->signedCertTimestamps[i]) !=
-                    SECSuccess) {
-                    goto loser;
-                }
-            }
-        }
-        if (mc->serverKeyPair) {
-            if (sc->serverKeyPair) {
-                ssl3_FreeKeyPair(sc->serverKeyPair);
-            }
-            sc->serverKeyPair = ssl3_GetKeyPairRef(mc->serverKeyPair);
-            sc->serverKeyBits = mc->serverKeyBits;
-        }
-    }
-    if (sm->stepDownKeyPair) {
-        if (ss->stepDownKeyPair) {
-            ssl3_FreeKeyPair(ss->stepDownKeyPair);
-        }
-        ss->stepDownKeyPair = ssl3_GetKeyPairRef(sm->stepDownKeyPair);
-    }
-    if (sm->ephemeralECDHKeyPair) {
-        if (ss->ephemeralECDHKeyPair) {
-            ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair);
-        }
-        ss->ephemeralECDHKeyPair =
-            ssl3_GetKeyPairRef(sm->ephemeralECDHKeyPair);
-    }
-    /* copy trust anchor names */
-    if (sm->ssl3.ca_list) {
-        if (ss->ssl3.ca_list) {
-            CERT_FreeDistNames(ss->ssl3.ca_list);
-        }
-        ss->ssl3.ca_list = CERT_DupDistNames(sm->ssl3.ca_list);
-        if (!ss->ssl3.ca_list) {
-            goto loser;
-        }
-    }
-
-    if (sm->authCertificate)
-        ss->authCertificate = sm->authCertificate;
-    if (sm->authCertificateArg)
-        ss->authCertificateArg = sm->authCertificateArg;
-    if (sm->getClientAuthData)
-        ss->getClientAuthData = sm->getClientAuthData;
-    if (sm->getClientAuthDataArg)
-        ss->getClientAuthDataArg = sm->getClientAuthDataArg;
-    if (sm->sniSocketConfig)
-        ss->sniSocketConfig = sm->sniSocketConfig;
-    if (sm->sniSocketConfigArg)
-        ss->sniSocketConfigArg = sm->sniSocketConfigArg;
-    if (sm->handleBadCert)
-        ss->handleBadCert = sm->handleBadCert;
-    if (sm->badCertArg)
-        ss->badCertArg = sm->badCertArg;
-    if (sm->handshakeCallback)
-        ss->handshakeCallback = sm->handshakeCallback;
-    if (sm->handshakeCallbackData)
-        ss->handshakeCallbackData = sm->handshakeCallbackData;
-    if (sm->pkcs11PinArg)
-        ss->pkcs11PinArg = sm->pkcs11PinArg;
-    if (sm->getChannelID)
-        ss->getChannelID = sm->getChannelID;
-    if (sm->getChannelIDArg)
-        ss->getChannelIDArg = sm->getChannelIDArg;
-    return fd;
-loser:
-    return NULL;
-}
-
-/*
- * Get the user supplied range
- */
-static SECStatus
-ssl3_GetRangePolicy(SSLProtocolVariant protocolVariant, SSLVersionRange *prange)
-{
-    SECStatus rv;
-    PRUint32 policy;
-    PRInt32 option;
-
-    /* only use policy constraints if we've set the apply ssl policy bit */
-    rv = NSS_GetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, &policy);
-    if ((rv != SECSuccess) || !(policy & NSS_USE_POLICY_IN_SSL)) {
-        return SECFailure;
-    }
-    rv = NSS_OptionGet(VERSIONS_POLICY_MIN(protocolVariant), &option);
-    if (rv != SECSuccess) {
-        return rv;
-    }
-    prange->min = (PRUint16)option;
-    rv = NSS_OptionGet(VERSIONS_POLICY_MAX(protocolVariant), &option);
-    if (rv != SECSuccess) {
-        return rv;
-    }
-    prange->max = (PRUint16)option;
-    if (prange->max < prange->min) {
-        return SECFailure; /* don't accept an invalid policy */
-    }
-    return SECSuccess;
-}
-
-/*
- * Constrain a single protocol variant's range based on the user policy
- */
-static SECStatus
-ssl3_ConstrainVariantRangeByPolicy(SSLProtocolVariant protocolVariant)
-{
-    SSLVersionRange vrange;
-    SSLVersionRange pvrange;
-    SECStatus rv;
-
-    vrange = *VERSIONS_DEFAULTS(protocolVariant);
-    rv = ssl3_GetRangePolicy(protocolVariant, &pvrange);
-    if (rv != SECSuccess) {
-        return SECSuccess; /* we don't have any policy */
-    }
-    vrange.min = PR_MAX(vrange.min, pvrange.min);
-    vrange.max = PR_MIN(vrange.max, pvrange.max);
-    if (vrange.max >= vrange.min) {
-        *VERSIONS_DEFAULTS(protocolVariant) = vrange;
-    } else {
-        /* there was no overlap, turn off range altogether */
-        pvrange.min = pvrange.max = SSL_LIBRARY_VERSION_NONE;
-        *VERSIONS_DEFAULTS(protocolVariant) = pvrange;
-    }
-    return SECSuccess;
-}
-
-static PRBool
-ssl_VersionIsSupportedByPolicy(SSLProtocolVariant protocolVariant,
-                               SSL3ProtocolVersion version)
-{
-    SSLVersionRange pvrange;
-    SECStatus rv;
-
-    rv = ssl3_GetRangePolicy(protocolVariant, &pvrange);
-    if (rv == SECSuccess) {
-        if ((version > pvrange.max) || (version < pvrange.min)) {
-            return PR_FALSE; /* disallowed by policy */
-        }
-    }
-    return PR_TRUE;
-}
-
-/*
- *  This is called at SSL init time to constrain the existing range based
- *  on user supplied policy.
- */
-SECStatus
-ssl3_ConstrainRangeByPolicy(void)
-{
-    SECStatus rv;
-    rv = ssl3_ConstrainVariantRangeByPolicy(ssl_variant_stream);
-    if (rv != SECSuccess) {
-        return rv;
-    }
-    rv = ssl3_ConstrainVariantRangeByPolicy(ssl_variant_datagram);
-    if (rv != SECSuccess) {
-        return rv;
-    }
-    return SECSuccess;
-}
-
-PRBool
-ssl3_VersionIsSupported(SSLProtocolVariant protocolVariant,
-                        SSL3ProtocolVersion version)
-{
-    if (!ssl_VersionIsSupportedByPolicy(protocolVariant, version)) {
-        return PR_FALSE;
-    }
-    switch (protocolVariant) {
-        case ssl_variant_stream:
-            return (version >= SSL_LIBRARY_VERSION_3_0 &&
-                    version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED);
-        case ssl_variant_datagram:
-            return (version >= SSL_LIBRARY_VERSION_TLS_1_1 &&
-                    version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED);
-        default:
-            /* Can't get here */
-            PORT_Assert(PR_FALSE);
-            return PR_FALSE;
-    }
-}
-
-/* Returns PR_TRUE if the given version range is valid and
-** fully supported; otherwise, returns PR_FALSE.
-*/
-static PRBool
-ssl3_VersionRangeIsValid(SSLProtocolVariant protocolVariant,
-                         const SSLVersionRange *vrange)
-{
-    return vrange &&
-           vrange->min <= vrange->max &&
-           ssl3_VersionIsSupported(protocolVariant, vrange->min) &&
-           ssl3_VersionIsSupported(protocolVariant, vrange->max);
-}
-
-const SECItem *
-SSL_PeerSignedCertTimestamps(PRFileDesc *fd)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_PeerSignedCertTimestamps",
-                 SSL_GETPID(), fd));
-        return NULL;
-    }
-
-    if (!ss->sec.ci.sid) {
-        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
-        return NULL;
-    }
-
-    if (ss->sec.ci.sid->version < SSL_LIBRARY_VERSION_3_0) {
-        PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
-        return NULL;
-    }
-    return &ss->sec.ci.sid->u.ssl3.signedCertTimestamps;
-}
-
-SECStatus
-SSL_VersionRangeGetSupported(SSLProtocolVariant protocolVariant,
-                             SSLVersionRange *vrange)
-{
-    if (!vrange) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    switch (protocolVariant) {
-        case ssl_variant_stream:
-            vrange->min = SSL_LIBRARY_VERSION_3_0;
-            vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED;
-            break;
-        case ssl_variant_datagram:
-            vrange->min = SSL_LIBRARY_VERSION_TLS_1_1;
-            vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED;
-            break;
-        default:
-            PORT_SetError(SEC_ERROR_INVALID_ARGS);
-            return SECFailure;
-    }
-
-    return SECSuccess;
-}
-
-SECStatus
-SSL_VersionRangeGetDefault(SSLProtocolVariant protocolVariant,
-                           SSLVersionRange *vrange)
-{
-    if ((protocolVariant != ssl_variant_stream &&
-         protocolVariant != ssl_variant_datagram) ||
-        !vrange) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    *vrange = *VERSIONS_DEFAULTS(protocolVariant);
-
-    return SECSuccess;
-}
-
-SECStatus
-SSL_VersionRangeSetDefault(SSLProtocolVariant protocolVariant,
-                           const SSLVersionRange *vrange)
-{
-    if (!ssl3_VersionRangeIsValid(protocolVariant, vrange)) {
-        PORT_SetError(SSL_ERROR_INVALID_VERSION_RANGE);
-        return SECFailure;
-    }
-
-    *VERSIONS_DEFAULTS(protocolVariant) = *vrange;
-
-    return SECSuccess;
-}
-
-SECStatus
-SSL_VersionRangeGet(PRFileDesc *fd, SSLVersionRange *vrange)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_VersionRangeGet",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (!vrange) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    ssl_Get1stHandshakeLock(ss);
-    ssl_GetSSL3HandshakeLock(ss);
-
-    *vrange = ss->vrange;
-
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    ssl_Release1stHandshakeLock(ss);
-
-    return SECSuccess;
-}
-
-SECStatus
-SSL_VersionRangeSet(PRFileDesc *fd, const SSLVersionRange *vrange)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_VersionRangeSet",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (!ssl3_VersionRangeIsValid(ss->protocolVariant, vrange)) {
-        PORT_SetError(SSL_ERROR_INVALID_VERSION_RANGE);
-        return SECFailure;
-    }
-
-    ssl_Get1stHandshakeLock(ss);
-    ssl_GetSSL3HandshakeLock(ss);
-
-    if (ss->ssl3.downgradeCheckVersion &&
-        ss->vrange.max > ss->ssl3.downgradeCheckVersion) {
-        PORT_SetError(SSL_ERROR_INVALID_VERSION_RANGE);
-        ssl_ReleaseSSL3HandshakeLock(ss);
-        ssl_Release1stHandshakeLock(ss);
-        return SECFailure;
-    }
-
-    ss->vrange = *vrange;
-
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    ssl_Release1stHandshakeLock(ss);
-
-    return SECSuccess;
-}
-
-SECStatus
-SSL_SetDowngradeCheckVersion(PRFileDesc *fd, PRUint16 version)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-    SECStatus rv = SECFailure;
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetDowngradeCheckVersion",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (version && !ssl3_VersionIsSupported(ss->protocolVariant, version)) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    ssl_Get1stHandshakeLock(ss);
-    ssl_GetSSL3HandshakeLock(ss);
-
-    if (version && version < ss->vrange.max) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        goto loser;
-    }
-    ss->ssl3.downgradeCheckVersion = version;
-    rv = SECSuccess;
-
-loser:
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    ssl_Release1stHandshakeLock(ss);
-
-    return rv;
-}
-
-const SECItemArray *
-SSL_PeerStapledOCSPResponses(PRFileDesc *fd)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_PeerStapledOCSPResponses",
-                 SSL_GETPID(), fd));
-        return NULL;
-    }
-
-    if (!ss->sec.ci.sid) {
-        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
-        return NULL;
-    }
-
-    return &ss->sec.ci.sid->peerCertStatus;
-}
-
-SECStatus
-SSL_HandshakeResumedSession(PRFileDesc *fd, PRBool *handshake_resumed)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_HandshakeResumedSession",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    *handshake_resumed = ss->ssl3.hs.isResuming;
-    return SECSuccess;
-}
-
-const SECItem *
-SSL_GetRequestedClientCertificateTypes(PRFileDesc *fd)
-{
-    sslSocket *ss = ssl_FindSocket(fd);
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in "
-                 "SSL_GetRequestedClientCertificateTypes",
-                 SSL_GETPID(), fd));
-        return NULL;
-    }
-
-    return ss->requestedCertTypes;
-}
-
-/************************************************************************/
-/* The following functions are the TOP LEVEL SSL functions.
-** They all get called through the NSPRIOMethods table below.
-*/
-
-static PRFileDesc *PR_CALLBACK
-ssl_Accept(PRFileDesc *fd, PRNetAddr *sockaddr, PRIntervalTime timeout)
-{
-    sslSocket *ss;
-    sslSocket *ns = NULL;
-    PRFileDesc *newfd = NULL;
-    PRFileDesc *osfd;
-    PRStatus status;
-
-    ss = ssl_GetPrivate(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in accept", SSL_GETPID(), fd));
-        return NULL;
-    }
-
-    /* IF this is a listen socket, there shouldn't be any I/O going on */
-    SSL_LOCK_READER(ss);
-    SSL_LOCK_WRITER(ss);
-    ssl_Get1stHandshakeLock(ss);
-    ssl_GetSSL3HandshakeLock(ss);
-
-    ss->cTimeout = timeout;
-
-    osfd = ss->fd->lower;
-
-    /* First accept connection */
-    newfd = osfd->methods->accept(osfd, sockaddr, timeout);
-    if (newfd == NULL) {
-        SSL_DBG(("%d: SSL[%d]: accept failed, errno=%d",
-                 SSL_GETPID(), ss->fd, PORT_GetError()));
-    } else {
-        /* Create ssl module */
-        ns = ssl_DupSocket(ss);
-    }
-
-    ssl_ReleaseSSL3HandshakeLock(ss);
-    ssl_Release1stHandshakeLock(ss);
-    SSL_UNLOCK_WRITER(ss);
-    SSL_UNLOCK_READER(ss); /* ss isn't used below here. */
-
-    if (ns == NULL)
-        goto loser;
-
-    /* push ssl module onto the new socket */
-    status = ssl_PushIOLayer(ns, newfd, PR_TOP_IO_LAYER);
-    if (status != PR_SUCCESS)
-        goto loser;
-
-    /* Now start server connection handshake with client.
-    ** Don't need locks here because nobody else has a reference to ns yet.
-    */
-    if (ns->opt.useSecurity) {
-        if (ns->opt.handshakeAsClient) {
-            ns->handshake = ssl2_BeginClientHandshake;
-            ss->handshaking = sslHandshakingAsClient;
-        } else {
-            ns->handshake = ssl2_BeginServerHandshake;
-            ss->handshaking = sslHandshakingAsServer;
-        }
-    }
-    ns->TCPconnected = 1;
-    return newfd;
-
-loser:
-    if (ns != NULL)
-        ssl_FreeSocket(ns);
-    if (newfd != NULL)
-        PR_Close(newfd);
-    return NULL;
-}
-
-static PRStatus PR_CALLBACK
-ssl_Connect(PRFileDesc *fd, const PRNetAddr *sockaddr, PRIntervalTime timeout)
-{
-    sslSocket *ss;
-    PRStatus rv;
-
-    ss = ssl_GetPrivate(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in connect", SSL_GETPID(), fd));
-        return PR_FAILURE;
-    }
-
-    /* IF this is a listen socket, there shouldn't be any I/O going on */
-    SSL_LOCK_READER(ss);
-    SSL_LOCK_WRITER(ss);
-
-    ss->cTimeout = timeout;
-    rv = (PRStatus)(*ss->ops->connect)(ss, sockaddr);
-
-    SSL_UNLOCK_WRITER(ss);
-    SSL_UNLOCK_READER(ss);
-
-    return rv;
-}
-
-static PRStatus PR_CALLBACK
-ssl_Bind(PRFileDesc *fd, const PRNetAddr *addr)
-{
-    sslSocket *ss = ssl_GetPrivate(fd);
-    PRStatus rv;
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in bind", SSL_GETPID(), fd));
-        return PR_FAILURE;
-    }
-    SSL_LOCK_READER(ss);
-    SSL_LOCK_WRITER(ss);
-
-    rv = (PRStatus)(*ss->ops->bind)(ss, addr);
-
-    SSL_UNLOCK_WRITER(ss);
-    SSL_UNLOCK_READER(ss);
-    return rv;
-}
-
-static PRStatus PR_CALLBACK
-ssl_Listen(PRFileDesc *fd, PRIntn backlog)
-{
-    sslSocket *ss = ssl_GetPrivate(fd);
-    PRStatus rv;
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in listen", SSL_GETPID(), fd));
-        return PR_FAILURE;
-    }
-    SSL_LOCK_READER(ss);
-    SSL_LOCK_WRITER(ss);
-
-    rv = (PRStatus)(*ss->ops->listen)(ss, backlog);
-
-    SSL_UNLOCK_WRITER(ss);
-    SSL_UNLOCK_READER(ss);
-    return rv;
-}
-
-static PRStatus PR_CALLBACK
-ssl_Shutdown(PRFileDesc *fd, PRIntn how)
-{
-    sslSocket *ss = ssl_GetPrivate(fd);
-    PRStatus rv;
-
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in shutdown", SSL_GETPID(), fd));
-        return PR_FAILURE;
-    }
-    if (how == PR_SHUTDOWN_RCV || how == PR_SHUTDOWN_BOTH) {
-        SSL_LOCK_READER(ss);
-    }
-    if (how == PR_SHUTDOWN_SEND || how == PR_SHUTDOWN_BOTH) {
-        SSL_LOCK_WRITER(ss);
-    }
-
-    rv = (PRStatus)(*ss->ops->shutdown)(ss, how);
-
-    if (how == PR_SHUTDOWN_SEND || how == PR_SHUTDOWN_BOTH) {
-        SSL_UNLOCK_WRITER(ss);
-    }
-    if (how == PR_SHUTDOWN_RCV || how == PR_SHUTDOWN_BOTH) {
-        SSL_UNLOCK_READER(ss);
-    }
-    return rv;
-}
-
-static PRStatus PR_CALLBACK
-ssl_Close(PRFileDesc *fd)
-{
-    sslSocket *ss;
-    PRStatus rv;
-
-    ss = ssl_GetPrivate(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in close", SSL_GETPID(), fd));
-        return PR_FAILURE;
-    }
-
-    /* There must not be any I/O going on */
-    SSL_LOCK_READER(ss);
-    SSL_LOCK_WRITER(ss);
-
-    /* By the time this function returns,
-    ** ss is an invalid pointer, and the locks to which it points have
-    ** been unlocked and freed.  So, this is the ONE PLACE in all of SSL
-    ** where the LOCK calls and the corresponding UNLOCK calls are not in
-    ** the same function scope.  The unlock calls are in ssl_FreeSocket().
-    */
-    rv = (PRStatus)(*ss->ops->close)(ss);
-
-    return rv;
-}
-
-static int PR_CALLBACK
-ssl_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,
-         PRIntervalTime timeout)
-{
-    sslSocket *ss;
-    int rv;
-
-    ss = ssl_GetPrivate(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in recv", SSL_GETPID(), fd));
-        return SECFailure;
-    }
-    SSL_LOCK_READER(ss);
-    ss->rTimeout = timeout;
-    if (!ss->opt.fdx)
-        ss->wTimeout = timeout;
-    rv = (*ss->ops->recv)(ss, (unsigned char *)buf, len, flags);
-    SSL_UNLOCK_READER(ss);
-    return rv;
-}
-
-static int PR_CALLBACK
-ssl_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags,
-         PRIntervalTime timeout)
-{
-    sslSocket *ss;
-    int rv;
-
-    ss = ssl_GetPrivate(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in send", SSL_GETPID(), fd));
-        return SECFailure;
-    }
-    SSL_LOCK_WRITER(ss);
-    ss->wTimeout = timeout;
-    if (!ss->opt.fdx)
-        ss->rTimeout = timeout;
-    rv = (*ss->ops->send)(ss, (const unsigned char *)buf, len, flags);
-    SSL_UNLOCK_WRITER(ss);
-    return rv;
-}
-
-static int PR_CALLBACK
-ssl_Read(PRFileDesc *fd, void *buf, PRInt32 len)
-{
-    sslSocket *ss;
-    int rv;
-
-    ss = ssl_GetPrivate(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in read", SSL_GETPID(), fd));
-        return SECFailure;
-    }
-    SSL_LOCK_READER(ss);
-    ss->rTimeout = PR_INTERVAL_NO_TIMEOUT;
-    if (!ss->opt.fdx)
-        ss->wTimeout = PR_INTERVAL_NO_TIMEOUT;
-    rv = (*ss->ops->read)(ss, (unsigned char *)buf, len);
-    SSL_UNLOCK_READER(ss);
-    return rv;
-}
-
-static int PR_CALLBACK
-ssl_Write(PRFileDesc *fd, const void *buf, PRInt32 len)
-{
-    sslSocket *ss;
-    int rv;
-
-    ss = ssl_GetPrivate(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in write", SSL_GETPID(), fd));
-        return SECFailure;
-    }
-    SSL_LOCK_WRITER(ss);
-    ss->wTimeout = PR_INTERVAL_NO_TIMEOUT;
-    if (!ss->opt.fdx)
-        ss->rTimeout = PR_INTERVAL_NO_TIMEOUT;
-    rv = (*ss->ops->write)(ss, (const unsigned char *)buf, len);
-    SSL_UNLOCK_WRITER(ss);
-    return rv;
-}
-
-static PRStatus PR_CALLBACK
-ssl_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
-{
-    sslSocket *ss;
-
-    ss = ssl_GetPrivate(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in getpeername", SSL_GETPID(), fd));
-        return PR_FAILURE;
-    }
-    return (PRStatus)(*ss->ops->getpeername)(ss, addr);
-}
-
-/*
-*/
-SECStatus
-ssl_GetPeerInfo(sslSocket *ss)
-{
-    PRFileDesc *osfd;
-    int rv;
-    PRNetAddr sin;
-
-    osfd = ss->fd->lower;
-
-    PORT_Memset(&sin, 0, sizeof(sin));
-    rv = osfd->methods->getpeername(osfd, &sin);
-    if (rv < 0) {
-        return SECFailure;
-    }
-    ss->TCPconnected = 1;
-    if (sin.inet.family == PR_AF_INET) {
-        PR_ConvertIPv4AddrToIPv6(sin.inet.ip, &ss->sec.ci.peer);
-        ss->sec.ci.port = sin.inet.port;
-    } else if (sin.ipv6.family == PR_AF_INET6) {
-        ss->sec.ci.peer = sin.ipv6.ip;
-        ss->sec.ci.port = sin.ipv6.port;
-    } else {
-        PORT_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR);
-        return SECFailure;
-    }
-    return SECSuccess;
-}
-
-static PRStatus PR_CALLBACK
-ssl_GetSockName(PRFileDesc *fd, PRNetAddr *name)
-{
-    sslSocket *ss;
-
-    ss = ssl_GetPrivate(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in getsockname", SSL_GETPID(), fd));
-        return PR_FAILURE;
-    }
-    return (PRStatus)(*ss->ops->getsockname)(ss, name);
-}
-
-SECStatus
-SSL_SetStapledOCSPResponses(PRFileDesc *fd, const SECItemArray *responses,
-                            SSLKEAType kea)
-{
-    sslSocket *ss;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetStapledOCSPResponses",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (kea <= 0 || kea >= kt_kea_size) {
-        SSL_DBG(("%d: SSL[%d]: invalid key type in SSL_SetStapledOCSPResponses",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (ss->certStatusArray[kea]) {
-        SECITEM_FreeArray(ss->certStatusArray[kea], PR_TRUE);
-        ss->certStatusArray[kea] = NULL;
-    }
-    if (responses) {
-        ss->certStatusArray[kea] = SECITEM_DupArray(NULL, responses);
-    }
-    return (ss->certStatusArray[kea] || !responses) ? SECSuccess : SECFailure;
-}
-
-SECStatus
-SSL_SetSignedCertTimestamps(PRFileDesc *fd, const SECItem *scts, SSLKEAType kea)
-{
-    sslSocket *ss;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetSignedCertTimestamps",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (kea <= 0 || kea >= kt_kea_size) {
-        SSL_DBG(("%d: SSL[%d]: invalid key type in SSL_SetSignedCertTimestamps",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (ss->signedCertTimestamps[kea].data) {
-        SECITEM_FreeItem(&ss->signedCertTimestamps[kea], PR_FALSE);
-    }
-
-    if (!scts) {
-        return SECSuccess;
-    }
-
-    return SECITEM_CopyItem(NULL, &ss->signedCertTimestamps[kea], scts);
-}
-
-SECStatus
-SSL_SetSockPeerID(PRFileDesc *fd, const char *peerID)
-{
-    sslSocket *ss;
-
-    ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetSockPeerID",
-                 SSL_GETPID(), fd));
-        return SECFailure;
-    }
-
-    if (ss->peerID) {
-        PORT_Free(ss->peerID);
-        ss->peerID = NULL;
-    }
-    if (peerID)
-        ss->peerID = PORT_Strdup(peerID);
-    return (ss->peerID || !peerID) ? SECSuccess : SECFailure;
-}
-
-#define PR_POLL_RW (PR_POLL_WRITE | PR_POLL_READ)
-
-static PRInt16 PR_CALLBACK
-ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_flags)
-{
-    sslSocket *ss;
-    PRInt16 new_flags = how_flags; /* should select on these flags. */
-    PRNetAddr addr;
-
-    *p_out_flags = 0;
-    ss = ssl_GetPrivate(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_Poll",
-                 SSL_GETPID(), fd));
-        return 0; /* don't poll on this socket */
-    }
-
-    if (ss->opt.useSecurity &&
-        ss->handshaking != sslHandshakingUndetermined &&
-        !ss->firstHsDone &&
-        (how_flags & PR_POLL_RW)) {
-        if (!ss->TCPconnected) {
-            ss->TCPconnected = (PR_SUCCESS == ssl_DefGetpeername(ss, &addr));
-        }
-        /* If it's not connected, then presumably the application is polling
-        ** on read or write appropriately, so don't change it.
-        */
-        if (ss->TCPconnected) {
-            if (!ss->handshakeBegun) {
-                /* If the handshake has not begun, poll on read or write
-                ** based on the local application's role in the handshake,
-                ** not based on what the application requested.
-                */
-                new_flags &= ~PR_POLL_RW;
-                if (ss->handshaking == sslHandshakingAsClient) {
-                    new_flags |= PR_POLL_WRITE;
-                } else { /* handshaking as server */
-                    new_flags |= PR_POLL_READ;
-                }
-            } else
-                /* First handshake is in progress */
-                if (ss->lastWriteBlocked) {
-                if (new_flags & PR_POLL_READ) {
-                    /* The caller is waiting for data to be received,
-                    ** but the initial handshake is blocked on write, or the
-                    ** client's first handshake record has not been written.
-                    ** The code should select on write, not read.
-                    */
-                    new_flags ^= PR_POLL_READ;  /* don't select on read. */
-                    new_flags |= PR_POLL_WRITE; /* do    select on write. */
-                }
-            } else if (new_flags & PR_POLL_WRITE) {
-                /* The caller is trying to write, but the handshake is
-                ** blocked waiting for data to read, and the first
-                ** handshake has been sent.  So do NOT to poll on write
-                ** unless we did false start.
-                */
-                if (!(ss->version >= SSL_LIBRARY_VERSION_3_0 &&
-                      ss->ssl3.hs.canFalseStart)) {
-                    new_flags ^= PR_POLL_WRITE; /* don't select on write. */
-                }
-                new_flags |= PR_POLL_READ; /* do    select on read. */
-            }
-        }
-    } else if ((new_flags & PR_POLL_READ) && (SSL_DataPending(fd) > 0)) {
-        *p_out_flags = PR_POLL_READ; /* it's ready already. */
-        return new_flags;
-    } else if ((ss->lastWriteBlocked) && (how_flags & PR_POLL_READ) &&
-               (ss->pendingBuf.len != 0)) { /* write data waiting to be sent */
-        new_flags |= PR_POLL_WRITE;         /* also select on write. */
-    }
-
-    if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
-        ss->ssl3.hs.restartTarget != NULL) {
-        /* Read and write will block until the asynchronous callback completes
-         * (e.g. until SSL_AuthCertificateComplete is called), so don't tell
-         * the caller to poll the socket unless there is pending write data.
-         */
-        if (ss->lastWriteBlocked && ss->pendingBuf.len != 0) {
-            /* Ignore any newly-received data on the socket, but do wait for
-             * the socket to become writable again. Here, it is OK for an error
-             * to be detected, because our logic for sending pending write data
-             * will allow us to report the error to the caller without the risk
-             * of the application spinning.
-             */
-            new_flags &= (PR_POLL_WRITE | PR_POLL_EXCEPT);
-        } else {
-            /* Unfortunately, clearing new_flags will make it impossible for
-             * the application to detect errors that it would otherwise be
-             * able to detect with PR_POLL_EXCEPT, until the asynchronous
-             * callback completes. However, we must clear all the flags to
-             * prevent the application from spinning (alternating between
-             * calling PR_Poll that would return PR_POLL_EXCEPT, and send/recv
-             * which won't actually report the I/O error while we are waiting
-             * for the asynchronous callback to complete).
-             */
-            new_flags = 0;
-        }
-    }
-
-    if (new_flags && (fd->lower->methods->poll != NULL)) {
-        PRInt16 lower_out_flags = 0;
-        PRInt16 lower_new_flags;
-        lower_new_flags = fd->lower->methods->poll(fd->lower, new_flags,
-                                                   &lower_out_flags);
-        if ((lower_new_flags & lower_out_flags) && (how_flags != new_flags)) {
-            PRInt16 out_flags = lower_out_flags & ~PR_POLL_RW;
-            if (lower_out_flags & PR_POLL_READ)
-                out_flags |= PR_POLL_WRITE;
-            if (lower_out_flags & PR_POLL_WRITE)
-                out_flags |= PR_POLL_READ;
-            *p_out_flags = out_flags;
-            new_flags = how_flags;
-        } else {
-            *p_out_flags = lower_out_flags;
-            new_flags = lower_new_flags;
-        }
-    }
-
-    return new_flags;
-}
-
-static PRInt32 PR_CALLBACK
-ssl_TransmitFile(PRFileDesc *sd, PRFileDesc *fd,
-                 const void *headers, PRInt32 hlen,
-                 PRTransmitFileFlags flags, PRIntervalTime timeout)
-{
-    PRSendFileData sfd;
-
-    sfd.fd = fd;
-    sfd.file_offset = 0;
-    sfd.file_nbytes = 0;
-    sfd.header = headers;
-    sfd.hlen = hlen;
-    sfd.trailer = NULL;
-    sfd.tlen = 0;
-
-    return sd->methods->sendfile(sd, &sfd, flags, timeout);
-}
-
-PRBool
-ssl_FdIsBlocking(PRFileDesc *fd)
-{
-    PRSocketOptionData opt;
-    PRStatus status;
-
-    opt.option = PR_SockOpt_Nonblocking;
-    opt.value.non_blocking = PR_FALSE;
-    status = PR_GetSocketOption(fd, &opt);
-    if (status != PR_SUCCESS)
-        return PR_FALSE;
-    return (PRBool)!opt.value.non_blocking;
-}
-
-PRBool
-ssl_SocketIsBlocking(sslSocket *ss)
-{
-    return ssl_FdIsBlocking(ss->fd);
-}
-
-PRInt32 sslFirstBufSize = 8 * 1024;
-PRInt32 sslCopyLimit = 1024;
-
-static PRInt32 PR_CALLBACK
-ssl_WriteV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 vectors,
-           PRIntervalTime timeout)
-{
-    PRInt32 i;
-    PRInt32 bufLen;
-    PRInt32 left;
-    PRInt32 rv;
-    PRInt32 sent = 0;
-    const PRInt32 first_len = sslFirstBufSize;
-    const PRInt32 limit = sslCopyLimit;
-    PRBool blocking;
-    PRIOVec myIov = { 0, 0 };
-    char buf[MAX_FRAGMENT_LENGTH];
-
-    if (vectors < 0) {
-        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-        return -1;
-    }
-    if (vectors > PR_MAX_IOVECTOR_SIZE) {
-        PORT_SetError(PR_BUFFER_OVERFLOW_ERROR);
-        return -1;
-    }
-    for (i = 0; i < vectors; i++) {
-        if (iov[i].iov_len < 0) {
-            PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-            return -1;
-        }
-    }
-    blocking = ssl_FdIsBlocking(fd);
-
-#define K16 sizeof(buf)
-#define KILL_VECTORS                   \
-    while (vectors && !iov->iov_len) { \
-        ++iov;                         \
-        --vectors;                     \
-    }
-#define GET_VECTOR      \
-    do {                \
-        myIov = *iov++; \
-        --vectors;      \
-        KILL_VECTORS    \
-    } while (0)
-#define HANDLE_ERR(rv, len)                                    \
-    if (rv != len) {                                           \
-        if (rv < 0) {                                          \
-            if (!blocking &&                                   \
-                (PR_GetError() == PR_WOULD_BLOCK_ERROR) &&     \
-                (sent > 0)) {                                  \
-                return sent;                                   \
-            } else {                                           \
-                return -1;                                     \
-            }                                                  \
-        }                                                      \
-        /* Only a nonblocking socket can have partial sends */ \
-        PR_ASSERT(!blocking);                                  \
-        return sent + rv;                                      \
-    }
-#define SEND(bfr, len)                           \
-    do {                                         \
-        rv = ssl_Send(fd, bfr, len, 0, timeout); \
-        HANDLE_ERR(rv, len)                      \
-        sent += len;                             \
-    } while (0)
-
-    /* Make sure the first write is at least 8 KB, if possible. */
-    KILL_VECTORS
-    if (!vectors)
-        return ssl_Send(fd, 0, 0, 0, timeout);
-    GET_VECTOR;
-    if (!vectors) {
-        return ssl_Send(fd, myIov.iov_base, myIov.iov_len, 0, timeout);
-    }
-    if (myIov.iov_len < first_len) {
-        PORT_Memcpy(buf, myIov.iov_base, myIov.iov_len);
-        bufLen = myIov.iov_len;
-        left = first_len - bufLen;
-        while (vectors && left) {
-            int toCopy;
-            GET_VECTOR;
-            toCopy = PR_MIN(left, myIov.iov_len);
-            PORT_Memcpy(buf + bufLen, myIov.iov_base, toCopy);
-            bufLen += toCopy;
-            left -= toCopy;
-            myIov.iov_base += toCopy;
-            myIov.iov_len -= toCopy;
-        }
-        SEND(buf, bufLen);
-    }
-
-    while (vectors || myIov.iov_len) {
-        PRInt32 addLen;
-        if (!myIov.iov_len) {
-            GET_VECTOR;
-        }
-        while (myIov.iov_len >= K16) {
-            SEND(myIov.iov_base, K16);
-            myIov.iov_base += K16;
-            myIov.iov_len -= K16;
-        }
-        if (!myIov.iov_len)
-            continue;
-
-        if (!vectors || myIov.iov_len > limit) {
-            addLen = 0;
-        } else if ((addLen = iov->iov_len % K16) + myIov.iov_len <= limit) {
-            /* Addlen is already computed. */;
-        } else if (vectors > 1 &&
-                   iov[1].iov_len % K16 + addLen + myIov.iov_len <= 2 * limit) {
-            addLen = limit - myIov.iov_len;
-        } else
-            addLen = 0;
-
-        if (!addLen) {
-            SEND(myIov.iov_base, myIov.iov_len);
-            myIov.iov_len = 0;
-            continue;
-        }
-        PORT_Memcpy(buf, myIov.iov_base, myIov.iov_len);
-        bufLen = myIov.iov_len;
-        do {
-            GET_VECTOR;
-            PORT_Memcpy(buf + bufLen, myIov.iov_base, addLen);
-            myIov.iov_base += addLen;
-            myIov.iov_len -= addLen;
-            bufLen += addLen;
-
-            left = PR_MIN(limit, K16 - bufLen);
-            if (!vectors             /* no more left */
-                || myIov.iov_len > 0 /* we didn't use that one all up */
-                || bufLen >= K16 /* it's full. */) {
-                addLen = 0;
-            } else if ((addLen = iov->iov_len % K16) <= left) {
-                /* Addlen is already computed. */;
-            } else if (vectors > 1 &&
-                       iov[1].iov_len % K16 + addLen <= left + limit) {
-                addLen = left;
-            } else
-                addLen = 0;
-
-        } while (addLen);
-        SEND(buf, bufLen);
-    }
-    return sent;
-}
-
-/*
- * These functions aren't implemented.
- */
-
-static PRInt32 PR_CALLBACK
-ssl_Available(PRFileDesc *fd)
-{
-    PORT_Assert(0);
-    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
-    return SECFailure;
-}
-
-static PRInt64 PR_CALLBACK
-ssl_Available64(PRFileDesc *fd)
-{
-    PRInt64 res;
-
-    PORT_Assert(0);
-    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
-    LL_I2L(res, -1L);
-    return res;
-}
-
-static PRStatus PR_CALLBACK
-ssl_FSync(PRFileDesc *fd)
-{
-    PORT_Assert(0);
-    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
-    return PR_FAILURE;
-}
-
-static PRInt32 PR_CALLBACK
-ssl_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence how)
-{
-    PORT_Assert(0);
-    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
-    return SECFailure;
-}
-
-static PRInt64 PR_CALLBACK
-ssl_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence how)
-{
-    PRInt64 res;
-
-    PORT_Assert(0);
-    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
-    LL_I2L(res, -1L);
-    return res;
-}
-
-static PRStatus PR_CALLBACK
-ssl_FileInfo(PRFileDesc *fd, PRFileInfo *info)
-{
-    PORT_Assert(0);
-    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
-    return PR_FAILURE;
-}
-
-static PRStatus PR_CALLBACK
-ssl_FileInfo64(PRFileDesc *fd, PRFileInfo64 *info)
-{
-    PORT_Assert(0);
-    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
-    return PR_FAILURE;
-}
-
-static PRInt32 PR_CALLBACK
-ssl_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
-             PRNetAddr *addr, PRIntervalTime timeout)
-{
-    PORT_Assert(0);
-    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
-    return SECFailure;
-}
-
-static PRInt32 PR_CALLBACK
-ssl_SendTo(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
-           const PRNetAddr *addr, PRIntervalTime timeout)
-{
-    PORT_Assert(0);
-    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
-    return SECFailure;
-}
-
-static const PRIOMethods ssl_methods = {
-    PR_DESC_LAYERED,
-    ssl_Close,            /* close        */
-    ssl_Read,             /* read         */
-    ssl_Write,            /* write        */
-    ssl_Available,        /* available    */
-    ssl_Available64,      /* available64  */
-    ssl_FSync,            /* fsync        */
-    ssl_Seek,             /* seek         */
-    ssl_Seek64,           /* seek64       */
-    ssl_FileInfo,         /* fileInfo     */
-    ssl_FileInfo64,       /* fileInfo64   */
-    ssl_WriteV,           /* writev       */
-    ssl_Connect,          /* connect      */
-    ssl_Accept,           /* accept       */
-    ssl_Bind,             /* bind         */
-    ssl_Listen,           /* listen       */
-    ssl_Shutdown,         /* shutdown     */
-    ssl_Recv,             /* recv         */
-    ssl_Send,             /* send         */
-    ssl_RecvFrom,         /* recvfrom     */
-    ssl_SendTo,           /* sendto       */
-    ssl_Poll,             /* poll         */
-    PR_EmulateAcceptRead, /* acceptread   */
-    ssl_TransmitFile,     /* transmitfile */
-    ssl_GetSockName,      /* getsockname  */
-    ssl_GetPeerName,      /* getpeername  */
-    NULL,                 /* getsockopt   OBSOLETE */
-    NULL,                 /* setsockopt   OBSOLETE */
-    NULL,                 /* getsocketoption   */
-    NULL,                 /* setsocketoption   */
-    PR_EmulateSendFile,   /* Send a (partial) file with header/trailer*/
-    NULL,                 /* reserved for future use */
-    NULL,                 /* reserved for future use */
-    NULL,                 /* reserved for future use */
-    NULL,                 /* reserved for future use */
-    NULL                  /* reserved for future use */
-};
-
-static PRIOMethods combined_methods;
-
-static void
-ssl_SetupIOMethods(void)
-{
-    PRIOMethods *new_methods = &combined_methods;
-    const PRIOMethods *nspr_methods = PR_GetDefaultIOMethods();
-    const PRIOMethods *my_methods = &ssl_methods;
-
-    *new_methods = *nspr_methods;
-
-    new_methods->file_type = my_methods->file_type;
-    new_methods->close = my_methods->close;
-    new_methods->read = my_methods->read;
-    new_methods->write = my_methods->write;
-    new_methods->available = my_methods->available;
-    new_methods->available64 = my_methods->available64;
-    new_methods->fsync = my_methods->fsync;
-    new_methods->seek = my_methods->seek;
-    new_methods->seek64 = my_methods->seek64;
-    new_methods->fileInfo = my_methods->fileInfo;
-    new_methods->fileInfo64 = my_methods->fileInfo64;
-    new_methods->writev = my_methods->writev;
-    new_methods->connect = my_methods->connect;
-    new_methods->accept = my_methods->accept;
-    new_methods->bind = my_methods->bind;
-    new_methods->listen = my_methods->listen;
-    new_methods->shutdown = my_methods->shutdown;
-    new_methods->recv = my_methods->recv;
-    new_methods->send = my_methods->send;
-    new_methods->recvfrom = my_methods->recvfrom;
-    new_methods->sendto = my_methods->sendto;
-    new_methods->poll = my_methods->poll;
-    new_methods->acceptread = my_methods->acceptread;
-    new_methods->transmitfile = my_methods->transmitfile;
-    new_methods->getsockname = my_methods->getsockname;
-    new_methods->getpeername = my_methods->getpeername;
-    /*  new_methods->getsocketoption   = my_methods->getsocketoption;       */
-    /*  new_methods->setsocketoption   = my_methods->setsocketoption;       */
-    new_methods->sendfile = my_methods->sendfile;
-}
-
-static PRCallOnceType initIoLayerOnce;
-
-static PRStatus
-ssl_InitIOLayer(void)
-{
-    ssl_layer_id = PR_GetUniqueIdentity("SSL");
-    ssl_SetupIOMethods();
-    ssl_inited = PR_TRUE;
-    return PR_SUCCESS;
-}
-
-static PRStatus
-ssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack, PRDescIdentity id)
-{
-    PRFileDesc *layer = NULL;
-    PRStatus status;
-
-    if (!ssl_inited) {
-        status = PR_CallOnce(&initIoLayerOnce, &ssl_InitIOLayer);
-        if (status != PR_SUCCESS)
-            goto loser;
-    }
-
-    if (ns == NULL)
-        goto loser;
-
-    layer = PR_CreateIOLayerStub(ssl_layer_id, &combined_methods);
-    if (layer == NULL)
-        goto loser;
-    layer->secret = (PRFilePrivate *)ns;
-
-    /* Here, "stack" points to the PRFileDesc on the top of the stack.
-    ** "layer" points to a new FD that is to be inserted into the stack.
-    ** If layer is being pushed onto the top of the stack, then
-    ** PR_PushIOLayer switches the contents of stack and layer, and then
-    ** puts stack on top of layer, so that after it is done, the top of
-    ** stack is the same "stack" as it was before, and layer is now the
-    ** FD for the former top of stack.
-    ** After this call, stack always points to the top PRFD on the stack.
-    ** If this function fails, the contents of stack and layer are as
-    ** they were before the call.
-    */
-    status = PR_PushIOLayer(stack, id, layer);
-    if (status != PR_SUCCESS)
-        goto loser;
-
-    ns->fd = (id == PR_TOP_IO_LAYER) ? stack : layer;
-    return PR_SUCCESS;
-
-loser:
-    if (layer) {
-        layer->dtor(layer); /* free layer */
-    }
-    return PR_FAILURE;
-}
-
-/* if this fails, caller must destroy socket. */
-static SECStatus
-ssl_MakeLocks(sslSocket *ss)
-{
-    ss->firstHandshakeLock = PZ_NewMonitor(nssILockSSL);
-    if (!ss->firstHandshakeLock)
-        goto loser;
-    ss->ssl3HandshakeLock = PZ_NewMonitor(nssILockSSL);
-    if (!ss->ssl3HandshakeLock)
-        goto loser;
-    ss->specLock = NSSRWLock_New(SSL_LOCK_RANK_SPEC, NULL);
-    if (!ss->specLock)
-        goto loser;
-    ss->recvBufLock = PZ_NewMonitor(nssILockSSL);
-    if (!ss->recvBufLock)
-        goto loser;
-    ss->xmitBufLock = PZ_NewMonitor(nssILockSSL);
-    if (!ss->xmitBufLock)
-        goto loser;
-    ss->writerThread = NULL;
-    if (ssl_lock_readers) {
-        ss->recvLock = PZ_NewLock(nssILockSSL);
-        if (!ss->recvLock)
-            goto loser;
-        ss->sendLock = PZ_NewLock(nssILockSSL);
-        if (!ss->sendLock)
-            goto loser;
-    }
-    return SECSuccess;
-loser:
-    ssl_DestroyLocks(ss);
-    return SECFailure;
-}
-
-#if defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_BEOS)
-#define NSS_HAVE_GETENV 1
-#endif
-
-#define LOWER(x) (x | 0x20) /* cheap ToLower function ignores LOCALE */
-
-static void
-ssl_SetDefaultsFromEnvironment(void)
-{
-#if defined(NSS_HAVE_GETENV)
-    static int firsttime = 1;
-
-    if (firsttime) {
-        char *ev;
-        firsttime = 0;
-#ifdef DEBUG
-        ev = PR_GetEnvSecure("SSLDEBUGFILE");
-        if (ev && ev[0]) {
-            ssl_trace_iob = fopen(ev, "w");
-        }
-        if (!ssl_trace_iob) {
-            ssl_trace_iob = stderr;
-        }
-#ifdef TRACE
-        ev = PR_GetEnvSecure("SSLTRACE");
-        if (ev && ev[0]) {
-            ssl_trace = atoi(ev);
-            SSL_TRACE(("SSL: tracing set to %d", ssl_trace));
-        }
-#endif /* TRACE */
-        ev = PR_GetEnvSecure("SSLDEBUG");
-        if (ev && ev[0]) {
-            ssl_debug = atoi(ev);
-            SSL_TRACE(("SSL: debugging set to %d", ssl_debug));
-        }
-#endif /* DEBUG */
-        ev = PR_GetEnvSecure("SSLKEYLOGFILE");
-        if (ev && ev[0]) {
-            ssl_keylog_iob = fopen(ev, "a");
-            if (!ssl_keylog_iob) {
-                SSL_TRACE(("SSL: failed to open key log file"));
-            } else {
-                if (ftell(ssl_keylog_iob) == 0) {
-                    fputs("# SSL/TLS secrets log file, generated by NSS\n",
-                          ssl_keylog_iob);
-                }
-                SSL_TRACE(("SSL: logging SSL/TLS secrets to %s", ev));
-            }
-        }
-#ifndef NO_PKCS11_BYPASS
-        ev = PR_GetEnvSecure("SSLBYPASS");
-        if (ev && ev[0]) {
-            ssl_defaults.bypassPKCS11 = (ev[0] == '1');
-            SSL_TRACE(("SSL: bypass default set to %d",
-                       ssl_defaults.bypassPKCS11));
-        }
-#endif /* NO_PKCS11_BYPASS */
-        ev = PR_GetEnvSecure("SSLFORCELOCKS");
-        if (ev && ev[0] == '1') {
-            ssl_force_locks = PR_TRUE;
-            ssl_defaults.noLocks = 0;
-            strcpy(lockStatus + LOCKSTATUS_OFFSET, "FORCED.  ");
-            SSL_TRACE(("SSL: force_locks set to %d", ssl_force_locks));
-        }
-        ev = PR_GetEnvSecure("NSS_SSL_ENABLE_RENEGOTIATION");
-        if (ev) {
-            if (ev[0] == '1' || LOWER(ev[0]) == 'u')
-                ssl_defaults.enableRenegotiation = SSL_RENEGOTIATE_UNRESTRICTED;
-            else if (ev[0] == '0' || LOWER(ev[0]) == 'n')
-                ssl_defaults.enableRenegotiation = SSL_RENEGOTIATE_NEVER;
-            else if (ev[0] == '2' || LOWER(ev[0]) == 'r')
-                ssl_defaults.enableRenegotiation = SSL_RENEGOTIATE_REQUIRES_XTN;
-            else if (ev[0] == '3' || LOWER(ev[0]) == 't')
-                ssl_defaults.enableRenegotiation = SSL_RENEGOTIATE_TRANSITIONAL;
-            SSL_TRACE(("SSL: enableRenegotiation set to %d",
-                       ssl_defaults.enableRenegotiation));
-        }
-        ev = PR_GetEnvSecure("NSS_SSL_REQUIRE_SAFE_NEGOTIATION");
-        if (ev && ev[0] == '1') {
-            ssl_defaults.requireSafeNegotiation = PR_TRUE;
-            SSL_TRACE(("SSL: requireSafeNegotiation set to %d",
-                       PR_TRUE));
-        }
-        ev = PR_GetEnvSecure("NSS_SSL_CBC_RANDOM_IV");
-        if (ev && ev[0] == '0') {
-            ssl_defaults.cbcRandomIV = PR_FALSE;
-            SSL_TRACE(("SSL: cbcRandomIV set to 0"));
-        }
-    }
-#endif /* NSS_HAVE_GETENV */
-}
-
-/*
-** Create a newsocket structure for a file descriptor.
-*/
-static sslSocket *
-ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
-{
-    sslSocket *ss;
-
-    ssl_SetDefaultsFromEnvironment();
-
-    if (ssl_force_locks)
-        makeLocks = PR_TRUE;
-
-    /* Make a new socket and get it ready */
-    ss = (sslSocket *)PORT_ZAlloc(sizeof(sslSocket));
-    if (ss) {
-        /* This should be of type SSLKEAType, but CC on IRIX
-         * complains during the for loop.
-         */
-        int i;
-        SECStatus status;
-
-        ss->opt = ssl_defaults;
-        ss->opt.useSocks = PR_FALSE;
-        ss->opt.noLocks = !makeLocks;
-        ss->vrange = *VERSIONS_DEFAULTS(protocolVariant);
-        ss->protocolVariant = protocolVariant;
-
-        ss->peerID = NULL;
-        ss->rTimeout = PR_INTERVAL_NO_TIMEOUT;
-        ss->wTimeout = PR_INTERVAL_NO_TIMEOUT;
-        ss->cTimeout = PR_INTERVAL_NO_TIMEOUT;
-        ss->cipherSpecs = NULL;
-        ss->sizeCipherSpecs = 0; /* produced lazily */
-        ss->preferredCipher = NULL;
-        ss->url = NULL;
-
-        for (i = kt_null; i < kt_kea_size; i++) {
-            sslServerCerts *sc = ss->serverCerts + i;
-            sc->serverCert = NULL;
-            sc->serverCertChain = NULL;
-            sc->serverKeyPair = NULL;
-            sc->serverKeyBits = 0;
-            ss->certStatusArray[i] = NULL;
-        }
-        ss->requestedCertTypes = NULL;
-        ss->stepDownKeyPair = NULL;
-
-        ss->dheParams = NULL;
-        ss->dheKeyPair = NULL;
-
-        ss->dbHandle = CERT_GetDefaultCertDB();
-
-        /* Provide default implementation of hooks */
-        ss->authCertificate = SSL_AuthCertificate;
-        ss->authCertificateArg = (void *)ss->dbHandle;
-        ss->sniSocketConfig = NULL;
-        ss->sniSocketConfigArg = NULL;
-        ss->getClientAuthData = NULL;
-        ss->handleBadCert = NULL;
-        ss->badCertArg = NULL;
-        ss->pkcs11PinArg = NULL;
-        ss->ephemeralECDHKeyPair = NULL;
-        ss->getChannelID = NULL;
-        ss->getChannelIDArg = NULL;
-
-        ssl_ChooseOps(ss);
-        ssl2_InitSocketPolicy(ss);
-        ssl3_InitSocketPolicy(ss);
-        PR_INIT_CLIST(&ss->ssl3.hs.lastMessageFlight);
-        PR_INIT_CLIST(&ss->ssl3.hs.remoteKeyShares);
-
-        if (makeLocks) {
-            status = ssl_MakeLocks(ss);
-            if (status != SECSuccess)
-                goto loser;
-        }
-        status = ssl_CreateSecurityInfo(ss);
-        if (status != SECSuccess)
-            goto loser;
-        status = ssl_InitGather(&ss->gs);
-        if (status != SECSuccess) {
-        loser:
-            ssl_DestroySocketContents(ss);
-            ssl_DestroyLocks(ss);
-            PORT_Free(ss);
-            ss = NULL;
-        }
-    }
-    return ss;
-}
diff --git a/net/third_party/nss/ssl/sslt.h b/net/third_party/nss/ssl/sslt.h
deleted file mode 100644
index 6f26e5f..0000000
--- a/net/third_party/nss/ssl/sslt.h
+++ /dev/null
@@ -1,269 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file contains prototypes for the public SSL functions.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef __sslt_h_
-#define __sslt_h_
-
-#include "prtypes.h"
-
-typedef struct SSL3StatisticsStr {
-    /* statistics from ssl3_SendClientHello (sch) */
-    long sch_sid_cache_hits;
-    long sch_sid_cache_misses;
-    long sch_sid_cache_not_ok;
-
-    /* statistics from ssl3_HandleServerHello (hsh) */
-    long hsh_sid_cache_hits;
-    long hsh_sid_cache_misses;
-    long hsh_sid_cache_not_ok;
-
-    /* statistics from ssl3_HandleClientHello (hch) */
-    long hch_sid_cache_hits;
-    long hch_sid_cache_misses;
-    long hch_sid_cache_not_ok;
-
-    /* statistics related to stateless resume */
-    long sch_sid_stateless_resumes;
-    long hsh_sid_stateless_resumes;
-    long hch_sid_stateless_resumes;
-    long hch_sid_ticket_parse_failures;
-} SSL3Statistics;
-
-/* Key Exchange algorithm values */
-typedef enum {
-    ssl_kea_null = 0,
-    ssl_kea_rsa = 1,
-    ssl_kea_dh = 2,
-    ssl_kea_fortezza = 3, /* deprecated, now unused */
-    ssl_kea_ecdh = 4,
-    ssl_kea_size /* number of ssl_kea_ algorithms */
-} SSLKEAType;
-
-/* The following defines are for backwards compatibility.
-** They will be removed in a forthcoming release to reduce namespace pollution.
-** programs that use the kt_ symbols should convert to the ssl_kt_ symbols
-** soon.
-*/
-#define kt_null ssl_kea_null
-#define kt_rsa ssl_kea_rsa
-#define kt_dh ssl_kea_dh
-#define kt_fortezza ssl_kea_fortezza /* deprecated, now unused */
-#define kt_ecdh ssl_kea_ecdh
-#define kt_kea_size ssl_kea_size
-
-/* Values of this enum match the SignatureAlgorithm enum from
- * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
-typedef enum {
-    ssl_sign_null = 0, /* "anonymous" in TLS */
-    ssl_sign_rsa = 1,
-    ssl_sign_dsa = 2,
-    ssl_sign_ecdsa = 3
-} SSLSignType;
-
-/* Values of this enum match the HashAlgorithm enum from
- * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
-typedef enum {
-    /* ssl_hash_none is used internally to mean the pre-1.2 combination of MD5
-     * and SHA1. The other values are only used in TLS 1.2. */
-    ssl_hash_none = 0,
-    ssl_hash_md5 = 1,
-    ssl_hash_sha1 = 2,
-    ssl_hash_sha224 = 3,
-    ssl_hash_sha256 = 4,
-    ssl_hash_sha384 = 5,
-    ssl_hash_sha512 = 6
-} SSLHashType;
-
-typedef struct SSLSignatureAndHashAlgStr {
-    SSLHashType hashAlg;
-    SSLSignType sigAlg;
-} SSLSignatureAndHashAlg;
-
-typedef enum {
-    ssl_auth_null = 0,
-    ssl_auth_rsa = 1,
-    ssl_auth_dsa = 2,
-    ssl_auth_kea = 3,
-    ssl_auth_ecdsa = 4
-} SSLAuthType;
-
-typedef enum {
-    ssl_calg_null = 0,
-    ssl_calg_rc4 = 1,
-    ssl_calg_rc2 = 2,
-    ssl_calg_des = 3,
-    ssl_calg_3des = 4,
-    ssl_calg_idea = 5,
-    ssl_calg_fortezza = 6, /* deprecated, now unused */
-    ssl_calg_aes = 7,
-    ssl_calg_camellia = 8,
-    ssl_calg_seed = 9,
-    ssl_calg_aes_gcm = 10,
-    ssl_calg_chacha20 = 11
-} SSLCipherAlgorithm;
-
-typedef enum {
-    ssl_mac_null = 0,
-    ssl_mac_md5 = 1,
-    ssl_mac_sha = 2,
-    ssl_hmac_md5 = 3, /* TLS HMAC version of mac_md5 */
-    ssl_hmac_sha = 4, /* TLS HMAC version of mac_sha */
-    ssl_hmac_sha256 = 5,
-    ssl_mac_aead = 6
-} SSLMACAlgorithm;
-
-typedef enum {
-    ssl_compression_null = 0,
-    ssl_compression_deflate = 1 /* RFC 3749 */
-} SSLCompressionMethod;
-
-typedef struct SSLChannelInfoStr {
-    /* |length| is obsolete. On return, SSL_GetChannelInfo sets |length| to the
-     * smaller of the |len| argument and the length of the struct. The caller
-     * may ignore |length|. */
-    PRUint32 length;
-    PRUint16 protocolVersion;
-    PRUint16 cipherSuite;
-
-    /* server authentication info */
-    PRUint32 authKeyBits;
-
-    /* key exchange algorithm info */
-    PRUint32 keaKeyBits;
-
-    /* session info */
-    PRUint32 creationTime;    /* seconds since Jan 1, 1970 */
-    PRUint32 lastAccessTime;  /* seconds since Jan 1, 1970 */
-    PRUint32 expirationTime;  /* seconds since Jan 1, 1970 */
-    PRUint32 sessionIDLength; /* up to 32 */
-    PRUint8 sessionID[32];
-
-    /* The following fields are added in NSS 3.12.5. */
-
-    /* compression method info */
-    const char* compressionMethodName;
-    SSLCompressionMethod compressionMethod;
-
-    /* The following fields are added in NSS 3.21.
-     * This field only has meaning in TLS < 1.3 and will be set to
-     *  PR_FALSE in TLS 1.3.
-     */
-    PRBool extendedMasterSecretUsed;
-} SSLChannelInfo;
-
-/* Preliminary channel info */
-#define ssl_preinfo_version (1U << 0)
-#define ssl_preinfo_cipher_suite (1U << 1)
-#define ssl_preinfo_all (ssl_preinfo_version | ssl_preinfo_cipher_suite)
-
-typedef struct SSLPreliminaryChannelInfoStr {
-    /* |length| is obsolete. On return, SSL_GetPreliminaryChannelInfo sets
-     * |length| to the smaller of the |len| argument and the length of the
-     * struct. The caller may ignore |length|. */
-    PRUint32 length;
-    /* A bitfield over SSLPreliminaryValueSet that describes which
-     * preliminary values are set (see ssl_preinfo_*). */
-    PRUint32 valuesSet;
-    /* Protocol version: test (valuesSet & ssl_preinfo_version) */
-    PRUint16 protocolVersion;
-    /* Cipher suite: test (valuesSet & ssl_preinfo_cipher_suite) */
-    PRUint16 cipherSuite;
-} SSLPreliminaryChannelInfo;
-
-typedef struct SSLCipherSuiteInfoStr {
-    /* |length| is obsolete. On return, SSL_GetCipherSuitelInfo sets |length|
-     * to the smaller of the |len| argument and the length of the struct. The
-     * caller may ignore |length|. */
-    PRUint16 length;
-    PRUint16 cipherSuite;
-
-    /* Cipher Suite Name */
-    const char* cipherSuiteName;
-
-    /* server authentication info */
-    const char* authAlgorithmName;
-    SSLAuthType authAlgorithm;
-
-    /* key exchange algorithm info */
-    const char* keaTypeName;
-    SSLKEAType keaType;
-
-    /* symmetric encryption info */
-    const char* symCipherName;
-    SSLCipherAlgorithm symCipher;
-    PRUint16 symKeyBits;
-    PRUint16 symKeySpace;
-    PRUint16 effectiveKeyBits;
-
-    /* MAC info */
-    /* AEAD ciphers don't have a MAC. For an AEAD cipher, macAlgorithmName
-     * is "AEAD", macAlgorithm is ssl_mac_aead, and macBits is the length in
-     * bits of the authentication tag. */
-    const char* macAlgorithmName;
-    SSLMACAlgorithm macAlgorithm;
-    PRUint16 macBits;
-
-    PRUintn isFIPS : 1;
-    PRUintn isExportable : 1;
-    PRUintn nonStandard : 1;
-    PRUintn reservedBits : 29;
-
-} SSLCipherSuiteInfo;
-
-typedef enum {
-    ssl_variant_stream = 0,
-    ssl_variant_datagram = 1
-} SSLProtocolVariant;
-
-typedef struct SSLVersionRangeStr {
-    PRUint16 min;
-    PRUint16 max;
-} SSLVersionRange;
-
-typedef enum {
-    SSL_sni_host_name = 0,
-    SSL_sni_type_total
-} SSLSniNameType;
-
-/* Supported extensions. */
-/* Update SSL_MAX_EXTENSIONS whenever a new extension type is added. */
-typedef enum {
-    ssl_server_name_xtn = 0,
-    ssl_cert_status_xtn = 5,
-#ifndef NSS_DISABLE_ECC
-    ssl_elliptic_curves_xtn = 10,
-    ssl_ec_point_formats_xtn = 11,
-#endif
-    ssl_signature_algorithms_xtn = 13,
-    ssl_use_srtp_xtn = 14,
-    ssl_app_layer_protocol_xtn = 16,
-    /* signed_certificate_timestamp extension, RFC 6962 */
-    ssl_signed_cert_timestamp_xtn = 18,
-    ssl_padding_xtn = 21,
-    ssl_extended_master_secret_xtn = 23,
-    ssl_session_ticket_xtn = 35,
-    ssl_tls13_key_share_xtn = 40, /* unofficial TODO(ekr) */
-    ssl_next_proto_nego_xtn = 13172,
-    ssl_channel_id_xtn = 30032,
-    ssl_renegotiation_info_xtn = 0xff01,
-    ssl_tls13_draft_version_xtn = 0xff02 /* experimental number */
-} SSLExtensionType;
-
-#define SSL_MAX_EXTENSIONS 15 /* doesn't include ssl_padding_xtn. */
-
-typedef enum {
-    ssl_dhe_group_none = 0,
-    ssl_ff_dhe_2048_group = 1,
-    ssl_ff_dhe_3072_group = 2,
-    ssl_ff_dhe_4096_group = 3,
-    ssl_ff_dhe_6144_group = 4,
-    ssl_ff_dhe_8192_group = 5,
-    ssl_dhe_group_max
-} SSLDHEGroupType;
-
-#endif /* __sslt_h_ */
diff --git a/net/third_party/nss/ssl/ssltrace.c b/net/third_party/nss/ssl/ssltrace.c
deleted file mode 100644
index 6be9a6d..0000000
--- a/net/third_party/nss/ssl/ssltrace.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Functions to trace SSL protocol behavior in DEBUG builds.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include <stdarg.h>
-#include "cert.h"
-#include "ssl.h"
-#include "sslimpl.h"
-#include "sslproto.h"
-#include "prprf.h"
-
-#if defined(DEBUG) || defined(TRACE)
-static const char *hex = "0123456789abcdef";
-
-static const char printable[257] = {
-    "................"  /* 0x */
-    "................"  /* 1x */
-    " !\"#$%&'()*+,-./" /* 2x */
-    "0123456789:;<=>?"  /* 3x */
-    "@ABCDEFGHIJKLMNO"  /* 4x */
-    "PQRSTUVWXYZ[\\]^_" /* 5x */
-    "`abcdefghijklmno"  /* 6x */
-    "pqrstuvwxyz{|}~."  /* 7x */
-    "................"  /* 8x */
-    "................"  /* 9x */
-    "................"  /* ax */
-    "................"  /* bx */
-    "................"  /* cx */
-    "................"  /* dx */
-    "................"  /* ex */
-    "................"  /* fx */
-};
-
-void
-ssl_PrintBuf(sslSocket *ss, const char *msg, const void *vp, int len)
-{
-    const unsigned char *cp = (const unsigned char *)vp;
-    char buf[80];
-    char *bp;
-    char *ap;
-
-    if (ss) {
-        SSL_TRACE(("%d: SSL[%d]: %s [Len: %d]", SSL_GETPID(), ss->fd,
-                   msg, len));
-    } else {
-        SSL_TRACE(("%d: SSL: %s [Len: %d]", SSL_GETPID(), msg, len));
-    }
-    memset(buf, ' ', sizeof buf);
-    bp = buf;
-    ap = buf + 50;
-    while (--len >= 0) {
-        unsigned char ch = *cp++;
-        *bp++ = hex[(ch >> 4) & 0xf];
-        *bp++ = hex[ch & 0xf];
-        *bp++ = ' ';
-        *ap++ = printable[ch];
-        if (ap - buf >= 66) {
-            *ap = 0;
-            SSL_TRACE(("   %s", buf));
-            memset(buf, ' ', sizeof buf);
-            bp = buf;
-            ap = buf + 50;
-        }
-    }
-    if (bp > buf) {
-        *ap = 0;
-        SSL_TRACE(("   %s", buf));
-    }
-}
-
-#define LEN(cp) (((cp)[0] << 8) | ((cp)[1]))
-
-static void
-PrintType(sslSocket *ss, char *msg)
-{
-    if (ss) {
-        SSL_TRACE(("%d: SSL[%d]: dump-msg: %s", SSL_GETPID(), ss->fd, msg));
-    } else {
-        SSL_TRACE(("%d: SSL: dump-msg: %s", SSL_GETPID(), msg));
-    }
-}
-
-static void
-PrintInt(sslSocket *ss, char *msg, unsigned v)
-{
-    if (ss) {
-        SSL_TRACE(("%d: SSL[%d]:           %s=%u", SSL_GETPID(), ss->fd, msg, v));
-    } else {
-        SSL_TRACE(("%d: SSL:           %s=%u", SSL_GETPID(), msg, v));
-    }
-}
-
-/* PrintBuf is just like ssl_PrintBuf above, except that:
- * a) It prefixes each line of the buffer with "XX: SSL[xxx]           "
- * b) It dumps only hex, not ASCII.
- */
-static void
-PrintBuf(sslSocket *ss, char *msg, unsigned char *cp, int len)
-{
-    char buf[80];
-    char *bp;
-
-    if (ss) {
-        SSL_TRACE(("%d: SSL[%d]:           %s [Len: %d]",
-                   SSL_GETPID(), ss->fd, msg, len));
-    } else {
-        SSL_TRACE(("%d: SSL:           %s [Len: %d]",
-                   SSL_GETPID(), msg, len));
-    }
-    bp = buf;
-    while (--len >= 0) {
-        unsigned char ch = *cp++;
-        *bp++ = hex[(ch >> 4) & 0xf];
-        *bp++ = hex[ch & 0xf];
-        *bp++ = ' ';
-        if (bp + 4 > buf + 50) {
-            *bp = 0;
-            if (ss) {
-                SSL_TRACE(("%d: SSL[%d]:             %s",
-                           SSL_GETPID(), ss->fd, buf));
-            } else {
-                SSL_TRACE(("%d: SSL:             %s", SSL_GETPID(), buf));
-            }
-            bp = buf;
-        }
-    }
-    if (bp > buf) {
-        *bp = 0;
-        if (ss) {
-            SSL_TRACE(("%d: SSL[%d]:             %s",
-                       SSL_GETPID(), ss->fd, buf));
-        } else {
-            SSL_TRACE(("%d: SSL:             %s", SSL_GETPID(), buf));
-        }
-    }
-}
-
-void
-ssl_DumpMsg(sslSocket *ss, unsigned char *bp, unsigned len)
-{
-    switch (bp[0]) {
-        case SSL_MT_ERROR:
-            PrintType(ss, "Error");
-            PrintInt(ss, "error", LEN(bp + 1));
-            break;
-
-        case SSL_MT_CLIENT_HELLO: {
-            unsigned lcs = LEN(bp + 3);
-            unsigned ls = LEN(bp + 5);
-            unsigned lc = LEN(bp + 7);
-
-            PrintType(ss, "Client-Hello");
-
-            PrintInt(ss, "version (Major)", bp[1]);
-            PrintInt(ss, "version (minor)", bp[2]);
-
-            PrintBuf(ss, "cipher-specs", bp + 9, lcs);
-            PrintBuf(ss, "session-id", bp + 9 + lcs, ls);
-            PrintBuf(ss, "challenge", bp + 9 + lcs + ls, lc);
-        } break;
-        case SSL_MT_CLIENT_MASTER_KEY: {
-            unsigned lck = LEN(bp + 4);
-            unsigned lek = LEN(bp + 6);
-            unsigned lka = LEN(bp + 8);
-
-            PrintType(ss, "Client-Master-Key");
-
-            PrintInt(ss, "cipher-choice", bp[1]);
-            PrintInt(ss, "key-length", LEN(bp + 2));
-
-            PrintBuf(ss, "clear-key", bp + 10, lck);
-            PrintBuf(ss, "encrypted-key", bp + 10 + lck, lek);
-            PrintBuf(ss, "key-arg", bp + 10 + lck + lek, lka);
-        } break;
-        case SSL_MT_CLIENT_FINISHED:
-            PrintType(ss, "Client-Finished");
-            PrintBuf(ss, "connection-id", bp + 1, len - 1);
-            break;
-        case SSL_MT_SERVER_HELLO: {
-            unsigned lc = LEN(bp + 5);
-            unsigned lcs = LEN(bp + 7);
-            unsigned lci = LEN(bp + 9);
-
-            PrintType(ss, "Server-Hello");
-
-            PrintInt(ss, "session-id-hit", bp[1]);
-            PrintInt(ss, "certificate-type", bp[2]);
-            PrintInt(ss, "version (Major)", bp[3]);
-            PrintInt(ss, "version (minor)", bp[3]);
-            PrintBuf(ss, "certificate", bp + 11, lc);
-            PrintBuf(ss, "cipher-specs", bp + 11 + lc, lcs);
-            PrintBuf(ss, "connection-id", bp + 11 + lc + lcs, lci);
-        } break;
-        case SSL_MT_SERVER_VERIFY:
-            PrintType(ss, "Server-Verify");
-            PrintBuf(ss, "challenge", bp + 1, len - 1);
-            break;
-        case SSL_MT_SERVER_FINISHED:
-            PrintType(ss, "Server-Finished");
-            PrintBuf(ss, "session-id", bp + 1, len - 1);
-            break;
-        case SSL_MT_REQUEST_CERTIFICATE:
-            PrintType(ss, "Request-Certificate");
-            PrintInt(ss, "authentication-type", bp[1]);
-            PrintBuf(ss, "certificate-challenge", bp + 2, len - 2);
-            break;
-        case SSL_MT_CLIENT_CERTIFICATE: {
-            unsigned lc = LEN(bp + 2);
-            unsigned lr = LEN(bp + 4);
-            PrintType(ss, "Client-Certificate");
-            PrintInt(ss, "certificate-type", bp[1]);
-            PrintBuf(ss, "certificate", bp + 6, lc);
-            PrintBuf(ss, "response", bp + 6 + lc, lr);
-        } break;
-        default:
-            ssl_PrintBuf(ss, "sending *unknown* message type", bp, len);
-            return;
-    }
-}
-
-void
-ssl_Trace(const char *format, ...)
-{
-    char buf[2000];
-    va_list args;
-
-    if (ssl_trace_iob) {
-        va_start(args, format);
-        PR_vsnprintf(buf, sizeof(buf), format, args);
-        va_end(args);
-
-        fputs(buf, ssl_trace_iob);
-        fputs("\n", ssl_trace_iob);
-    }
-}
-#endif
diff --git a/net/third_party/nss/ssl/sslver.c b/net/third_party/nss/ssl/sslver.c
deleted file mode 100644
index 666e259..0000000
--- a/net/third_party/nss/ssl/sslver.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Library identity and versioning */
-
-#include "nss.h"
-
-#if defined(DEBUG)
-#define _DEBUG_STRING " (debug)"
-#else
-#define _DEBUG_STRING ""
-#endif
-
-/*
- * Version information
- */
-const char __nss_ssl_version[] = "Version: NSS " NSS_VERSION _DEBUG_STRING;
diff --git a/net/third_party/nss/ssl/tls13con.c b/net/third_party/nss/ssl/tls13con.c
deleted file mode 100644
index 4bb136a..0000000
--- a/net/third_party/nss/ssl/tls13con.c
+++ /dev/null
@@ -1,2059 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * TLS 1.3 Protocol
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "stdarg.h"
-#include "cert.h"
-#include "ssl.h"
-#include "keyhi.h"
-#include "pk11func.h"
-#include "secitem.h"
-#include "sslimpl.h"
-#include "sslproto.h"
-#include "sslerr.h"
-#include "tls13hkdf.h"
-#include "tls13con.h"
-
-typedef enum {
-    TrafficKeyEarlyData,
-    TrafficKeyHandshake,
-    TrafficKeyApplicationData
-} TrafficKeyType;
-
-typedef enum {
-    InstallCipherSpecRead,
-    InstallCipherSpecWrite,
-    InstallCipherSpecBoth
-} InstallCipherSpecDirection;
-
-#define MAX_FINISHED_SIZE 64
-
-static SECStatus tls13_InitializeHandshakeEncryption(sslSocket *ss);
-static SECStatus tls13_InstallCipherSpec(
-    sslSocket *ss, InstallCipherSpecDirection direction);
-static SECStatus tls13_InitCipherSpec(
-    sslSocket *ss, TrafficKeyType type, InstallCipherSpecDirection install);
-static SECStatus tls13_AESGCM(
-    ssl3KeyMaterial *keys,
-    PRBool doDecrypt,
-    unsigned char *out, int *outlen, int maxout,
-    const unsigned char *in, int inlen,
-    const unsigned char *additionalData, int additionalDataLen);
-static SECStatus tls13_SendEncryptedExtensions(sslSocket *ss);
-static SECStatus tls13_HandleEncryptedExtensions(sslSocket *ss, SSL3Opaque *b,
-                                                 PRUint32 length);
-static SECStatus tls13_HandleCertificate(
-    sslSocket *ss, SSL3Opaque *b, PRUint32 length);
-static SECStatus tls13_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b,
-                                                PRUint32 length);
-static SECStatus tls13_HandleCertificateStatus(sslSocket *ss, SSL3Opaque *b,
-                                               PRUint32 length);
-static SECStatus tls13_HandleCertificateVerify(
-    sslSocket *ss, SSL3Opaque *b, PRUint32 length,
-    SSL3Hashes *hashes);
-static SECStatus tls13_HkdfExtractSharedKey(sslSocket *ss, PK11SymKey *key,
-                                            SharedSecretType keyType);
-static SECStatus tls13_SendFinished(sslSocket *ss);
-static SECStatus tls13_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
-                                      const SSL3Hashes *hashes);
-static SECStatus tls13_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b,
-                                              PRUint32 length);
-static SECStatus tls13_ComputeSecrets1(sslSocket *ss);
-static SECStatus tls13_ComputeFinished(
-    sslSocket *ss, const SSL3Hashes *hashes,
-    PRBool sending,
-    PRUint8 *output, unsigned int *outputLen,
-    unsigned int maxOutputLen);
-static SECStatus tls13_SendClientSecondRound(sslSocket *ss);
-static SECStatus tls13_FinishHandshake(sslSocket *ss);
-
-const char kHkdfLabelExpandedSs[] = "expanded static secret";
-const char kHkdfLabelExpandedEs[] = "expanded ephemeral secret";
-const char kHkdfLabelMasterSecret[] = "master secret";
-const char kHkdfLabelTrafficSecret[] = "traffic secret";
-const char kHkdfLabelClientFinishedSecret[] = "client finished";
-const char kHkdfLabelServerFinishedSecret[] = "server finished";
-const char kHkdfLabelResumptionMasterSecret[] = "resumption master secret";
-const char kHkdfLabelExporterMasterSecret[] = "exporter master secret";
-const char kHkdfPhaseEarlyHandshakeDataKeys[] = "early handshake key expansion";
-const char kHkdfPhaseEarlyApplicationDataKeys[] = "early application data key expansion";
-const char kHkdfPhaseHandshakeKeys[] = "handshake key expansion";
-const char kHkdfPhaseApplicationDataKeys[] = "application data key expansion";
-const char kHkdfPurposeClientWriteKey[] = "client write key";
-const char kHkdfPurposeServerWriteKey[] = "server write key";
-const char kHkdfPurposeClientWriteIv[] = "client write iv";
-const char kHkdfPurposeServerWriteIv[] = "server write iv";
-const char kClientFinishedLabel[] = "client finished";
-const char kServerFinishedLabel[] = "server finished";
-
-const SSL3ProtocolVersion kRecordVersion = 0x0301U;
-
-#define FATAL_ERROR(ss, prError, desc)                                             \
-    do {                                                                           \
-        SSL_TRC(3, ("%d: TLS13[%d]: fatal error %d in %s (%s:%d)",                 \
-                    SSL_GETPID(), ss->fd, prError, __func__, __FILE__, __LINE__)); \
-        tls13_FatalError(ss, prError, desc);                                       \
-    } while (0)
-
-#define UNIMPLEMENTED()                                                   \
-    do {                                                                  \
-        SSL_TRC(3, ("%d: TLS13[%d]: unimplemented feature in %s (%s:%d)", \
-                    SSL_GETPID(), ss->fd, __func__, __FILE__, __LINE__)); \
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);                         \
-        PORT_Assert(0);                                                   \
-        return SECFailure;                                                \
-    } while (0)
-
-void
-tls13_FatalError(sslSocket *ss, PRErrorCode prError, SSL3AlertDescription desc)
-{
-    PORT_Assert(desc != internal_error); /* These should never happen */
-    (void)SSL3_SendAlert(ss, alert_fatal, desc);
-    PORT_SetError(prError);
-}
-
-#ifdef TRACE
-#define STATE_CASE(a) \
-    case a:           \
-        return #a
-static char *
-tls13_HandshakeState(SSL3WaitState st)
-{
-    switch (st) {
-        STATE_CASE(wait_client_hello);
-        STATE_CASE(wait_client_cert);
-        STATE_CASE(wait_cert_verify);
-        STATE_CASE(wait_finished);
-        STATE_CASE(wait_server_hello);
-        STATE_CASE(wait_certificate_status);
-        STATE_CASE(wait_server_cert);
-        STATE_CASE(wait_cert_request);
-        STATE_CASE(wait_encrypted_extensions);
-        STATE_CASE(idle_handshake);
-        default:
-            break;
-    }
-    PORT_Assert(0);
-    return "unknown";
-}
-#endif
-
-#define TLS13_WAIT_STATE_MASK 0x80
-
-#define TLS13_BASE_WAIT_STATE(ws) (ws & ~TLS13_WAIT_STATE_MASK)
-/* We don't mask idle_handshake because other parts of the code use it*/
-#define TLS13_WAIT_STATE(ws) (ws == idle_handshake ? ws : ws | TLS13_WAIT_STATE_MASK)
-#define TLS13_CHECK_HS_STATE(ss, err, ...)                          \
-    tls13_CheckHsState(ss, err, #err, __func__, __FILE__, __LINE__, \
-                       __VA_ARGS__,                                 \
-                       wait_invalid)
-void
-tls13_SetHsState(sslSocket *ss, SSL3WaitState ws,
-                 const char *func, const char *file, int line)
-{
-#ifdef TRACE
-    const char *new_state_name =
-        tls13_HandshakeState(ws);
-
-    SSL_TRC(3, ("%d: TLS13[%d]: state change from %s->%s in %s (%s:%d)",
-                SSL_GETPID(), ss->fd,
-                tls13_HandshakeState(TLS13_BASE_WAIT_STATE(ss->ssl3.hs.ws)),
-                new_state_name,
-                func, file, line));
-#endif
-
-    ss->ssl3.hs.ws = TLS13_WAIT_STATE(ws);
-}
-
-static PRBool
-tls13_InHsStateV(sslSocket *ss, va_list ap)
-{
-    SSL3WaitState ws;
-
-    while ((ws = va_arg(ap, SSL3WaitState)) != wait_invalid) {
-        if (ws == TLS13_BASE_WAIT_STATE(ss->ssl3.hs.ws)) {
-            return PR_TRUE;
-        }
-    }
-    return PR_FALSE;
-}
-
-PRBool
-tls13_InHsState(sslSocket *ss, ...)
-{
-    PRBool found;
-    va_list ap;
-
-    va_start(ap, ss);
-    found = tls13_InHsStateV(ss, ap);
-    va_end(ap);
-
-    return found;
-}
-
-static SECStatus
-tls13_CheckHsState(sslSocket *ss, int err, const char *error_name,
-                   const char *func, const char *file, int line,
-                   ...)
-{
-    va_list ap;
-    va_start(ap, line);
-    if (tls13_InHsStateV(ss, ap)) {
-        va_end(ap);
-        return SECSuccess;
-    }
-    va_end(ap);
-
-    SSL_TRC(3, ("%d: TLS13[%d]: error %s state is (%s) at %s (%s:%d)",
-                SSL_GETPID(), ss->fd,
-                error_name,
-                tls13_HandshakeState(TLS13_BASE_WAIT_STATE(ss->ssl3.hs.ws)),
-                func, file, line));
-    tls13_FatalError(ss, err, unexpected_message);
-    return SECFailure;
-}
-
-SSLHashType
-tls13_GetHash(sslSocket *ss)
-{
-    /* TODO(ekr@rtfm.com): This needs to actually be looked up. */
-    return ssl_hash_sha256;
-}
-
-CK_MECHANISM_TYPE
-tls13_GetHkdfMechanism(sslSocket *ss)
-{
-    /* TODO(ekr@rtfm.com): This needs to actually be looked up. */
-    return CKM_NSS_HKDF_SHA256;
-}
-
-static CK_MECHANISM_TYPE
-tls13_GetHmacMechanism(sslSocket *ss)
-{
-    /* TODO(ekr@rtfm.com): This needs to actually be looked up. */
-    return CKM_SHA256_HMAC;
-}
-
-/*
- * Called from ssl3_SendClientHello
- */
-SECStatus
-tls13_SetupClientHello(sslSocket *ss)
-{
-    SECStatus rv;
-    /* TODO(ekr@rtfm.com): Handle multiple curves here. */
-    ECName curves_to_try[] = { ec_secp256r1 };
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    PORT_Assert(!ss->ephemeralECDHKeyPair);
-
-    rv = ssl3_CreateECDHEphemeralKeyPair(curves_to_try[0],
-                                         &ss->ephemeralECDHKeyPair);
-    if (rv != SECSuccess)
-        return rv;
-
-    return SECSuccess;
-}
-
-static SECStatus
-tls13_HandleECDHEKeyShare(sslSocket *ss,
-                          TLS13KeyShareEntry *entry,
-                          SECKEYPrivateKey *privKey,
-                          SharedSecretType type)
-{
-    SECStatus rv;
-    SECKEYPublicKey *peerKey;
-    PK11SymKey *shared;
-
-    peerKey = tls13_ImportECDHKeyShare(ss, entry->key_exchange.data,
-                                       entry->key_exchange.len,
-                                       entry->group);
-    if (!peerKey)
-        return SECFailure; /* Error code set already. */
-
-    /* Compute shared key. */
-    shared = tls13_ComputeECDHSharedKey(ss, privKey, peerKey);
-    SECKEY_DestroyPublicKey(peerKey);
-    if (!shared) {
-        return SECFailure; /* Error code set already. */
-    }
-
-    /* Extract key. */
-    rv = tls13_HkdfExtractSharedKey(ss, shared, type);
-    PK11_FreeSymKey(shared);
-
-    return rv;
-}
-
-SECStatus
-tls13_HandlePostHelloHandshakeMessage(sslSocket *ss, SSL3Opaque *b,
-                                      PRUint32 length, SSL3Hashes *hashesPtr)
-{
-    /* TODO(ekr@rtfm.com): Would it be better to check all the states here? */
-    switch (ss->ssl3.hs.msg_type) {
-        case certificate:
-            return tls13_HandleCertificate(ss, b, length);
-
-        case certificate_status:
-            return tls13_HandleCertificateStatus(ss, b, length);
-
-        case certificate_request:
-            return tls13_HandleCertificateRequest(ss, b, length);
-
-        case certificate_verify:
-            return tls13_HandleCertificateVerify(ss, b, length, hashesPtr);
-
-        case encrypted_extensions:
-            return tls13_HandleEncryptedExtensions(ss, b, length);
-
-        case new_session_ticket:
-            return tls13_HandleNewSessionTicket(ss, b, length);
-
-        case finished:
-            return tls13_HandleFinished(ss, b, length, hashesPtr);
-
-        default:
-            FATAL_ERROR(ss, SSL_ERROR_RX_UNKNOWN_HANDSHAKE, unexpected_message);
-            return SECFailure;
-    }
-
-    PORT_Assert(0); /* Unreached */
-    return SECFailure;
-}
-
-/* Called from ssl3_HandleClientHello.
- *
- * Caller must hold Handshake and RecvBuf locks.
- */
-SECStatus
-tls13_HandleClientKeyShare(sslSocket *ss)
-{
-    ECName expectedGroup;
-    SECStatus rv;
-    TLS13KeyShareEntry *found = NULL;
-    PRCList *cur_p;
-
-    SSL_TRC(3, ("%d: TLS13[%d]: handle client_key_share handshake",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    rv = ssl3_SetupPendingCipherSpec(ss);
-    if (rv != SECSuccess)
-        return SECFailure; /* Error code set below */
-
-    /* Figure out what group we expect */
-    switch (ss->ssl3.hs.kea_def->exchKeyType) {
-#ifndef NSS_DISABLE_ECC
-        case ssl_kea_ecdh:
-            expectedGroup = ssl3_GetCurveNameForServerSocket(ss);
-            if (!expectedGroup) {
-                FATAL_ERROR(ss, SSL_ERROR_NO_CYPHER_OVERLAP,
-                            handshake_failure);
-                return SECFailure;
-            }
-            break;
-#endif
-        default:
-            /* Got an unknown or unsupported Key Exchange Algorithm.
-             * Can't happen. */
-            FATAL_ERROR(ss, SEC_ERROR_UNSUPPORTED_KEYALG,
-                        internal_error);
-            return SECFailure;
-    }
-
-    /* Now walk through the keys until we find one for our group */
-    cur_p = PR_NEXT_LINK(&ss->ssl3.hs.remoteKeyShares);
-    while (cur_p != &ss->ssl3.hs.remoteKeyShares) {
-        TLS13KeyShareEntry *offer = (TLS13KeyShareEntry *)cur_p;
-
-        if (offer->group == expectedGroup) {
-            found = offer;
-            break;
-        }
-        cur_p = PR_NEXT_LINK(cur_p);
-    }
-
-    if (!found) {
-        /* No acceptable group. In future, we will need to correct the client.
-         * Currently just generate an error.
-         * TODO(ekr@rtfm.com): Write code to correct client.
-         */
-        FATAL_ERROR(ss, SSL_ERROR_NO_CYPHER_OVERLAP, handshake_failure);
-        return SECFailure;
-    }
-
-    /* Generate our key */
-    rv = ssl3_CreateECDHEphemeralKeyPair(expectedGroup, &ss->ephemeralECDHKeyPair);
-    if (rv != SECSuccess)
-        return rv;
-
-    ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
-    ss->sec.keaKeyBits = SECKEY_PublicKeyStrengthInBits(
-        ss->ephemeralECDHKeyPair->pubKey);
-
-    /* Register the sender */
-    rv = ssl3_RegisterServerHelloExtensionSender(ss, ssl_tls13_key_share_xtn,
-                                                 tls13_ServerSendKeyShareXtn);
-    if (rv != SECSuccess)
-        return SECFailure; /* Error code set below */
-
-    rv = tls13_HandleECDHEKeyShare(ss, found,
-                                   ss->ephemeralECDHKeyPair->privKey,
-                                   EphemeralSharedSecret);
-    if (rv != SECSuccess)
-        return SECFailure; /* Error code set below */
-
-    return SECSuccess;
-}
-
-/*
- *     [draft-ietf-tls-tls13-11] Section 6.3.3.2
- *
- *     opaque DistinguishedName<1..2^16-1>;
- *
- *     struct {
- *         opaque certificate_extension_oid<1..2^8-1>;
- *         opaque certificate_extension_values<0..2^16-1>;
- *     } CertificateExtension;
- *
- *     struct {
- *         opaque certificate_request_context<0..2^8-1>;
- *         SignatureAndHashAlgorithm
- *           supported_signature_algorithms<2..2^16-2>;
- *         DistinguishedName certificate_authorities<0..2^16-1>;
- *         CertificateExtension certificate_extensions<0..2^16-1>;
- *     } CertificateRequest;
- */
-static SECStatus
-tls13_SendCertificateRequest(sslSocket *ss)
-{
-    SECStatus rv;
-    int calen;
-    SECItem *names;
-    int nnames;
-    SECItem *name;
-    int i;
-    PRUint8 sigAlgs[MAX_SIGNATURE_ALGORITHMS * 2];
-    unsigned int sigAlgsLength = 0;
-    int length;
-
-    SSL_TRC(3, ("%d: TLS13[%d]: begin send certificate_request",
-                SSL_GETPID(), ss->fd));
-
-    /* Fixed context value. */
-    ss->ssl3.hs.certReqContext[0] = 0;
-    ss->ssl3.hs.certReqContextLen = 1;
-
-    rv = ssl3_EncodeCertificateRequestSigAlgs(ss, sigAlgs, sizeof(sigAlgs),
-                                              &sigAlgsLength);
-    if (rv != SECSuccess) {
-        return rv;
-    }
-
-    ssl3_GetCertificateRequestCAs(ss, &calen, &names, &nnames);
-    length = 1 + ss->ssl3.hs.certReqContextLen +
-             2 + sigAlgsLength + 2 + calen + 2;
-
-    rv = ssl3_AppendHandshakeHeader(ss, certificate_request, length);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake. */
-    }
-    rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.hs.certReqContext,
-                                      ss->ssl3.hs.certReqContextLen, 1);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake. */
-    }
-    rv = ssl3_AppendHandshakeVariable(ss, sigAlgs, sigAlgsLength, 2);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake. */
-    }
-    rv = ssl3_AppendHandshakeNumber(ss, calen, 2);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake. */
-    }
-    for (i = 0, name = names; i < nnames; i++, name++) {
-        rv = ssl3_AppendHandshakeVariable(ss, name->data, name->len, 2);
-        if (rv != SECSuccess) {
-            return rv; /* err set by AppendHandshake. */
-        }
-    }
-    rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
-    if (rv != SECSuccess) {
-        return rv; /* err set by AppendHandshake. */
-    }
-
-    return SECSuccess;
-}
-
-static SECStatus
-tls13_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    SECStatus rv;
-    SECItem context = { siBuffer, NULL, 0 };
-    SECItem algorithms = { siBuffer, NULL, 0 };
-    PLArenaPool *arena;
-    CERTDistNames ca_list;
-    PRInt32 extensionsLength;
-
-    SSL_TRC(3, ("%d: TLS13[%d]: handle certificate_request sequence",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    /* Client */
-    rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST, wait_cert_request);
-    if (rv != SECSuccess) {
-        return SECFailure;
-    }
-
-    PORT_Assert(ss->ssl3.clientCertChain == NULL);
-    PORT_Assert(ss->ssl3.clientCertificate == NULL);
-    PORT_Assert(ss->ssl3.clientPrivateKey == NULL);
-
-    rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length);
-    if (rv != SECSuccess)
-        return SECFailure;
-    PORT_Assert(sizeof(ss->ssl3.hs.certReqContext) == 255);
-    PORT_Memcpy(ss->ssl3.hs.certReqContext, context.data, context.len);
-    ss->ssl3.hs.certReqContextLen = context.len;
-
-    rv = ssl3_ConsumeHandshakeVariable(ss, &algorithms, 2, &b, &length);
-    if (rv != SECSuccess)
-        return SECFailure;
-
-    if (algorithms.len == 0 || (algorithms.len & 1) != 0) {
-        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST,
-                    illegal_parameter);
-        return SECFailure;
-    }
-
-    arena = ca_list.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-    if (!arena) {
-        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-        return SECFailure;
-    }
-
-    rv = ssl3_ParseCertificateRequestCAs(ss, &b, &length, arena, &ca_list);
-    if (rv != SECSuccess)
-        goto loser; /* alert sent below */
-
-    /* Verify that the extensions length is correct. */
-    extensionsLength = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
-    if (extensionsLength < 0) {
-        goto loser; /* alert sent below */
-    }
-    if (extensionsLength != length) {
-        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST,
-                    illegal_parameter);
-        goto loser;
-    }
-
-    TLS13_SET_HS_STATE(ss, wait_server_cert);
-
-    rv = ssl3_CompleteHandleCertificateRequest(ss, &algorithms, &ca_list);
-    if (rv != SECSuccess) {
-        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-        goto loser;
-    }
-
-    return SECSuccess;
-
-loser:
-    PORT_FreeArena(arena, PR_FALSE);
-    return SECFailure;
-}
-
-static SECStatus
-tls13_InitializeHandshakeEncryption(sslSocket *ss)
-{
-    SECStatus rv;
-
-    /* For all present cipher suites, SS = ES.
-     * TODO(ekr@rtfm.com): Revisit for 0-RTT. */
-    ss->ssl3.hs.xSS = PK11_ReferenceSymKey(ss->ssl3.hs.xES);
-    if (!ss->ssl3.hs.xSS) {
-        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-        return SECFailure;
-    }
-
-    rv = tls13_InitCipherSpec(ss, TrafficKeyHandshake,
-                              InstallCipherSpecBoth);
-    if (rv != SECSuccess) {
-        FATAL_ERROR(ss, SSL_ERROR_INIT_CIPHER_SUITE_FAILURE, internal_error);
-        return SECFailure;
-    }
-
-    return rv;
-}
-
-/* Called from:  ssl3_HandleClientHello */
-SECStatus
-tls13_SendServerHelloSequence(sslSocket *ss)
-{
-    SECStatus rv;
-    SSL3KEAType certIndex;
-
-    SSL_TRC(3, ("%d: TLS13[%d]: begin send server_hello sequence",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    rv = ssl3_SendServerHello(ss);
-    if (rv != SECSuccess) {
-        return rv; /* err code is set. */
-    }
-
-    rv = tls13_InitializeHandshakeEncryption(ss);
-    if (rv != SECSuccess) {
-        return SECFailure; /* error code is set. */
-    }
-
-    rv = tls13_SendEncryptedExtensions(ss);
-    if (rv != SECSuccess) {
-        return SECFailure; /* error code is set. */
-    }
-
-    if (ss->opt.requestCertificate) {
-        rv = tls13_SendCertificateRequest(ss);
-        if (rv != SECSuccess) {
-            return SECFailure; /* error code is set. */
-        }
-    }
-    rv = ssl3_SendCertificate(ss);
-    if (rv != SECSuccess) {
-        return SECFailure; /* error code is set. */
-    }
-    rv = ssl3_SendCertificateStatus(ss);
-    if (rv != SECSuccess) {
-        return SECFailure; /* error code is set. */
-    }
-
-    /* This was copied from: ssl3_SendCertificate.
-     * TODO(ekr@rtfm.com): Verify that this selection logic is correct.
-     * Bug 1237514.
-    */
-    if ((ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) ||
-        (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) {
-        certIndex = kt_rsa;
-    } else {
-        certIndex = ss->ssl3.hs.kea_def->exchKeyType;
-    }
-    rv = ssl3_SendCertificateVerify(ss, ss->serverCerts[certIndex].SERVERKEY);
-    if (rv != SECSuccess) {
-        return rv; /* err code is set. */
-    }
-
-    /* Compute the rest of the secrets except for the resumption
-     * and exporter secret. */
-    rv = tls13_ComputeSecrets1(ss);
-    if (rv != SECSuccess) {
-        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-        return SECFailure;
-    }
-
-    rv = tls13_SendFinished(ss);
-    if (rv != SECSuccess) {
-        return rv; /* error code is set. */
-    }
-
-    TLS13_SET_HS_STATE(ss, ss->opt.requestCertificate ? wait_client_cert
-                                                      : wait_finished);
-
-    return SECSuccess;
-}
-
-/*
- * Called from ssl3_HandleServerHello.
- *
- * Caller must hold Handshake and RecvBuf locks.
- */
-SECStatus
-tls13_HandleServerKeyShare(sslSocket *ss)
-{
-    SECStatus rv;
-    ECName expectedGroup;
-    PRCList *cur_p;
-    TLS13KeyShareEntry *entry;
-
-    SSL_TRC(3, ("%d: TLS13[%d]: handle server_key_share handshake",
-                SSL_GETPID(), ss->fd));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    switch (ss->ssl3.hs.kea_def->exchKeyType) {
-#ifndef NSS_DISABLE_ECC
-        case ssl_kea_ecdh:
-            expectedGroup = ssl3_PubKey2ECName(ss->ephemeralECDHKeyPair->pubKey);
-            break;
-#endif /* NSS_DISABLE_ECC */
-        default:
-            FATAL_ERROR(ss, SEC_ERROR_UNSUPPORTED_KEYALG, handshake_failure);
-            return SECFailure;
-    }
-
-    /* This list should have one entry. */
-    cur_p = PR_NEXT_LINK(&ss->ssl3.hs.remoteKeyShares);
-    if (!cur_p) {
-        FATAL_ERROR(ss, SSL_ERROR_MISSING_KEY_SHARE, missing_extension);
-        return SECFailure;
-    }
-    PORT_Assert(PR_NEXT_LINK(cur_p) == &ss->ssl3.hs.remoteKeyShares);
-
-    entry = (TLS13KeyShareEntry *)cur_p;
-    if (entry->group != expectedGroup) {
-        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_KEY_SHARE, illegal_parameter);
-        return SECFailure;
-    }
-
-    rv = tls13_HandleECDHEKeyShare(ss, entry,
-                                   ss->ephemeralECDHKeyPair->privKey,
-                                   EphemeralSharedSecret);
-
-    ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
-    ss->sec.keaKeyBits = SECKEY_PublicKeyStrengthInBits(
-        ss->ephemeralECDHKeyPair->pubKey);
-
-    if (rv != SECSuccess)
-        return SECFailure; /* Error code set below */
-
-    return tls13_InitializeHandshakeEncryption(ss);
-}
-
-/* Called from tls13_CompleteHandleHandshakeMessage() when it has deciphered a complete
- * tls13 Certificate message.
- * Caller must hold Handshake and RecvBuf locks.
- */
-static SECStatus
-tls13_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    SECStatus rv;
-    SECItem context = { siBuffer, NULL, 0 };
-
-    SSL_TRC(3, ("%d: TLS13[%d]: handle certificate handshake",
-                SSL_GETPID(), ss->fd));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if (ss->sec.isServer) {
-        rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE,
-                                  wait_client_cert);
-    } else {
-        rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE,
-                                  wait_cert_request, wait_server_cert);
-    }
-    if (rv != SECSuccess)
-        return SECFailure;
-
-    /* Process the context string */
-    rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length);
-    if (rv != SECSuccess)
-        return SECFailure;
-    if (!ss->sec.isServer) {
-        if (context.len) {
-            /* The server's context string MUST be empty */
-            FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE,
-                        illegal_parameter);
-            return SECFailure;
-        }
-    } else {
-        if (!context.len || context.len != ss->ssl3.hs.certReqContextLen ||
-            (NSS_SecureMemcmp(ss->ssl3.hs.certReqContext,
-                              context.data, context.len) != 0)) {
-            FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE,
-                        illegal_parameter);
-            return SECFailure;
-        }
-        context.len = 0; /* Belt and suspenders. Zero out the context. */
-    }
-
-    return ssl3_CompleteHandleCertificate(ss, b, length);
-}
-
-/* Called from tls13_CompleteHandleHandshakeMessage() when it has deciphered a complete
- * ssl3 CertificateStatus message.
- * Caller must hold Handshake and RecvBuf locks.
- */
-static SECStatus
-tls13_HandleCertificateStatus(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    SECStatus rv;
-
-    rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERT_STATUS,
-                              wait_certificate_status);
-    if (rv != SECSuccess)
-        return rv;
-
-    return ssl3_CompleteHandleCertificateStatus(ss, b, length);
-}
-
-/*
- * TODO(ekr@rtfm.com): This install logic needs renaming since it's
- * what happens at various stages of cipher spec setup. Legacy from ssl3con.c.
- */
-int
-tls13_InstallCipherSpec(sslSocket *ss, InstallCipherSpecDirection direction)
-{
-    SSL_TRC(3, ("%d: TLS13[%d]: Installing new cipher specs direction = %s",
-                SSL_GETPID(), ss->fd,
-                direction == InstallCipherSpecRead ? "read" : "write"));
-
-    PORT_Assert(!IS_DTLS(ss)); /* TODO(ekr@rtfm.com): Update for DTLS */
-    /* TODO(ekr@rtfm.com): Holddown timer for DTLS. */
-    ssl_GetSpecWriteLock(ss); /**************************************/
-
-    /* Flush out any old stuff in the handshake buffers */
-    switch (direction) {
-        case InstallCipherSpecWrite: {
-            ssl3CipherSpec *pwSpec;
-            pwSpec = ss->ssl3.pwSpec;
-
-            ss->ssl3.pwSpec = ss->ssl3.cwSpec;
-            ss->ssl3.cwSpec = pwSpec;
-            break;
-        } break;
-        case InstallCipherSpecRead: {
-            ssl3CipherSpec *prSpec;
-
-            prSpec = ss->ssl3.prSpec;
-            ss->ssl3.prSpec = ss->ssl3.crSpec;
-            ss->ssl3.crSpec = prSpec;
-        } break;
-        default:
-            PORT_Assert(0);
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            ssl_ReleaseSpecWriteLock(ss); /**************************************/
-            return SECFailure;
-    }
-
-    /* If we are really through with the old cipher prSpec
-     * (Both the read and write sides have changed) destroy it.
-     */
-    if (ss->ssl3.prSpec == ss->ssl3.pwSpec) {
-        ssl3_DestroyCipherSpec(ss->ssl3.prSpec, PR_FALSE /*freeSrvName*/);
-    }
-    ssl_ReleaseSpecWriteLock(ss); /**************************************/
-
-    return SECSuccess;
-}
-
-/* Add context to the hash functions as described in
-   [draft-ietf-tls-tls13; Section 4.9.1] */
-SECStatus
-tls13_AddContextToHashes(sslSocket *ss, SSL3Hashes *hashes /* IN/OUT */,
-                         SSLHashType algorithm, PRBool sending)
-{
-    SECStatus rv = SECSuccess;
-    PK11Context *ctx;
-    const unsigned char context_padding[] = {
-        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-    };
-    const char *client_cert_verify_string = "TLS 1.3, client CertificateVerify";
-    const char *server_cert_verify_string = "TLS 1.3, server CertificateVerify";
-    const char *context_string = (sending ^ ss->sec.isServer) ? client_cert_verify_string
-                                                              : server_cert_verify_string;
-    unsigned int hashlength;
-
-    /* Double check that we are doing SHA-256 for the handshake hash.*/
-    PORT_Assert(hashes->hashAlg == ssl_hash_sha256);
-    if (hashes->hashAlg != ssl_hash_sha256) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        goto loser;
-    }
-    PORT_Assert(hashes->len == 32);
-
-    ctx = PK11_CreateDigestContext(ssl3_TLSHashAlgorithmToOID(algorithm));
-    if (!ctx) {
-        PORT_SetError(SEC_ERROR_NO_MEMORY);
-        goto loser;
-    }
-
-    PORT_Assert(SECFailure);
-    PORT_Assert(!SECSuccess);
-
-    rv |= PK11_DigestBegin(ctx);
-    rv |= PK11_DigestOp(ctx, context_padding, sizeof(context_padding));
-    rv |= PK11_DigestOp(ctx, (unsigned char *)context_string,
-                        strlen(context_string) + 1); /* +1 includes the terminating 0 */
-    rv |= PK11_DigestOp(ctx, hashes->u.raw, hashes->len);
-    /* Update the hash in-place */
-    rv |= PK11_DigestFinal(ctx, hashes->u.raw, &hashlength, sizeof(hashes->u.raw));
-    PK11_DestroyContext(ctx, PR_TRUE);
-    PRINT_BUF(90, (NULL, "TLS 1.3 hash with context", hashes->u.raw, hashlength));
-
-    hashes->len = hashlength;
-    hashes->hashAlg = algorithm;
-
-    if (rv) {
-        ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
-        goto loser;
-    }
-    return SECSuccess;
-
-loser:
-    return SECFailure;
-}
-
-static SECStatus
-tls13_HkdfExtractSharedKey(sslSocket *ss, PK11SymKey *key,
-                           SharedSecretType keyType)
-{
-    PK11SymKey **destp;
-
-    switch (keyType) {
-        case EphemeralSharedSecret:
-            destp = &ss->ssl3.hs.xES;
-            break;
-        case StaticSharedSecret:
-            destp = &ss->ssl3.hs.xSS;
-            break;
-        default:
-            PORT_Assert(0);
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            return SECFailure;
-    }
-
-    PORT_Assert(!*destp);
-    return tls13_HkdfExtract(NULL, key, tls13_GetHash(ss), destp);
-}
-
-static SECStatus
-tls13_DeriveTrafficKeys(sslSocket *ss, ssl3CipherSpec *pwSpec,
-                        TrafficKeyType type)
-{
-    size_t keySize = pwSpec->cipher_def->key_size;
-    size_t ivSize = pwSpec->cipher_def->iv_size +
-                    pwSpec->cipher_def->explicit_nonce_size; /* This isn't always going to
-                                                              * work, but it does for
-                                                              * AES-GCM */
-    CK_MECHANISM_TYPE bulkAlgorithm = ssl3_Alg2Mech(pwSpec->cipher_def->calg);
-    SSL3Hashes hashes;
-    PK11SymKey *prk = NULL;
-    const char *phase;
-    char label[256]; /* Arbitrary buffer large enough to hold the label */
-    SECStatus rv;
-
-#define FORMAT_LABEL(phase_, purpose_)                                              \
-    do {                                                                            \
-        PRUint32 n = PR_snprintf(label, sizeof(label), "%s, %s", phase_, purpose_); \
-        /* Check for getting close. */                                              \
-        if ((n + 1) >= sizeof(label)) {                                             \
-            PORT_Assert(0);                                                         \
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);                               \
-            goto loser;                                                             \
-        }                                                                           \
-    } while (0)
-#define EXPAND_TRAFFIC_KEY(purpose_, target_)                                 \
-    do {                                                                      \
-        FORMAT_LABEL(phase, purpose_);                                        \
-        rv = tls13_HkdfExpandLabel(prk, tls13_GetHash(ss),                    \
-                                   hashes.u.raw, hashes.len,                  \
-                                   label, strlen(label),                      \
-                                   bulkAlgorithm, keySize, &pwSpec->target_); \
-        if (rv != SECSuccess) {                                               \
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);                         \
-            PORT_Assert(0);                                                   \
-            goto loser;                                                       \
-        }                                                                     \
-    } while (0)
-
-#define EXPAND_TRAFFIC_IV(purpose_, target_)                    \
-    do {                                                        \
-        FORMAT_LABEL(phase, purpose_);                          \
-        rv = tls13_HkdfExpandLabelRaw(prk, tls13_GetHash(ss),   \
-                                      hashes.u.raw, hashes.len, \
-                                      label, strlen(label),     \
-                                      pwSpec->target_, ivSize); \
-        if (rv != SECSuccess) {                                 \
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);           \
-            PORT_Assert(0);                                     \
-            goto loser;                                         \
-        }                                                       \
-    } while (0)
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
-    PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
-
-    rv = ssl3_ComputeHandshakeHashes(ss, pwSpec, &hashes, 0);
-    if (rv != SECSuccess) {
-        PORT_Assert(0); /* Should never fail */
-        ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
-        return SECFailure;
-    }
-    PRINT_BUF(60, (ss, "Deriving traffic keys. Session hash=", hashes.u.raw,
-                   hashes.len));
-
-    switch (type) {
-        case TrafficKeyHandshake:
-            phase = kHkdfPhaseHandshakeKeys;
-            prk = ss->ssl3.hs.xES;
-            break;
-        case TrafficKeyApplicationData:
-            phase = kHkdfPhaseApplicationDataKeys;
-            prk = ss->ssl3.hs.trafficSecret;
-            break;
-        default:
-            PORT_Assert(0);
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            return SECFailure;
-    }
-    PORT_Assert(prk != NULL);
-
-    SSL_TRC(3, ("%d: TLS13[%d]: deriving traffic keys phase='%s'",
-                SSL_GETPID(), ss->fd, phase));
-
-    EXPAND_TRAFFIC_KEY(kHkdfPurposeClientWriteKey, client.write_key);
-    EXPAND_TRAFFIC_KEY(kHkdfPurposeServerWriteKey, server.write_key);
-    EXPAND_TRAFFIC_IV(kHkdfPurposeClientWriteIv, client.write_iv);
-    EXPAND_TRAFFIC_IV(kHkdfPurposeServerWriteIv, server.write_iv);
-
-    return SECSuccess;
-
-loser:
-    return SECFailure;
-}
-
-/* Set up a cipher spec with keys. If install is nonzero, then also install
- * it as the current cipher spec for each value in the mask. */
-SECStatus
-tls13_InitCipherSpec(sslSocket *ss, TrafficKeyType type, InstallCipherSpecDirection install)
-{
-    ssl3CipherSpec *pwSpec;
-    ssl3CipherSpec *cwSpec;
-    SECStatus rv;
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    if (install == InstallCipherSpecWrite ||
-        install == InstallCipherSpecBoth) {
-        ssl_GetXmitBufLock(ss);
-
-        rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
-        ssl_ReleaseXmitBufLock(ss);
-        if (rv != SECSuccess) {
-            goto loser;
-        }
-    }
-
-    ssl_GetSpecWriteLock(ss); /**************************************/
-
-    PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
-
-    pwSpec = ss->ssl3.pwSpec;
-    cwSpec = ss->ssl3.cwSpec;
-
-    switch (pwSpec->cipher_def->calg) {
-        case calg_aes_gcm:
-            pwSpec->aead = tls13_AESGCM;
-            break;
-        default:
-            PORT_Assert(0);
-            goto loser;
-            break;
-    }
-
-    /* Generic behaviors -- common to all crypto methods */
-    if (!IS_DTLS(ss)) {
-        pwSpec->read_seq_num.high = pwSpec->write_seq_num.high = 0;
-    } else {
-        if (cwSpec->epoch == PR_UINT16_MAX) {
-            /* The problem here is that we have rehandshaked too many
-             * times (you are not allowed to wrap the epoch). The
-             * spec says you should be discarding the connection
-             * and start over, so not much we can do here. */
-            rv = SECFailure;
-            goto loser;
-        }
-        /* The sequence number has the high 16 bits as the epoch. */
-        pwSpec->epoch = cwSpec->epoch + 1;
-        pwSpec->read_seq_num.high = pwSpec->write_seq_num.high =
-            pwSpec->epoch << 16;
-
-        dtls_InitRecvdRecords(&pwSpec->recvdRecords);
-    }
-    pwSpec->read_seq_num.low = pwSpec->write_seq_num.low = 0;
-
-    rv = tls13_DeriveTrafficKeys(ss, pwSpec, type);
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-    if (install == InstallCipherSpecWrite ||
-        install == InstallCipherSpecBoth) {
-        rv = tls13_InstallCipherSpec(ss, InstallCipherSpecWrite);
-        if (rv != SECSuccess) {
-            goto loser;
-        }
-    }
-    if (install == InstallCipherSpecRead ||
-        install == InstallCipherSpecBoth) {
-        rv = tls13_InstallCipherSpec(ss, InstallCipherSpecRead);
-        if (rv != SECSuccess) {
-            goto loser;
-        }
-    }
-    ssl_ReleaseSpecWriteLock(ss); /**************************************/
-
-    return SECSuccess;
-
-loser:
-    ssl_ReleaseSpecWriteLock(ss); /**************************************/
-    PORT_SetError(SSL_ERROR_INIT_CIPHER_SUITE_FAILURE);
-    return SECFailure;
-}
-
-static SECStatus
-tls13_ComputeSecrets1(sslSocket *ss)
-{
-    SECStatus rv;
-    PK11SymKey *mSS = NULL;
-    PK11SymKey *mES = NULL;
-    PK11SymKey *masterSecret = NULL;
-    SSL3Hashes hashes;
-
-    rv = ssl3_SetupPendingCipherSpec(ss);
-    if (rv != SECSuccess) {
-        return rv; /* error code set below. */
-    }
-
-    rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, 0);
-    if (rv != SECSuccess) {
-        PORT_Assert(0); /* Should never fail */
-        ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
-        return SECFailure;
-    }
-
-    PORT_Assert(ss->ssl3.hs.xSS);
-    PORT_Assert(ss->ssl3.hs.xES);
-
-    rv = tls13_HkdfExpandLabel(ss->ssl3.hs.xSS,
-                               tls13_GetHash(ss),
-                               hashes.u.raw, hashes.len,
-                               kHkdfLabelExpandedSs,
-                               strlen(kHkdfLabelExpandedSs),
-                               tls13_GetHkdfMechanism(ss),
-                               hashes.len, &mSS);
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-
-    rv = tls13_HkdfExpandLabel(ss->ssl3.hs.xES,
-                               tls13_GetHash(ss),
-                               hashes.u.raw, hashes.len,
-                               kHkdfLabelExpandedEs,
-                               strlen(kHkdfLabelExpandedEs),
-                               tls13_GetHkdfMechanism(ss),
-                               hashes.len, &mES);
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-
-    rv = tls13_HkdfExtract(mSS, mES,
-                           tls13_GetHash(ss),
-                           &masterSecret);
-
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-
-    rv = tls13_HkdfExpandLabel(masterSecret,
-                               tls13_GetHash(ss),
-                               hashes.u.raw, hashes.len,
-                               kHkdfLabelTrafficSecret,
-                               strlen(kHkdfLabelTrafficSecret),
-                               tls13_GetHkdfMechanism(ss),
-                               hashes.len, &ss->ssl3.hs.trafficSecret);
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-
-    rv = tls13_HkdfExpandLabel(masterSecret,
-                               tls13_GetHash(ss),
-                               NULL, 0,
-                               kHkdfLabelClientFinishedSecret,
-                               strlen(kHkdfLabelClientFinishedSecret),
-                               tls13_GetHmacMechanism(ss),
-                               hashes.len, &ss->ssl3.hs.clientFinishedSecret);
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-
-    rv = tls13_HkdfExpandLabel(masterSecret,
-                               tls13_GetHash(ss),
-                               NULL, 0,
-                               kHkdfLabelServerFinishedSecret,
-                               strlen(kHkdfLabelServerFinishedSecret),
-                               tls13_GetHmacMechanism(ss),
-                               hashes.len, &ss->ssl3.hs.serverFinishedSecret);
-    if (rv != SECSuccess) {
-        goto loser;
-    }
-
-loser:
-    PK11_FreeSymKey(ss->ssl3.hs.xSS);
-    ss->ssl3.hs.xSS = NULL;
-    PK11_FreeSymKey(ss->ssl3.hs.xES);
-    ss->ssl3.hs.xES = NULL;
-
-    if (mSS) {
-        PK11_FreeSymKey(mSS);
-    }
-    if (mES) {
-        PK11_FreeSymKey(mES);
-    }
-    if (masterSecret) {
-        PK11_FreeSymKey(masterSecret);
-    }
-
-    return rv;
-}
-
-void
-tls13_DestroyKeyShareEntry(TLS13KeyShareEntry *offer)
-{
-    SECITEM_ZfreeItem(&offer->key_exchange, PR_FALSE);
-    PORT_ZFree(offer, sizeof(*offer));
-}
-
-void
-tls13_DestroyKeyShares(PRCList *list)
-{
-    PRCList *cur_p;
-
-    while (!PR_CLIST_IS_EMPTY(list)) {
-        cur_p = PR_LIST_TAIL(list);
-        PR_REMOVE_LINK(cur_p);
-        tls13_DestroyKeyShareEntry((TLS13KeyShareEntry *)cur_p);
-    }
-}
-
-/* Implement the SSLAEADCipher interface defined in sslimpl.h.
- *
- * That interface mixes the AD and the sequence number, but in
- * TLS 1.3 there is no additional data so this value is just the
- * encoded sequence number and we call it |seqNumBuf|.
- */
-static SECStatus
-tls13_AESGCM(ssl3KeyMaterial *keys,
-             PRBool doDecrypt,
-             unsigned char *out,
-             int *outlen,
-             int maxout,
-             const unsigned char *in,
-             int inlen,
-             const unsigned char *seqNumBuf,
-             int seqNumLen)
-{
-    SECItem param;
-    SECStatus rv = SECFailure;
-    unsigned char nonce[12];
-    size_t i;
-    unsigned int uOutLen;
-    CK_GCM_PARAMS gcmParams;
-    static const int tagSize = 16;
-
-    PORT_Assert(seqNumLen == 8);
-
-    /* draft-ietf-tls-tls13 Section 5.2.2 specifies the following
-     * nonce algorithm:
-     *
-     * The length of the per-record nonce (iv_length) is set to max(8 bytes,
-     * N_MIN) for the AEAD algorithm (see [RFC5116] Section 4).  An AEAD
-     * algorithm where N_MAX is less than 8 bytes MUST NOT be used with TLS.
-     * The per-record nonce for the AEAD construction is formed as follows:
-     *
-     * 1.  The 64-bit record sequence number is padded to the left with
-     *     zeroes to iv_length.
-     *
-     * 2.  The padded sequence number is XORed with the static
-     *     client_write_iv or server_write_iv, depending on the role.
-     *
-     * The resulting quantity (of length iv_length) is used as the per-
-     * record nonce.
-     *
-     * Per RFC 5288: N_MIN = N_MAX = 12 bytes.
-     *
-     */
-    memcpy(nonce, keys->write_iv, sizeof(nonce));
-    for (i = 0; i < 8; ++i) {
-        nonce[4 + i] ^= seqNumBuf[i];
-    }
-
-    param.type = siBuffer;
-    param.data = (unsigned char *)&gcmParams;
-    param.len = sizeof(gcmParams);
-    gcmParams.pIv = nonce;
-    gcmParams.ulIvLen = sizeof(nonce);
-    gcmParams.pAAD = NULL;
-    gcmParams.ulAADLen = 0;
-    gcmParams.ulTagBits = tagSize * 8;
-
-    if (doDecrypt) {
-        rv = PK11_Decrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
-                          maxout, in, inlen);
-    } else {
-        rv = PK11_Encrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
-                          maxout, in, inlen);
-    }
-    *outlen = (int)uOutLen;
-
-    return rv;
-}
-
-static SECStatus
-tls13_HandleEncryptedExtensions(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    SECStatus rv;
-    PRInt32 innerLength;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    SSL_TRC(3, ("%d: TLS13[%d]: handle encrypted extensions",
-                SSL_GETPID(), ss->fd));
-
-    rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_ENCRYPTED_EXTENSIONS,
-                              wait_encrypted_extensions);
-    if (rv != SECSuccess) {
-        return SECFailure;
-    }
-
-    innerLength = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
-    if (innerLength < 0) {
-        return SECFailure; /* Alert already sent. */
-    }
-    if (innerLength != length) {
-        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_ENCRYPTED_EXTENSIONS,
-                    illegal_parameter);
-        return SECFailure;
-    }
-
-    rv = ssl3_HandleHelloExtensions(ss, &b, &length, encrypted_extensions);
-    if (rv != SECSuccess) {
-        return SECFailure; /* Error code set below */
-    }
-
-    TLS13_SET_HS_STATE(ss, wait_cert_request);
-    return SECSuccess;
-}
-
-static SECStatus
-tls13_SendEncryptedExtensions(sslSocket *ss)
-{
-    SECStatus rv;
-    PRInt32 extensions_len = 0;
-    PRInt32 sent_len = 0;
-    PRUint32 maxBytes = 65535;
-
-    SSL_TRC(3, ("%d: TLS13[%d]: send encrypted extensions handshake",
-                SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-
-    extensions_len = ssl3_CallHelloExtensionSenders(
-        ss, PR_FALSE, maxBytes, &ss->xtnData.encryptedExtensionsSenders[0]);
-
-    rv = ssl3_AppendHandshakeHeader(ss, encrypted_extensions,
-                                    extensions_len + 2);
-    if (rv != SECSuccess) {
-        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-        return SECFailure;
-    }
-    rv = ssl3_AppendHandshakeNumber(ss, extensions_len, 2);
-    if (rv != SECSuccess) {
-        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-        return SECFailure;
-    }
-    sent_len = ssl3_CallHelloExtensionSenders(
-        ss, PR_TRUE, extensions_len,
-        &ss->xtnData.encryptedExtensionsSenders[0]);
-    PORT_Assert(sent_len == extensions_len);
-    if (sent_len != extensions_len) {
-        PORT_Assert(sent_len == 0);
-        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-        return SECFailure;
-    }
-
-    return SECSuccess;
-}
-
-/* Called from tls13_CompleteHandleHandshakeMessage() when it has deciphered a complete
- * tls13 CertificateVerify message
- * Caller must hold Handshake and RecvBuf locks.
- */
-SECStatus
-tls13_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
-                              SSL3Hashes *hashes)
-{
-    SECItem signed_hash = { siBuffer, NULL, 0 };
-    SECStatus rv;
-    SSLSignatureAndHashAlg sigAndHash;
-
-    SSL_TRC(3, ("%d: TLS13[%d]: handle certificate_verify handshake",
-                SSL_GETPID(), ss->fd));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY,
-                              wait_cert_verify);
-    if (rv != SECSuccess) {
-        return SECFailure;
-    }
-
-    if (!hashes) {
-        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-        return SECFailure;
-    }
-
-    /* We only support CertificateVerify messages that use the handshake
-     * hash.
-     * TODO(ekr@rtfm.com): This should be easy to relax in TLS 1.3 by
-     * reading the client's hash algorithm first, but there may
-     * be subtleties so retain the restriction for now.
-     */
-    rv = tls13_AddContextToHashes(ss, hashes, hashes->hashAlg, PR_FALSE);
-    if (rv != SECSuccess) {
-        FATAL_ERROR(ss, SSL_ERROR_DIGEST_FAILURE, internal_error);
-        return SECFailure;
-    }
-
-    rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
-                                               &sigAndHash);
-    if (rv != SECSuccess) {
-        PORT_SetError(SSL_ERROR_RX_MALFORMED_CERT_VERIFY);
-        return SECFailure;
-    }
-
-    rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
-        ss, &sigAndHash, ss->sec.peerCert);
-    if (rv != SECSuccess) {
-        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_VERIFY, decrypt_error);
-        return SECFailure;
-    }
-
-    /* We only support CertificateVerify messages that use the handshake
-     * hash. */
-    if (sigAndHash.hashAlg != hashes->hashAlg) {
-        FATAL_ERROR(ss, SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM, decrypt_error);
-        return SECFailure;
-    }
-
-    rv = ssl3_ConsumeHandshakeVariable(ss, &signed_hash, 2, &b, &length);
-    if (rv != SECSuccess) {
-        PORT_SetError(SSL_ERROR_RX_MALFORMED_CERT_VERIFY);
-        return SECFailure;
-    }
-
-    if (length != 0) {
-        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_VERIFY, decode_error);
-        return SECFailure;
-    }
-
-    rv = ssl3_VerifySignedHashes(hashes, ss->sec.peerCert, &signed_hash,
-                                 PR_TRUE, ss->pkcs11PinArg);
-    if (rv != SECSuccess) {
-        FATAL_ERROR(ss, PORT_GetError(), decrypt_error);
-        return SECFailure;
-    }
-
-    if (!ss->sec.isServer) {
-        /* Compute the rest of the secrets except for the resumption
-         * and exporter secret. */
-        rv = tls13_ComputeSecrets1(ss);
-        if (rv != SECSuccess) {
-            FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-            return SECFailure;
-        }
-    }
-    TLS13_SET_HS_STATE(ss, wait_finished);
-
-    return SECSuccess;
-}
-
-static SECStatus
-tls13_ComputeFinished(sslSocket *ss, const SSL3Hashes *hashes, PRBool sending,
-                      PRUint8 *output, unsigned int *outputLen, unsigned int maxOutputLen)
-{
-    SECStatus rv;
-    PK11Context *hmacCtx = NULL;
-    CK_MECHANISM_TYPE macAlg = tls13_GetHmacMechanism(ss);
-    SECItem param = { siBuffer, NULL, 0 };
-    unsigned int outputLenUint;
-    PK11SymKey *secret = (ss->sec.isServer ^ sending) ? ss->ssl3.hs.clientFinishedSecret
-                                                      : ss->ssl3.hs.serverFinishedSecret;
-
-    PORT_Assert(secret);
-    PRINT_BUF(90, (NULL, "Handshake hash", hashes->u.raw, hashes->len));
-
-    hmacCtx = PK11_CreateContextBySymKey(macAlg, CKA_SIGN,
-                                         secret, &param);
-    if (!hmacCtx) {
-        goto abort;
-    }
-
-    rv = PK11_DigestBegin(hmacCtx);
-    if (rv != SECSuccess)
-        goto abort;
-
-    rv = PK11_DigestOp(hmacCtx, hashes->u.raw, hashes->len);
-    if (rv != SECSuccess)
-        goto abort;
-
-    PORT_Assert(maxOutputLen >= hashes->len);
-    rv = PK11_DigestFinal(hmacCtx, output, &outputLenUint, maxOutputLen);
-    if (rv != SECSuccess)
-        goto abort;
-    *outputLen = outputLenUint;
-
-    PK11_DestroyContext(hmacCtx, PR_TRUE);
-    return SECSuccess;
-
-abort:
-    if (hmacCtx) {
-        PK11_DestroyContext(hmacCtx, PR_TRUE);
-    }
-
-    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-    return SECFailure;
-}
-
-static SECStatus
-tls13_SendFinished(sslSocket *ss)
-{
-    SECStatus rv;
-    PRUint8 finishedBuf[MAX_FINISHED_SIZE];
-    unsigned int finishedLen;
-    SSL3Hashes hashes;
-    int errCode;
-
-    SSL_TRC(3, ("%d: TLS13[%d]: send finished handshake", SSL_GETPID(), ss->fd));
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.cwSpec, &hashes, 0);
-    if (rv != SECSuccess) {
-        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-        return SECFailure;
-    }
-
-    ssl_GetSpecReadLock(ss);
-    rv = tls13_ComputeFinished(ss, &hashes, PR_TRUE,
-                               finishedBuf, &finishedLen, sizeof(finishedBuf));
-    ssl_ReleaseSpecReadLock(ss);
-    if (rv != SECSuccess) {
-        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-        return SECFailure;
-    }
-
-    rv = ssl3_AppendHandshakeHeader(ss, finished, finishedLen);
-    if (rv != SECSuccess) {
-        errCode = PR_GetError();
-        goto alert_loser;
-    }
-
-    rv = ssl3_AppendHandshake(ss, finishedBuf, finishedLen);
-    if (rv != SECSuccess) {
-        errCode = PR_GetError();
-        goto alert_loser;
-    }
-
-    rv = ssl3_FlushHandshake(ss, 0);
-    if (rv != SECSuccess) {
-        errCode = PR_GetError();
-        goto alert_loser;
-    }
-
-    if (ss->sec.isServer) {
-        rv = tls13_InitCipherSpec(ss, TrafficKeyApplicationData,
-                                  InstallCipherSpecWrite);
-    } else {
-        rv = tls13_InstallCipherSpec(ss, InstallCipherSpecWrite);
-    }
-    if (rv != SECSuccess) {
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        return SECFailure;
-    }
-
-    /* TODO(ekr@rtfm.com): Record key log */
-    return SECSuccess;
-
-alert_loser:
-    (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
-    PORT_SetError(errCode); /* Restore error code */
-    return rv;
-}
-
-static SECStatus
-tls13_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
-                     const SSL3Hashes *hashes)
-{
-    SECStatus rv;
-    PRUint8 finishedBuf[MAX_FINISHED_SIZE];
-    unsigned int finishedLen;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    SSL_TRC(3, ("%d: TLS13[%d]: handle finished handshake",
-                SSL_GETPID(), ss->fd));
-
-    rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_FINISHED, wait_finished);
-    if (rv != SECSuccess) {
-        return SECFailure;
-    }
-    if (!hashes) {
-        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-        return SECFailure;
-    }
-
-    ssl_GetSpecReadLock(ss);
-    rv = tls13_ComputeFinished(ss, hashes, PR_FALSE,
-                               finishedBuf, &finishedLen, sizeof(finishedBuf));
-    ssl_ReleaseSpecReadLock(ss);
-    if (rv != SECSuccess) {
-        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-        return SECFailure;
-    }
-
-    if (length != finishedLen) {
-        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_FINISHED, decode_error);
-        return SECFailure;
-    }
-
-    if (NSS_SecureMemcmp(b, finishedBuf, finishedLen) != 0) {
-        FATAL_ERROR(ss, SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE,
-                    decrypt_error);
-        return SECFailure;
-    }
-
-    /* Server is now finished.
-     * Client sends second flight
-     */
-    /* TODO(ekr@rtfm.com): Send NewSession Ticket if server. */
-    if (ss->sec.isServer) {
-        rv = tls13_InstallCipherSpec(ss, InstallCipherSpecRead);
-        if (rv != SECSuccess) {
-            FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-            return SECFailure;
-        }
-
-        rv = tls13_FinishHandshake(ss);
-    } else {
-        if (ss->ssl3.hs.authCertificatePending) {
-            /* TODO(ekr@rtfm.com): Handle pending auth */
-            FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-            PORT_Assert(0);
-            return SECFailure;
-        }
-        rv = tls13_InitCipherSpec(ss, TrafficKeyApplicationData,
-                                  InstallCipherSpecRead);
-        if (rv != SECSuccess) {
-            FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-            return SECFailure;
-        }
-
-        rv = tls13_SendClientSecondRound(ss);
-        if (rv != SECSuccess)
-            return SECFailure; /* Error code and alerts handled below */
-    }
-
-    return rv;
-}
-
-static SECStatus
-tls13_FinishHandshake(sslSocket *ss)
-{
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-    PORT_Assert(ss->ssl3.hs.restartTarget == NULL);
-
-    /* The first handshake is now completed. */
-    ss->handshake = NULL;
-
-    TLS13_SET_HS_STATE(ss, idle_handshake);
-
-    ssl_FinishHandshake(ss);
-
-    return SECSuccess;
-}
-
-static SECStatus
-tls13_SendClientSecondRound(sslSocket *ss)
-{
-    SECStatus rv;
-    PRBool sendClientCert;
-
-    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
-    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    sendClientCert = !ss->ssl3.sendEmptyCert &&
-                     ss->ssl3.clientCertChain != NULL &&
-                     ss->ssl3.clientPrivateKey != NULL;
-
-    /* Defer client authentication sending if we are still
-     * waiting for server authentication. See the long block
-     * comment in ssl3_SendClientSecondRound for more detail.
-     */
-    if (ss->ssl3.hs.restartTarget) {
-        PR_NOT_REACHED("unexpected ss->ssl3.hs.restartTarget");
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        return SECFailure;
-    }
-    if (ss->ssl3.hs.authCertificatePending && (sendClientCert ||
-                                               ss->ssl3.sendEmptyCert)) {
-        SSL_TRC(3, ("%d: TLS13[%p]: deferring ssl3_SendClientSecondRound because"
-                    " certificate authentication is still pending.",
-                    SSL_GETPID(), ss->fd));
-        ss->ssl3.hs.restartTarget = tls13_SendClientSecondRound;
-        return SECWouldBlock;
-    }
-
-    ssl_GetXmitBufLock(ss); /*******************************/
-    if (ss->ssl3.sendEmptyCert) {
-        ss->ssl3.sendEmptyCert = PR_FALSE;
-        rv = ssl3_SendEmptyCertificate(ss);
-        /* Don't send verify */
-        if (rv != SECSuccess) {
-            goto loser; /* error code is set. */
-        }
-    } else if (sendClientCert) {
-        rv = ssl3_SendCertificate(ss);
-        if (rv != SECSuccess) {
-            goto loser; /* error code is set. */
-        }
-    }
-
-    if (sendClientCert) {
-        rv = ssl3_SendCertificateVerify(ss, ss->ssl3.clientPrivateKey);
-        SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
-        ss->ssl3.clientPrivateKey = NULL;
-        if (rv != SECSuccess) {
-            goto loser; /* err is set. */
-        }
-    }
-
-    rv = tls13_SendFinished(ss);
-    if (rv != SECSuccess) {
-        goto loser; /* err code was set. */
-    }
-    ssl_ReleaseXmitBufLock(ss); /*******************************/
-
-    /* The handshake is now finished */
-    return tls13_FinishHandshake(ss);
-
-loser:
-    ssl_ReleaseXmitBufLock(ss); /*******************************/
-    return SECFailure;
-}
-
-static SECStatus
-tls13_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    SECStatus rv;
-
-    rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET,
-                              idle_handshake);
-    if (rv != SECSuccess) {
-        return SECFailure;
-    }
-
-    UNIMPLEMENTED();
-
-    /* Ignore */
-    return SECSuccess;
-}
-
-typedef enum {
-    ExtensionNotUsed,
-    ExtensionClientOnly,
-    ExtensionSendClear,
-    ExtensionSendEncrypted,
-} Tls13ExtensionStatus;
-
-static const struct {
-    SSLExtensionType ex_value;
-    Tls13ExtensionStatus status;
-} KnownExtensions[] = {
-    { ssl_server_name_xtn,
-      ExtensionSendEncrypted },
-    {
-        ssl_cert_status_xtn,
-        ExtensionNotUsed /* TODO(ekr@rtfm.com): Disabled because broken
-                            in TLS 1.3. */
-        /* ExtensionSendEncrypted */
-    },
-    { ssl_elliptic_curves_xtn,
-      ExtensionSendClear },
-    { ssl_ec_point_formats_xtn,
-      ExtensionNotUsed },
-    { ssl_signature_algorithms_xtn,
-      ExtensionClientOnly },
-    { ssl_use_srtp_xtn,
-      ExtensionSendEncrypted },
-    { ssl_app_layer_protocol_xtn,
-      ExtensionSendEncrypted },
-    { ssl_padding_xtn,
-      ExtensionNotUsed },
-    { ssl_extended_master_secret_xtn,
-      ExtensionNotUsed },
-    { ssl_session_ticket_xtn,
-      ExtensionClientOnly },
-    { ssl_tls13_key_share_xtn,
-      ExtensionSendClear },
-    { ssl_next_proto_nego_xtn,
-      ExtensionNotUsed },
-    { ssl_renegotiation_info_xtn,
-      ExtensionNotUsed },
-    { ssl_tls13_draft_version_xtn,
-      ExtensionClientOnly }
-};
-
-PRBool
-tls13_ExtensionAllowed(PRUint16 extension, SSL3HandshakeType message)
-{
-    unsigned int i;
-
-    PORT_Assert((message == client_hello) ||
-                (message == server_hello) ||
-                (message == encrypted_extensions));
-
-    for (i = 0; i < PR_ARRAY_SIZE(KnownExtensions); i++) {
-        if (KnownExtensions[i].ex_value == extension)
-            break;
-    }
-    if (i == PR_ARRAY_SIZE(KnownExtensions)) {
-        /* We have never heard of this extension which is OK on
-         * the server but not the client. */
-        return message == client_hello;
-    }
-
-    switch (KnownExtensions[i].status) {
-        case ExtensionNotUsed:
-            return PR_FALSE;
-        case ExtensionClientOnly:
-            return message == client_hello;
-        case ExtensionSendClear:
-            return message == client_hello ||
-                   message == server_hello;
-        case ExtensionSendEncrypted:
-            return message == client_hello ||
-                   message == encrypted_extensions;
-    }
-
-    PORT_Assert(0);
-
-    /* Not reached */
-    return PR_TRUE;
-}
-
-/* Helper function to encode a uint32 into a buffer */
-unsigned char *
-tls13_EncodeUintX(PRUint32 value, unsigned int bytes, unsigned char *to)
-{
-    PRUint32 encoded;
-
-    PORT_Assert(bytes > 0 && bytes <= 4);
-
-    encoded = PR_htonl(value);
-    memcpy(to, ((unsigned char *)(&encoded)) + (4 - bytes), bytes);
-    return to + bytes;
-}
-
-/* TLS 1.3 doesn't actually have additional data but the aead function
- * signature overloads additional data to carry the record sequence
- * number and that's what we put here. The TLS 1.3 AEAD functions
- * just use this input as the sequence number and not as additional
- * data. */
-static void
-tls13_FormatAdditionalData(unsigned char *aad, unsigned int length,
-                           SSL3SequenceNumber seqNum)
-{
-    unsigned char *ptr = aad;
-
-    PORT_Assert(length == 8);
-    ptr = tls13_EncodeUintX(seqNum.high, 4, ptr);
-    ptr = tls13_EncodeUintX(seqNum.low, 4, ptr);
-    PORT_Assert((ptr - aad) == length);
-}
-
-SECStatus
-tls13_ProtectRecord(sslSocket *ss,
-                    SSL3ContentType type,
-                    const SSL3Opaque *pIn,
-                    PRUint32 contentLen,
-                    sslBuffer *wrBuf)
-{
-    ssl3CipherSpec *cwSpec = ss->ssl3.cwSpec;
-    const ssl3BulkCipherDef *cipher_def = cwSpec->cipher_def;
-    SECStatus rv;
-    PRUint16 headerLen;
-    int cipherBytes = 0;
-    const int tagLen = cipher_def->tag_size;
-
-    SSL_TRC(3, ("%d: TLS13[%d]: protect record of length %u, seq=0x%0x%0x",
-                SSL_GETPID(), ss->fd, contentLen,
-                cwSpec->write_seq_num.high,
-                cwSpec->write_seq_num.low));
-
-    headerLen = IS_DTLS(ss) ? DTLS_RECORD_HEADER_LENGTH : SSL3_RECORD_HEADER_LENGTH;
-
-    if (headerLen + contentLen + 1 + tagLen > wrBuf->space) {
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        return SECFailure;
-    }
-
-    /* Copy the data into the wrBuf. We're going to encrypt in-place
-     * in the AEAD branch anyway */
-    PORT_Memcpy(wrBuf->buf + headerLen, pIn, contentLen);
-
-    if (cipher_def->calg == ssl_calg_null) {
-        /* Shortcut for plaintext */
-        cipherBytes = contentLen;
-    } else {
-        unsigned char aad[8];
-        PORT_Assert(cipher_def->type == type_aead);
-
-        /* Add the content type at the end. */
-        wrBuf->buf[headerLen + contentLen] = type;
-
-        /* Stomp the content type to be application_data */
-        type = content_application_data;
-
-        tls13_FormatAdditionalData(aad, sizeof(aad),
-                                   cwSpec->write_seq_num);
-        cipherBytes = contentLen + 1; /* Room for the content type on the end. */
-        rv = cwSpec->aead(
-            ss->sec.isServer ? &cwSpec->server : &cwSpec->client,
-            PR_FALSE,                               /* do encrypt */
-            wrBuf->buf + headerLen,                 /* output  */
-            &cipherBytes,                           /* out len */
-            wrBuf->space - headerLen,               /* max out */
-            wrBuf->buf + headerLen, contentLen + 1, /* input   */
-            aad, sizeof(aad));
-        if (rv != SECSuccess) {
-            PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
-            return SECFailure;
-        }
-    }
-
-    PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 256);
-
-    wrBuf->len = cipherBytes + headerLen;
-    wrBuf->buf[0] = type;
-
-    if (IS_DTLS(ss)) {
-        (void)tls13_EncodeUintX(2, dtls_TLSVersionToDTLSVersion(kRecordVersion),
-                                &wrBuf->buf[1]);
-        (void)tls13_EncodeUintX(cwSpec->write_seq_num.high, 4, &wrBuf->buf[3]);
-        (void)tls13_EncodeUintX(cwSpec->write_seq_num.low, 4, &wrBuf->buf[7]);
-        (void)tls13_EncodeUintX(cipherBytes, 2, &wrBuf->buf[11]);
-    } else {
-        (void)tls13_EncodeUintX(kRecordVersion, 2, &wrBuf->buf[1]);
-        (void)tls13_EncodeUintX(cipherBytes, 2, &wrBuf->buf[3]);
-    }
-    ssl3_BumpSequenceNumber(&cwSpec->write_seq_num);
-
-    return SECSuccess;
-}
-
-/* Unprotect a TLS 1.3 record and leave the result in plaintext.
- *
- * Called by ssl3_HandleRecord. Caller must hold the spec read lock.
- * Therefore, we MUST not call SSL3_SendAlert().
- *
- * If SECFailure is returned, we:
- * 1. Set |*alert| to the alert to be sent.
- * 2. Call PORT_SetError() witn an appropriate code.
- */
-SECStatus
-tls13_UnprotectRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *plaintext,
-                      SSL3AlertDescription *alert)
-{
-    ssl3CipherSpec *crSpec = ss->ssl3.crSpec;
-    const ssl3BulkCipherDef *cipher_def = crSpec->cipher_def;
-    unsigned char aad[8];
-    SECStatus rv;
-
-    *alert = bad_record_mac; /* Default alert for most issues. */
-
-    SSL_TRC(3, ("%d: TLS13[%d]: unprotect record of length %u",
-                SSL_GETPID(), ss->fd, cText->buf->len));
-
-    /* We can perform this test in variable time because the record's total
-     * length and the ciphersuite are both public knowledge. */
-    if (cText->buf->len < cipher_def->tag_size) {
-        PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
-        return SECFailure;
-    }
-
-    /* Verify that the content type is right, even though we overwrite it. */
-    if (cText->type != content_application_data) {
-        /* Do we need a better error here? */
-        PORT_SetError(SSL_ERROR_BAD_MAC_READ);
-        return SECFailure;
-    }
-
-    /* Check the version number in the record */
-    if (cText->version != kRecordVersion) {
-        /* Do we need a better error here? */
-        PORT_SetError(SSL_ERROR_BAD_MAC_READ);
-        return SECFailure;
-    }
-
-    /* Decrypt */
-    PORT_Assert(cipher_def->type == type_aead);
-    tls13_FormatAdditionalData(aad, sizeof(aad),
-                               IS_DTLS(ss) ? cText->seq_num
-                                           : crSpec->read_seq_num);
-    rv = crSpec->aead(
-        ss->sec.isServer ? &crSpec->client : &crSpec->server,
-        PR_TRUE,                /* do decrypt */
-        plaintext->buf,         /* out */
-        (int *)&plaintext->len, /* outlen */
-        plaintext->space,       /* maxout */
-        cText->buf->buf,        /* in */
-        cText->buf->len,        /* inlen */
-        aad, sizeof(aad));
-    if (rv != SECSuccess) {
-        PORT_SetError(SSL_ERROR_BAD_MAC_READ);
-        return SECFailure;
-    }
-
-    /* The record is right-padded with 0s, followed by the true
-     * content type, so read from the right until we receive a
-     * nonzero byte. */
-    while (plaintext->len > 0 && !(plaintext->buf[plaintext->len - 1])) {
-        --plaintext->len;
-    }
-
-    /* Bogus padding. */
-    if (plaintext->len < 1) {
-        /* It's safe to report this specifically because it happened
-         * after the MAC has been verified. */
-        PORT_SetError(SSL_ERROR_BAD_BLOCK_PADDING);
-        return SECFailure;
-    }
-
-    /* Record the type. */
-    cText->type = plaintext->buf[plaintext->len - 1];
-    --plaintext->len;
-
-    return SECSuccess;
-}
diff --git a/net/third_party/nss/ssl/tls13con.h b/net/third_party/nss/ssl/tls13con.h
deleted file mode 100644
index a96d3236..0000000
--- a/net/third_party/nss/ssl/tls13con.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is PRIVATE to SSL.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef __tls13con_h_
-#define __tls13con_h_
-
-typedef enum {
-    StaticSharedSecret,
-    EphemeralSharedSecret
-} SharedSecretType;
-
-SECStatus tls13_UnprotectRecord(
-    sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *plaintext,
-    SSL3AlertDescription *alert);
-unsigned char *
-tls13_EncodeUintX(PRUint32 value, unsigned int bytes, unsigned char *to);
-
-#if defined(WIN32)
-#define __func__ __FUNCTION__
-#endif
-
-void tls13_SetHsState(sslSocket *ss, SSL3WaitState ws,
-                      const char *func, const char *file, int line);
-#define TLS13_SET_HS_STATE(ss, ws) \
-    tls13_SetHsState(ss, ws, __func__, __FILE__, __LINE__)
-
-/* Return PR_TRUE if the socket is in one of the given states, else return
- * PR_FALSE. Only call the macro not the function, because the trailing
- * wait_invalid is needed to terminate the argument list. */
-PRBool tls13_InHsState(sslSocket *ss, ...);
-#define TLS13_IN_HS_STATE(ss, ...) \
-    tls13_InHsState(ss, __VA_ARGS__, wait_invalid)
-
-SSLHashType tls13_GetHash(sslSocket *ss);
-CK_MECHANISM_TYPE tls13_GetHkdfMechanism(sslSocket *ss);
-void tls13_FatalError(sslSocket *ss, PRErrorCode prError,
-                      SSL3AlertDescription desc);
-SECStatus tls13_SetupClientHello(sslSocket *ss);
-SECStatus tls13_HandlePostHelloHandshakeMessage(sslSocket *ss, SSL3Opaque *b,
-                                                PRUint32 length,
-                                                SSL3Hashes *hashesPtr);
-SECStatus tls13_HandleClientKeyShare(sslSocket *ss);
-SECStatus tls13_SendServerHelloSequence(sslSocket *ss);
-SECStatus tls13_HandleServerKeyShare(sslSocket *ss);
-SECStatus tls13_AddContextToHashes(sslSocket *ss,
-                                   SSL3Hashes *hashes /* IN/OUT */,
-                                   SSLHashType algorithm, PRBool sending);
-void tls13_DestroyKeyShareEntry(TLS13KeyShareEntry *entry);
-void tls13_DestroyKeyShares(PRCList *list);
-PRBool tls13_ExtensionAllowed(PRUint16 extension, SSL3HandshakeType message);
-SECStatus tls13_ProtectRecord(sslSocket *ss,
-                              SSL3ContentType type,
-                              const SSL3Opaque *pIn,
-                              PRUint32 contentLen,
-                              sslBuffer *wrBuf);
-
-#endif /* __tls13con_h_ */
diff --git a/net/third_party/nss/ssl/tls13hkdf.c b/net/third_party/nss/ssl/tls13hkdf.c
deleted file mode 100644
index 3dc2d1b..0000000
--- a/net/third_party/nss/ssl/tls13hkdf.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * TLS 1.3 Protocol
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "keyhi.h"
-#include "pk11func.h"
-#include "secitem.h"
-#include "sslt.h"
-#include "sslerr.h"
-
-// TODO(ekr@rtfm.com): Export this separately.
-unsigned char *tls13_EncodeUintX(PRUint32 value, unsigned int bytes, unsigned char *to);
-
-/* This table contains the mapping between TLS hash identifiers and the
- * PKCS#11 identifiers */
-static const struct {
-    SSLHashType hash;
-    CK_MECHANISM_TYPE pkcs11Mech;
-    unsigned int hashSize;
-} kTlsHkdfInfo[] = {
-    { ssl_hash_none, 0, 0 },
-    { ssl_hash_md5, 0, 0 },
-    { ssl_hash_sha1, 0, 0 },
-    { ssl_hash_sha224, 0 },
-    { ssl_hash_sha256, CKM_NSS_HKDF_SHA256, 32 },
-    { ssl_hash_sha384, CKM_NSS_HKDF_SHA384, 48 },
-    { ssl_hash_sha512, CKM_NSS_HKDF_SHA512, 64 }
-};
-
-SECStatus
-tls13_HkdfExtract(PK11SymKey *ikm1, PK11SymKey *ikm2, SSLHashType baseHash,
-                  PK11SymKey **prkp)
-{
-    CK_NSS_HKDFParams params;
-    SECItem paramsi;
-    SECStatus rv;
-    SECItem *salt;
-    PK11SymKey *prk;
-
-    params.bExtract = CK_TRUE;
-    params.bExpand = CK_FALSE;
-    params.pInfo = NULL;
-    params.ulInfoLen = 0UL;
-
-    if (ikm1) {
-        /* TODO(ekr@rtfm.com): This violates the PKCS#11 key boundary
-         * but is imposed on us by the present HKDF interface. */
-        rv = PK11_ExtractKeyValue(ikm1);
-        if (rv != SECSuccess)
-            return rv;
-
-        salt = PK11_GetKeyData(ikm1);
-        if (!salt)
-            return SECFailure;
-
-        params.pSalt = salt->data;
-        params.ulSaltLen = salt->len;
-        PORT_Assert(salt->len > 0);
-    } else {
-        /* Per documentation for CKM_NSS_HKDF_*:
-         *
-         *  If the optional salt is given, it is used; otherwise, the salt is
-         *  set to a sequence of zeros equal in length to the HMAC output.
-         */
-        params.pSalt = NULL;
-        params.ulSaltLen = 0UL;
-    }
-    paramsi.data = (unsigned char *)&params;
-    paramsi.len = sizeof(params);
-
-    PORT_Assert(kTlsHkdfInfo[baseHash].pkcs11Mech);
-    PORT_Assert(kTlsHkdfInfo[baseHash].hashSize);
-    PORT_Assert(kTlsHkdfInfo[baseHash].hash == baseHash);
-    prk = PK11_Derive(ikm2, kTlsHkdfInfo[baseHash].pkcs11Mech,
-                      &paramsi, kTlsHkdfInfo[baseHash].pkcs11Mech,
-                      CKA_DERIVE, kTlsHkdfInfo[baseHash].hashSize);
-    if (!prk)
-        return SECFailure;
-
-    *prkp = prk;
-    return SECSuccess;
-}
-
-SECStatus
-tls13_HkdfExpandLabel(PK11SymKey *prk, SSLHashType baseHash,
-                      const PRUint8 *handshakeHash, unsigned int handshakeHashLen,
-                      const char *label, unsigned int labelLen,
-                      CK_MECHANISM_TYPE algorithm, unsigned int keySize,
-                      PK11SymKey **keyp)
-{
-    CK_NSS_HKDFParams params;
-    SECItem paramsi = { siBuffer, NULL, 0 };
-    PRUint8 info[100];
-    PRUint8 *ptr = info;
-    unsigned int infoLen;
-    PK11SymKey *derived;
-    const char *kLabelPrefix = "TLS 1.3, ";
-    const unsigned int kLabelPrefixLen = strlen(kLabelPrefix);
-
-    if (handshakeHash) {
-        PORT_Assert(handshakeHashLen == kTlsHkdfInfo[baseHash].hashSize);
-    } else {
-        PORT_Assert(!handshakeHashLen);
-    }
-
-    /*
-     *  [draft-ietf-tls-tls13-11] Section 7.1:
-     *
-     *  HKDF-Expand-Label(Secret, Label, HashValue, Length) =
-     *       HKDF-Expand(Secret, HkdfLabel, Length)
-     *
-     *  Where HkdfLabel is specified as:
-     *
-     *  struct HkdfLabel {
-     *    uint16 length;
-     *    opaque label<9..255>;
-     *    opaque hash_value<0..255>;
-     *  };
-     *
-     *  Where:
-     *  - HkdfLabel.length is Length
-     *  - HkdfLabel.hash_value is HashValue.
-     *  - HkdfLabel.label is "TLS 1.3, " + Label
-     *
-     */
-    infoLen = 2 + 1 + kLabelPrefixLen + labelLen + 1 + handshakeHashLen;
-    if (infoLen > sizeof(info)) {
-        PORT_Assert(0);
-        goto abort;
-    }
-
-    ptr = tls13_EncodeUintX(keySize, 2, ptr);
-    ptr = tls13_EncodeUintX(labelLen + kLabelPrefixLen, 1, ptr);
-    PORT_Memcpy(ptr, kLabelPrefix, kLabelPrefixLen);
-    ptr += kLabelPrefixLen;
-    PORT_Memcpy(ptr, label, labelLen);
-    ptr += labelLen;
-    ptr = tls13_EncodeUintX(handshakeHashLen, 1, ptr);
-    if (handshakeHash) {
-        PORT_Memcpy(ptr, handshakeHash, handshakeHashLen);
-        ptr += handshakeHashLen;
-    }
-    PORT_Assert((ptr - info) == infoLen);
-
-    params.bExtract = CK_FALSE;
-    params.bExpand = CK_TRUE;
-    params.pInfo = info;
-    params.ulInfoLen = infoLen;
-    paramsi.data = (unsigned char *)&params;
-    paramsi.len = sizeof(params);
-
-    derived = PK11_DeriveWithFlags(prk, kTlsHkdfInfo[baseHash].pkcs11Mech,
-                                   &paramsi, algorithm,
-                                   CKA_DERIVE, keySize,
-                                   CKF_SIGN | CKF_VERIFY);
-    if (!derived)
-        return SECFailure;
-
-    *keyp = derived;
-
-    return SECSuccess;
-
-abort:
-    PORT_SetError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
-    return SECFailure;
-}
-
-SECStatus
-tls13_HkdfExpandLabelRaw(PK11SymKey *prk, SSLHashType baseHash,
-                         const PRUint8 *handshakeHash, unsigned int handshakeHashLen,
-                         const char *label, unsigned int labelLen,
-                         unsigned char *output, unsigned int outputLen)
-{
-    PK11SymKey *derived = NULL;
-    SECItem *rawkey;
-    SECStatus rv;
-
-    rv = tls13_HkdfExpandLabel(prk, baseHash, handshakeHash, handshakeHashLen,
-                               label, labelLen,
-                               kTlsHkdfInfo[baseHash].pkcs11Mech, outputLen,
-                               &derived);
-    if (rv != SECSuccess || !derived) {
-        goto abort;
-    }
-
-    rv = PK11_ExtractKeyValue(derived);
-    if (rv != SECSuccess) {
-        goto abort;
-    }
-
-    rawkey = PK11_GetKeyData(derived);
-    if (!rawkey) {
-        goto abort;
-    }
-
-    PORT_Assert(rawkey->len == outputLen);
-    memcpy(output, rawkey->data, outputLen);
-    PK11_FreeSymKey(derived);
-
-    return SECSuccess;
-
-abort:
-    if (derived) {
-        PK11_FreeSymKey(derived);
-    }
-    PORT_SetError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
-    return SECFailure;
-}
diff --git a/net/third_party/nss/ssl/tls13hkdf.h b/net/third_party/nss/ssl/tls13hkdf.h
deleted file mode 100644
index 78347a11..0000000
--- a/net/third_party/nss/ssl/tls13hkdf.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is PRIVATE to SSL.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef __tls13hkdf_h_
-#define __tls13hkdf_h_
-
-#include "keyhi.h"
-#include "sslt.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-SECStatus tls13_HkdfExtract(
-    PK11SymKey *ikm1, PK11SymKey *ikm2, SSLHashType baseHash,
-    PK11SymKey **prkp);
-SECStatus tls13_HkdfExpandLabelRaw(
-    PK11SymKey *prk, SSLHashType baseHash,
-    const PRUint8 *handshakeHash, unsigned int handshakeHashLen,
-    const char *label, unsigned int labelLen,
-    unsigned char *output, unsigned int outputLen);
-SECStatus tls13_HkdfExpandLabel(
-    PK11SymKey *prk, SSLHashType baseHash,
-    const PRUint8 *handshakeHash, unsigned int handshakeHashLen,
-    const char *label, unsigned int labelLen,
-    CK_MECHANISM_TYPE algorithm, unsigned int keySize,
-    PK11SymKey **keyp);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/net/third_party/nss/ssl/unix_err.c b/net/third_party/nss/ssl/unix_err.c
deleted file mode 100644
index ca0b0507..0000000
--- a/net/third_party/nss/ssl/unix_err.c
+++ /dev/null
@@ -1,837 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/*
- * This file essentially replicates NSPR's source for the functions that
- * map system-specific error codes to NSPR error codes.  We would use
- * NSPR's functions, instead of duplicating them, but they're private.
- * As long as SSL's server session cache code must do platform native I/O
- * to accomplish its job, and NSPR's error mapping functions remain private,
- * this code will continue to need to be replicated.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#if 0
-#include "primpl.h"
-#else
-#define _PR_POLL_AVAILABLE 1
-#include "prerror.h"
-#endif
-
-#if defined(__bsdi__) || defined(NTO) || defined(DARWIN) || defined(BEOS)
-#undef _PR_POLL_AVAILABLE
-#endif
-
-#if defined(_PR_POLL_AVAILABLE)
-#include <poll.h>
-#endif
-#include <errno.h>
-
-/* forward declarations. */
-void nss_MD_unix_map_default_error(int err);
-
-void
-nss_MD_unix_map_opendir_error(int err)
-{
-    nss_MD_unix_map_default_error(err);
-}
-
-void
-nss_MD_unix_map_closedir_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case EINVAL:
-            prError = PR_BAD_DESCRIPTOR_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_readdir_error(int err)
-{
-    PRErrorCode prError;
-
-    switch (err) {
-        case ENOENT:
-            prError = PR_NO_MORE_FILES_ERROR;
-            break;
-#ifdef EOVERFLOW
-        case EOVERFLOW:
-            prError = PR_IO_ERROR;
-            break;
-#endif
-        case EINVAL:
-            prError = PR_IO_ERROR;
-            break;
-        case ENXIO:
-            prError = PR_IO_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_unlink_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case EPERM:
-            prError = PR_IS_DIRECTORY_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_stat_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case ETIMEDOUT:
-            prError = PR_REMOTE_FILE_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_fstat_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case ETIMEDOUT:
-            prError = PR_REMOTE_FILE_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_rename_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case EEXIST:
-            prError = PR_DIRECTORY_NOT_EMPTY_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_access_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case ETIMEDOUT:
-            prError = PR_REMOTE_FILE_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_mkdir_error(int err)
-{
-    nss_MD_unix_map_default_error(err);
-}
-
-void
-nss_MD_unix_map_rmdir_error(int err)
-{
-    PRErrorCode prError;
-
-    switch (err) {
-        case EEXIST:
-            prError = PR_DIRECTORY_NOT_EMPTY_ERROR;
-            break;
-        case EINVAL:
-            prError = PR_DIRECTORY_NOT_EMPTY_ERROR;
-            break;
-        case ETIMEDOUT:
-            prError = PR_REMOTE_FILE_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_read_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case EINVAL:
-            prError = PR_INVALID_METHOD_ERROR;
-            break;
-        case ENXIO:
-            prError = PR_INVALID_ARGUMENT_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_write_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case EINVAL:
-            prError = PR_INVALID_METHOD_ERROR;
-            break;
-        case ENXIO:
-            prError = PR_INVALID_METHOD_ERROR;
-            break;
-        case ETIMEDOUT:
-            prError = PR_REMOTE_FILE_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_lseek_error(int err)
-{
-    nss_MD_unix_map_default_error(err);
-}
-
-void
-nss_MD_unix_map_fsync_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case ETIMEDOUT:
-            prError = PR_REMOTE_FILE_ERROR;
-            break;
-        case EINVAL:
-            prError = PR_INVALID_METHOD_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_close_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case ETIMEDOUT:
-            prError = PR_REMOTE_FILE_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_socket_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case ENOMEM:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_socketavailable_error(int err)
-{
-    PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
-}
-
-void
-nss_MD_unix_map_recv_error(int err)
-{
-    nss_MD_unix_map_default_error(err);
-}
-
-void
-nss_MD_unix_map_recvfrom_error(int err)
-{
-    nss_MD_unix_map_default_error(err);
-}
-
-void
-nss_MD_unix_map_send_error(int err)
-{
-    nss_MD_unix_map_default_error(err);
-}
-
-void
-nss_MD_unix_map_sendto_error(int err)
-{
-    nss_MD_unix_map_default_error(err);
-}
-
-void
-nss_MD_unix_map_writev_error(int err)
-{
-    nss_MD_unix_map_default_error(err);
-}
-
-void
-nss_MD_unix_map_accept_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case ENODEV:
-            prError = PR_NOT_TCP_SOCKET_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_connect_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case EACCES:
-            prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
-            break;
-#if defined(UNIXWARE) || defined(SNI) || defined(NEC)
-        /*
-         * On some platforms, if we connect to a port on the local host
-         * (the loopback address) that no process is listening on, we get
-         * EIO instead of ECONNREFUSED.
-         */
-        case EIO:
-            prError = PR_CONNECT_REFUSED_ERROR;
-            break;
-#endif
-        case ELOOP:
-            prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
-            break;
-        case ENOENT:
-            prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
-            break;
-        case ENXIO:
-            prError = PR_IO_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_bind_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case EINVAL:
-            prError = PR_SOCKET_ADDRESS_IS_BOUND_ERROR;
-            break;
-            /*
-             * UNIX domain sockets are not supported in NSPR
-             */
-        case EIO:
-            prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
-            break;
-        case EISDIR:
-            prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
-            break;
-        case ELOOP:
-            prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
-            break;
-        case ENOENT:
-            prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
-            break;
-        case ENOTDIR:
-            prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
-            break;
-        case EROFS:
-            prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_listen_error(int err)
-{
-    nss_MD_unix_map_default_error(err);
-}
-
-void
-nss_MD_unix_map_shutdown_error(int err)
-{
-    nss_MD_unix_map_default_error(err);
-}
-
-void
-nss_MD_unix_map_socketpair_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case ENOMEM:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_getsockname_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case ENOMEM:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_getpeername_error(int err)
-{
-    PRErrorCode prError;
-
-    switch (err) {
-        case ENOMEM:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_getsockopt_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case EINVAL:
-            prError = PR_BUFFER_OVERFLOW_ERROR;
-            break;
-        case ENOMEM:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_setsockopt_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case EINVAL:
-            prError = PR_BUFFER_OVERFLOW_ERROR;
-            break;
-        case ENOMEM:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_open_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case EAGAIN:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-        case EBUSY:
-            prError = PR_IO_ERROR;
-            break;
-        case ENODEV:
-            prError = PR_FILE_NOT_FOUND_ERROR;
-            break;
-        case ENOMEM:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-        case ETIMEDOUT:
-            prError = PR_REMOTE_FILE_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_mmap_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case EAGAIN:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-        case EMFILE:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-        case ENODEV:
-            prError = PR_OPERATION_NOT_SUPPORTED_ERROR;
-            break;
-        case ENXIO:
-            prError = PR_INVALID_ARGUMENT_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_gethostname_error(int err)
-{
-    nss_MD_unix_map_default_error(err);
-}
-
-void
-nss_MD_unix_map_select_error(int err)
-{
-    nss_MD_unix_map_default_error(err);
-}
-
-#ifdef _PR_POLL_AVAILABLE
-void
-nss_MD_unix_map_poll_error(int err)
-{
-    PRErrorCode prError;
-
-    switch (err) {
-        case EAGAIN:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_poll_revents_error(int err)
-{
-    if (err & POLLNVAL)
-        PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
-    else if (err & POLLHUP)
-        PR_SetError(PR_CONNECT_RESET_ERROR, EPIPE);
-    else if (err & POLLERR)
-        PR_SetError(PR_IO_ERROR, EIO);
-    else
-        PR_SetError(PR_UNKNOWN_ERROR, err);
-}
-#endif /* _PR_POLL_AVAILABLE */
-
-void
-nss_MD_unix_map_flock_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case EINVAL:
-            prError = PR_BAD_DESCRIPTOR_ERROR;
-            break;
-        case EWOULDBLOCK:
-            prError = PR_FILE_IS_LOCKED_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_unix_map_lockf_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case EACCES:
-            prError = PR_FILE_IS_LOCKED_ERROR;
-            break;
-        case EDEADLK:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-        default:
-            nss_MD_unix_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-#ifdef HPUX11
-void
-nss_MD_hpux_map_sendfile_error(int err)
-{
-    nss_MD_unix_map_default_error(err);
-}
-#endif /* HPUX11 */
-
-void
-nss_MD_unix_map_default_error(int err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case EACCES:
-            prError = PR_NO_ACCESS_RIGHTS_ERROR;
-            break;
-        case EADDRINUSE:
-            prError = PR_ADDRESS_IN_USE_ERROR;
-            break;
-        case EADDRNOTAVAIL:
-            prError = PR_ADDRESS_NOT_AVAILABLE_ERROR;
-            break;
-        case EAFNOSUPPORT:
-            prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
-            break;
-        case EAGAIN:
-            prError = PR_WOULD_BLOCK_ERROR;
-            break;
-    /*
-     * On QNX and Neutrino, EALREADY is defined as EBUSY.
-     */
-#if EALREADY != EBUSY
-        case EALREADY:
-            prError = PR_ALREADY_INITIATED_ERROR;
-            break;
-#endif
-        case EBADF:
-            prError = PR_BAD_DESCRIPTOR_ERROR;
-            break;
-#ifdef EBADMSG
-        case EBADMSG:
-            prError = PR_IO_ERROR;
-            break;
-#endif
-        case EBUSY:
-            prError = PR_FILESYSTEM_MOUNTED_ERROR;
-            break;
-        case ECONNREFUSED:
-            prError = PR_CONNECT_REFUSED_ERROR;
-            break;
-        case ECONNRESET:
-            prError = PR_CONNECT_RESET_ERROR;
-            break;
-        case EDEADLK:
-            prError = PR_DEADLOCK_ERROR;
-            break;
-#ifdef EDIRCORRUPTED
-        case EDIRCORRUPTED:
-            prError = PR_DIRECTORY_CORRUPTED_ERROR;
-            break;
-#endif
-#ifdef EDQUOT
-        case EDQUOT:
-            prError = PR_NO_DEVICE_SPACE_ERROR;
-            break;
-#endif
-        case EEXIST:
-            prError = PR_FILE_EXISTS_ERROR;
-            break;
-        case EFAULT:
-            prError = PR_ACCESS_FAULT_ERROR;
-            break;
-        case EFBIG:
-            prError = PR_FILE_TOO_BIG_ERROR;
-            break;
-        case EINPROGRESS:
-            prError = PR_IN_PROGRESS_ERROR;
-            break;
-        case EINTR:
-            prError = PR_PENDING_INTERRUPT_ERROR;
-            break;
-        case EINVAL:
-            prError = PR_INVALID_ARGUMENT_ERROR;
-            break;
-        case EIO:
-            prError = PR_IO_ERROR;
-            break;
-        case EISCONN:
-            prError = PR_IS_CONNECTED_ERROR;
-            break;
-        case EISDIR:
-            prError = PR_IS_DIRECTORY_ERROR;
-            break;
-        case ELOOP:
-            prError = PR_LOOP_ERROR;
-            break;
-        case EMFILE:
-            prError = PR_PROC_DESC_TABLE_FULL_ERROR;
-            break;
-        case EMLINK:
-            prError = PR_MAX_DIRECTORY_ENTRIES_ERROR;
-            break;
-        case EMSGSIZE:
-            prError = PR_INVALID_ARGUMENT_ERROR;
-            break;
-#ifdef EMULTIHOP
-        case EMULTIHOP:
-            prError = PR_REMOTE_FILE_ERROR;
-            break;
-#endif
-        case ENAMETOOLONG:
-            prError = PR_NAME_TOO_LONG_ERROR;
-            break;
-        case ENETUNREACH:
-            prError = PR_NETWORK_UNREACHABLE_ERROR;
-            break;
-        case ENFILE:
-            prError = PR_SYS_DESC_TABLE_FULL_ERROR;
-            break;
-#if !defined(SCO)
-        case ENOBUFS:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-#endif
-        case ENODEV:
-            prError = PR_FILE_NOT_FOUND_ERROR;
-            break;
-        case ENOENT:
-            prError = PR_FILE_NOT_FOUND_ERROR;
-            break;
-        case ENOLCK:
-            prError = PR_FILE_IS_LOCKED_ERROR;
-            break;
-#ifdef ENOLINK
-        case ENOLINK:
-            prError = PR_REMOTE_FILE_ERROR;
-            break;
-#endif
-        case ENOMEM:
-            prError = PR_OUT_OF_MEMORY_ERROR;
-            break;
-        case ENOPROTOOPT:
-            prError = PR_INVALID_ARGUMENT_ERROR;
-            break;
-        case ENOSPC:
-            prError = PR_NO_DEVICE_SPACE_ERROR;
-            break;
-#ifdef ENOSR
-        case ENOSR:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-#endif
-        case ENOTCONN:
-            prError = PR_NOT_CONNECTED_ERROR;
-            break;
-        case ENOTDIR:
-            prError = PR_NOT_DIRECTORY_ERROR;
-            break;
-        case ENOTSOCK:
-            prError = PR_NOT_SOCKET_ERROR;
-            break;
-        case ENXIO:
-            prError = PR_FILE_NOT_FOUND_ERROR;
-            break;
-        case EOPNOTSUPP:
-            prError = PR_NOT_TCP_SOCKET_ERROR;
-            break;
-#ifdef EOVERFLOW
-        case EOVERFLOW:
-            prError = PR_BUFFER_OVERFLOW_ERROR;
-            break;
-#endif
-        case EPERM:
-            prError = PR_NO_ACCESS_RIGHTS_ERROR;
-            break;
-        case EPIPE:
-            prError = PR_CONNECT_RESET_ERROR;
-            break;
-#ifdef EPROTO
-        case EPROTO:
-            prError = PR_IO_ERROR;
-            break;
-#endif
-        case EPROTONOSUPPORT:
-            prError = PR_PROTOCOL_NOT_SUPPORTED_ERROR;
-            break;
-        case EPROTOTYPE:
-            prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
-            break;
-        case ERANGE:
-            prError = PR_INVALID_METHOD_ERROR;
-            break;
-        case EROFS:
-            prError = PR_READ_ONLY_FILESYSTEM_ERROR;
-            break;
-        case ESPIPE:
-            prError = PR_INVALID_METHOD_ERROR;
-            break;
-        case ETIMEDOUT:
-            prError = PR_IO_TIMEOUT_ERROR;
-            break;
-#if EWOULDBLOCK != EAGAIN
-        case EWOULDBLOCK:
-            prError = PR_WOULD_BLOCK_ERROR;
-            break;
-#endif
-        case EXDEV:
-            prError = PR_NOT_SAME_DEVICE_ERROR;
-            break;
-
-        default:
-            prError = PR_UNKNOWN_ERROR;
-            break;
-    }
-    PR_SetError(prError, err);
-}
diff --git a/net/third_party/nss/ssl/unix_err.h b/net/third_party/nss/ssl/unix_err.h
deleted file mode 100644
index 5d7d547..0000000
--- a/net/third_party/nss/ssl/unix_err.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * This file essentially replicates NSPR's source for the functions that
- * map system-specific error codes to NSPR error codes.  We would use
- * NSPR's functions, instead of duplicating them, but they're private.
- * As long as SSL's server session cache code must do platform native I/O
- * to accomplish its job, and NSPR's error mapping functions remain private,
- * this code will continue to need to be replicated.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*  NSPR doesn't make these functions public, so we have to duplicate
-**  them in NSS.
-*/
-extern void nss_MD_hpux_map_sendfile_error(int err);
-extern void nss_MD_unix_map_accept_error(int err);
-extern void nss_MD_unix_map_access_error(int err);
-extern void nss_MD_unix_map_bind_error(int err);
-extern void nss_MD_unix_map_close_error(int err);
-extern void nss_MD_unix_map_closedir_error(int err);
-extern void nss_MD_unix_map_connect_error(int err);
-extern void nss_MD_unix_map_default_error(int err);
-extern void nss_MD_unix_map_flock_error(int err);
-extern void nss_MD_unix_map_fstat_error(int err);
-extern void nss_MD_unix_map_fsync_error(int err);
-extern void nss_MD_unix_map_gethostname_error(int err);
-extern void nss_MD_unix_map_getpeername_error(int err);
-extern void nss_MD_unix_map_getsockname_error(int err);
-extern void nss_MD_unix_map_getsockopt_error(int err);
-extern void nss_MD_unix_map_listen_error(int err);
-extern void nss_MD_unix_map_lockf_error(int err);
-extern void nss_MD_unix_map_lseek_error(int err);
-extern void nss_MD_unix_map_mkdir_error(int err);
-extern void nss_MD_unix_map_mmap_error(int err);
-extern void nss_MD_unix_map_open_error(int err);
-extern void nss_MD_unix_map_opendir_error(int err);
-extern void nss_MD_unix_map_poll_error(int err);
-extern void nss_MD_unix_map_poll_revents_error(int err);
-extern void nss_MD_unix_map_read_error(int err);
-extern void nss_MD_unix_map_readdir_error(int err);
-extern void nss_MD_unix_map_recv_error(int err);
-extern void nss_MD_unix_map_recvfrom_error(int err);
-extern void nss_MD_unix_map_rename_error(int err);
-extern void nss_MD_unix_map_rmdir_error(int err);
-extern void nss_MD_unix_map_select_error(int err);
-extern void nss_MD_unix_map_send_error(int err);
-extern void nss_MD_unix_map_sendto_error(int err);
-extern void nss_MD_unix_map_setsockopt_error(int err);
-extern void nss_MD_unix_map_shutdown_error(int err);
-extern void nss_MD_unix_map_socket_error(int err);
-extern void nss_MD_unix_map_socketavailable_error(int err);
-extern void nss_MD_unix_map_socketpair_error(int err);
-extern void nss_MD_unix_map_stat_error(int err);
-extern void nss_MD_unix_map_unlink_error(int err);
-extern void nss_MD_unix_map_write_error(int err);
-extern void nss_MD_unix_map_writev_error(int err);
diff --git a/net/third_party/nss/ssl/win32err.c b/net/third_party/nss/ssl/win32err.c
deleted file mode 100644
index caa12b956..0000000
--- a/net/third_party/nss/ssl/win32err.c
+++ /dev/null
@@ -1,550 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/*
- * This file essentially replicates NSPR's source for the functions that
- * map system-specific error codes to NSPR error codes.  We would use
- * NSPR's functions, instead of duplicating them, but they're private.
- * As long as SSL's server session cache code must do platform native I/O
- * to accomplish its job, and NSPR's error mapping functions remain private,
- * this code will continue to need to be replicated.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "prerror.h"
-#include "prlog.h"
-#include <errno.h>
-#include <windows.h>
-
-/*
- * On Win32, we map three kinds of error codes:
- * - GetLastError(): for Win32 functions
- * - WSAGetLastError(): for Winsock functions
- * - errno: for standard C library functions
- *
- * We do not check for WSAEINPROGRESS and WSAEINTR because we do not
- * use blocking Winsock 1.1 calls.
- *
- * Except for the 'socket' call, we do not check for WSAEINITIALISED.
- * It is assumed that if Winsock is not initialized, that fact will
- * be detected at the time we create new sockets.
- */
-
-/* forward declaration. */
-void nss_MD_win32_map_default_error(PRInt32 err);
-
-void
-nss_MD_win32_map_opendir_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_closedir_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_readdir_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_delete_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-/* The error code for stat() is in errno. */
-void
-nss_MD_win32_map_stat_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_fstat_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_rename_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-/* The error code for access() is in errno. */
-void
-nss_MD_win32_map_access_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_mkdir_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_rmdir_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_read_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_transmitfile_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_write_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_lseek_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_fsync_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-/*
- * For both CloseHandle() and closesocket().
- */
-void
-nss_MD_win32_map_close_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_socket_error(PRInt32 err)
-{
-    PR_ASSERT(err != WSANOTINITIALISED);
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_recv_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_recvfrom_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_send_error(PRInt32 err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case WSAEMSGSIZE:
-            prError = PR_INVALID_ARGUMENT_ERROR;
-            break;
-        default:
-            nss_MD_win32_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_win32_map_sendto_error(PRInt32 err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case WSAEMSGSIZE:
-            prError = PR_INVALID_ARGUMENT_ERROR;
-            break;
-        default:
-            nss_MD_win32_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_win32_map_accept_error(PRInt32 err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case WSAEOPNOTSUPP:
-            prError = PR_NOT_TCP_SOCKET_ERROR;
-            break;
-        case WSAEINVAL:
-            prError = PR_INVALID_STATE_ERROR;
-            break;
-        default:
-            nss_MD_win32_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_win32_map_acceptex_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_connect_error(PRInt32 err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case WSAEWOULDBLOCK:
-            prError = PR_IN_PROGRESS_ERROR;
-            break;
-        case WSAEINVAL:
-            prError = PR_ALREADY_INITIATED_ERROR;
-            break;
-        case WSAETIMEDOUT:
-            prError = PR_IO_TIMEOUT_ERROR;
-            break;
-        default:
-            nss_MD_win32_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_win32_map_bind_error(PRInt32 err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case WSAEINVAL:
-            prError = PR_SOCKET_ADDRESS_IS_BOUND_ERROR;
-            break;
-        default:
-            nss_MD_win32_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_win32_map_listen_error(PRInt32 err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case WSAEOPNOTSUPP:
-            prError = PR_NOT_TCP_SOCKET_ERROR;
-            break;
-        case WSAEINVAL:
-            prError = PR_INVALID_STATE_ERROR;
-            break;
-        default:
-            nss_MD_win32_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_win32_map_shutdown_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_getsockname_error(PRInt32 err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case WSAEINVAL:
-            prError = PR_INVALID_STATE_ERROR;
-            break;
-        default:
-            nss_MD_win32_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_win32_map_getpeername_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_getsockopt_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_setsockopt_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_open_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_gethostname_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-/* Win32 select() only works on sockets.  So in this
-** context, WSAENOTSOCK is equivalent to EBADF on Unix.
-*/
-void
-nss_MD_win32_map_select_error(PRInt32 err)
-{
-    PRErrorCode prError;
-    switch (err) {
-        case WSAENOTSOCK:
-            prError = PR_BAD_DESCRIPTOR_ERROR;
-            break;
-        default:
-            nss_MD_win32_map_default_error(err);
-            return;
-    }
-    PR_SetError(prError, err);
-}
-
-void
-nss_MD_win32_map_lockf_error(PRInt32 err)
-{
-    nss_MD_win32_map_default_error(err);
-}
-
-void
-nss_MD_win32_map_default_error(PRInt32 err)
-{
-    PRErrorCode prError;
-
-    switch (err) {
-        case EACCES:
-            prError = PR_NO_ACCESS_RIGHTS_ERROR;
-            break;
-        case ENOENT:
-            prError = PR_FILE_NOT_FOUND_ERROR;
-            break;
-        case ERROR_ACCESS_DENIED:
-            prError = PR_NO_ACCESS_RIGHTS_ERROR;
-            break;
-        case ERROR_ALREADY_EXISTS:
-            prError = PR_FILE_EXISTS_ERROR;
-            break;
-        case ERROR_DISK_CORRUPT:
-            prError = PR_IO_ERROR;
-            break;
-        case ERROR_DISK_FULL:
-            prError = PR_NO_DEVICE_SPACE_ERROR;
-            break;
-        case ERROR_DISK_OPERATION_FAILED:
-            prError = PR_IO_ERROR;
-            break;
-        case ERROR_DRIVE_LOCKED:
-            prError = PR_FILE_IS_LOCKED_ERROR;
-            break;
-        case ERROR_FILENAME_EXCED_RANGE:
-            prError = PR_NAME_TOO_LONG_ERROR;
-            break;
-        case ERROR_FILE_CORRUPT:
-            prError = PR_IO_ERROR;
-            break;
-        case ERROR_FILE_EXISTS:
-            prError = PR_FILE_EXISTS_ERROR;
-            break;
-        case ERROR_FILE_INVALID:
-            prError = PR_BAD_DESCRIPTOR_ERROR;
-            break;
-#if ERROR_FILE_NOT_FOUND != ENOENT
-        case ERROR_FILE_NOT_FOUND:
-            prError = PR_FILE_NOT_FOUND_ERROR;
-            break;
-#endif
-        case ERROR_HANDLE_DISK_FULL:
-            prError = PR_NO_DEVICE_SPACE_ERROR;
-            break;
-        case ERROR_INVALID_ADDRESS:
-            prError = PR_ACCESS_FAULT_ERROR;
-            break;
-        case ERROR_INVALID_HANDLE:
-            prError = PR_BAD_DESCRIPTOR_ERROR;
-            break;
-        case ERROR_INVALID_NAME:
-            prError = PR_INVALID_ARGUMENT_ERROR;
-            break;
-        case ERROR_INVALID_PARAMETER:
-            prError = PR_INVALID_ARGUMENT_ERROR;
-            break;
-        case ERROR_INVALID_USER_BUFFER:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-        case ERROR_LOCKED:
-            prError = PR_FILE_IS_LOCKED_ERROR;
-            break;
-        case ERROR_NETNAME_DELETED:
-            prError = PR_CONNECT_RESET_ERROR;
-            break;
-        case ERROR_NOACCESS:
-            prError = PR_ACCESS_FAULT_ERROR;
-            break;
-        case ERROR_NOT_ENOUGH_MEMORY:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-        case ERROR_NOT_ENOUGH_QUOTA:
-            prError = PR_OUT_OF_MEMORY_ERROR;
-            break;
-        case ERROR_NOT_READY:
-            prError = PR_IO_ERROR;
-            break;
-        case ERROR_NO_MORE_FILES:
-            prError = PR_NO_MORE_FILES_ERROR;
-            break;
-        case ERROR_OPEN_FAILED:
-            prError = PR_IO_ERROR;
-            break;
-        case ERROR_OPEN_FILES:
-            prError = PR_IO_ERROR;
-            break;
-        case ERROR_OUTOFMEMORY:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-        case ERROR_PATH_BUSY:
-            prError = PR_IO_ERROR;
-            break;
-        case ERROR_PATH_NOT_FOUND:
-            prError = PR_FILE_NOT_FOUND_ERROR;
-            break;
-        case ERROR_SEEK_ON_DEVICE:
-            prError = PR_IO_ERROR;
-            break;
-        case ERROR_SHARING_VIOLATION:
-            prError = PR_FILE_IS_BUSY_ERROR;
-            break;
-        case ERROR_STACK_OVERFLOW:
-            prError = PR_ACCESS_FAULT_ERROR;
-            break;
-        case ERROR_TOO_MANY_OPEN_FILES:
-            prError = PR_SYS_DESC_TABLE_FULL_ERROR;
-            break;
-        case ERROR_WRITE_PROTECT:
-            prError = PR_NO_ACCESS_RIGHTS_ERROR;
-            break;
-        case WSAEACCES:
-            prError = PR_NO_ACCESS_RIGHTS_ERROR;
-            break;
-        case WSAEADDRINUSE:
-            prError = PR_ADDRESS_IN_USE_ERROR;
-            break;
-        case WSAEADDRNOTAVAIL:
-            prError = PR_ADDRESS_NOT_AVAILABLE_ERROR;
-            break;
-        case WSAEAFNOSUPPORT:
-            prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
-            break;
-        case WSAEALREADY:
-            prError = PR_ALREADY_INITIATED_ERROR;
-            break;
-        case WSAEBADF:
-            prError = PR_BAD_DESCRIPTOR_ERROR;
-            break;
-        case WSAECONNABORTED:
-            prError = PR_CONNECT_ABORTED_ERROR;
-            break;
-        case WSAECONNREFUSED:
-            prError = PR_CONNECT_REFUSED_ERROR;
-            break;
-        case WSAECONNRESET:
-            prError = PR_CONNECT_RESET_ERROR;
-            break;
-        case WSAEDESTADDRREQ:
-            prError = PR_INVALID_ARGUMENT_ERROR;
-            break;
-        case WSAEFAULT:
-            prError = PR_ACCESS_FAULT_ERROR;
-            break;
-        case WSAEHOSTUNREACH:
-            prError = PR_HOST_UNREACHABLE_ERROR;
-            break;
-        case WSAEINVAL:
-            prError = PR_INVALID_ARGUMENT_ERROR;
-            break;
-        case WSAEISCONN:
-            prError = PR_IS_CONNECTED_ERROR;
-            break;
-        case WSAEMFILE:
-            prError = PR_PROC_DESC_TABLE_FULL_ERROR;
-            break;
-        case WSAEMSGSIZE:
-            prError = PR_BUFFER_OVERFLOW_ERROR;
-            break;
-        case WSAENETDOWN:
-            prError = PR_NETWORK_DOWN_ERROR;
-            break;
-        case WSAENETRESET:
-            prError = PR_CONNECT_ABORTED_ERROR;
-            break;
-        case WSAENETUNREACH:
-            prError = PR_NETWORK_UNREACHABLE_ERROR;
-            break;
-        case WSAENOBUFS:
-            prError = PR_INSUFFICIENT_RESOURCES_ERROR;
-            break;
-        case WSAENOPROTOOPT:
-            prError = PR_INVALID_ARGUMENT_ERROR;
-            break;
-        case WSAENOTCONN:
-            prError = PR_NOT_CONNECTED_ERROR;
-            break;
-        case WSAENOTSOCK:
-            prError = PR_NOT_SOCKET_ERROR;
-            break;
-        case WSAEOPNOTSUPP:
-            prError = PR_OPERATION_NOT_SUPPORTED_ERROR;
-            break;
-        case WSAEPROTONOSUPPORT:
-            prError = PR_PROTOCOL_NOT_SUPPORTED_ERROR;
-            break;
-        case WSAEPROTOTYPE:
-            prError = PR_INVALID_ARGUMENT_ERROR;
-            break;
-        case WSAESHUTDOWN:
-            prError = PR_SOCKET_SHUTDOWN_ERROR;
-            break;
-        case WSAESOCKTNOSUPPORT:
-            prError = PR_INVALID_ARGUMENT_ERROR;
-            break;
-        case WSAETIMEDOUT:
-            prError = PR_CONNECT_ABORTED_ERROR;
-            break;
-        case WSAEWOULDBLOCK:
-            prError = PR_WOULD_BLOCK_ERROR;
-            break;
-        default:
-            prError = PR_UNKNOWN_ERROR;
-            break;
-    }
-    PR_SetError(prError, err);
-}
diff --git a/net/third_party/nss/ssl/win32err.h b/net/third_party/nss/ssl/win32err.h
deleted file mode 100644
index a6988490..0000000
--- a/net/third_party/nss/ssl/win32err.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * This file essentially replicates NSPR's source for the functions that
- * map system-specific error codes to NSPR error codes.  We would use
- * NSPR's functions, instead of duplicating them, but they're private.
- * As long as SSL's server session cache code must do platform native I/O
- * to accomplish its job, and NSPR's error mapping functions remain private,
- * This code will continue to need to be replicated.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*  NSPR doesn't make these functions public, so we have to duplicate
-**  them in NSS.
-*/
-extern void nss_MD_win32_map_accept_error(PRInt32 err);
-extern void nss_MD_win32_map_acceptex_error(PRInt32 err);
-extern void nss_MD_win32_map_access_error(PRInt32 err);
-extern void nss_MD_win32_map_bind_error(PRInt32 err);
-extern void nss_MD_win32_map_close_error(PRInt32 err);
-extern void nss_MD_win32_map_closedir_error(PRInt32 err);
-extern void nss_MD_win32_map_connect_error(PRInt32 err);
-extern void nss_MD_win32_map_default_error(PRInt32 err);
-extern void nss_MD_win32_map_delete_error(PRInt32 err);
-extern void nss_MD_win32_map_fstat_error(PRInt32 err);
-extern void nss_MD_win32_map_fsync_error(PRInt32 err);
-extern void nss_MD_win32_map_gethostname_error(PRInt32 err);
-extern void nss_MD_win32_map_getpeername_error(PRInt32 err);
-extern void nss_MD_win32_map_getsockname_error(PRInt32 err);
-extern void nss_MD_win32_map_getsockopt_error(PRInt32 err);
-extern void nss_MD_win32_map_listen_error(PRInt32 err);
-extern void nss_MD_win32_map_lockf_error(PRInt32 err);
-extern void nss_MD_win32_map_lseek_error(PRInt32 err);
-extern void nss_MD_win32_map_mkdir_error(PRInt32 err);
-extern void nss_MD_win32_map_open_error(PRInt32 err);
-extern void nss_MD_win32_map_opendir_error(PRInt32 err);
-extern void nss_MD_win32_map_read_error(PRInt32 err);
-extern void nss_MD_win32_map_readdir_error(PRInt32 err);
-extern void nss_MD_win32_map_recv_error(PRInt32 err);
-extern void nss_MD_win32_map_recvfrom_error(PRInt32 err);
-extern void nss_MD_win32_map_rename_error(PRInt32 err);
-extern void nss_MD_win32_map_rmdir_error(PRInt32 err);
-extern void nss_MD_win32_map_select_error(PRInt32 err);
-extern void nss_MD_win32_map_send_error(PRInt32 err);
-extern void nss_MD_win32_map_sendto_error(PRInt32 err);
-extern void nss_MD_win32_map_setsockopt_error(PRInt32 err);
-extern void nss_MD_win32_map_shutdown_error(PRInt32 err);
-extern void nss_MD_win32_map_socket_error(PRInt32 err);
-extern void nss_MD_win32_map_stat_error(PRInt32 err);
-extern void nss_MD_win32_map_transmitfile_error(PRInt32 err);
-extern void nss_MD_win32_map_write_error(PRInt32 err);
diff --git a/net/url_request/url_fetcher_impl_unittest.cc b/net/url_request/url_fetcher_impl_unittest.cc
index 1f83e1d..095d6b1c 100644
--- a/net/url_request/url_fetcher_impl_unittest.cc
+++ b/net/url_request/url_fetcher_impl_unittest.cc
@@ -45,7 +45,7 @@
 #include "net/url_request/url_request_throttler_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
 #include "net/cert_net/nss_ocsp.h"
 #endif
 
@@ -425,14 +425,14 @@
         kDefaultResponsePath));
     ASSERT_TRUE(hanging_url_.is_valid());
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
     crypto::EnsureNSSInit();
     EnsureNSSHttpIOInit();
 #endif
   }
 
   void TearDown() override {
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
     ShutdownNSSHttpIO();
 #endif
   }
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index c59ee4f..200349b 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -9235,7 +9235,7 @@
     CHECK_NE(static_cast<X509Certificate*>(NULL), root_cert.get());
     test_root_.reset(new ScopedTestRoot(root_cert.get()));
 
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
     SetURLRequestContextForNSSHttpIO(&context_);
     EnsureNSSHttpIOInit();
 #endif
@@ -9264,7 +9264,7 @@
   }
 
   ~HTTPSOCSPTest() override {
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
     ShutdownNSSHttpIO();
 #endif
   }
@@ -9304,7 +9304,7 @@
 // If it does not, then tests which rely on 'hard fail' behaviour should be
 // skipped.
 static bool SystemSupportsHardFailRevocationChecking() {
-#if defined(OS_WIN) || defined(USE_NSS_VERIFIER)
+#if defined(OS_WIN) || defined(USE_NSS_CERTS)
   return true;
 #else
   return false;
@@ -9343,7 +9343,7 @@
 }
 
 static bool SystemSupportsOCSPStapling() {
-#if defined(USE_NSS_VERIFIER)
+#if defined(USE_NSS_CERTS)
   return true;
 #elif defined(OS_WIN)
   return base::win::GetVersion() >= base::win::VERSION_VISTA;
diff --git a/remoting/host/token_validator_base.cc b/remoting/host/token_validator_base.cc
index 08c077e..99796421 100644
--- a/remoting/host/token_validator_base.cc
+++ b/remoting/host/token_validator_base.cc
@@ -151,11 +151,9 @@
   client_cert_store = new net::ClientCertStoreWin(cert_store);
 #elif defined(OS_MACOSX)
   client_cert_store = new net::ClientCertStoreMac();
-#elif defined(USE_OPENSSL)
-    // OpenSSL does not use the ClientCertStore infrastructure.
-  client_cert_store = nullptr;
 #else
-#error Unknown platform.
+  // OpenSSL does not use the ClientCertStore infrastructure.
+  client_cert_store = nullptr;
 #endif
   // The callback is uncancellable, and GetClientCert requires selected_certs
   // and client_cert_store to stay alive until the callback is called. So we
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index fff00bb..e060eeb 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2714,8 +2714,8 @@
 crbug.com/604642 [ Mac ]  fast/text/midword-break-after-breakable-char.html [ Failure ]
 crbug.com/605024 [ Mac ]  svg/transforms/animated-path-inside-transformed-html.xhtml [ Failure ]
 
-crbug.com/605047 [ Mac10.11 ]  fast/text/emphasis.html [ Failure ]
-crbug.com/605047 [ Mac10.11 ]  fast/text/international/complex-character-based-fallback.html [ Failure ]
+crbug.com/605047 [ Mac10.11 Retina ] fast/text/emphasis.html [ Failure ]
+crbug.com/605047 [ Mac10.11 Retina ] fast/text/international/complex-character-based-fallback.html [ Failure ]
 
 crbug.com/605059 [ Retina ] fast/text/international/bidi-neutral-directionality-paragraph-start.html [ Failure ]
 crbug.com/605059 [ Retina ] fast/text/international/bidi-AN-after-empty-run.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/editing/execCommand/apply-inline-style-to-element-with-no-renderer-crash.html b/third_party/WebKit/LayoutTests/editing/execCommand/apply-inline-style-to-element-with-no-renderer-crash.html
index 3cba805..1f0f5f2 100644
--- a/third_party/WebKit/LayoutTests/editing/execCommand/apply-inline-style-to-element-with-no-renderer-crash.html
+++ b/third_party/WebKit/LayoutTests/editing/execCommand/apply-inline-style-to-element-with-no-renderer-crash.html
@@ -25,7 +25,7 @@
 
     input=document.createElement('input');
     textPath.parentNode.insertBefore(input, textPath);
-    window.getSelection().setBaseAndExtent(input, 4);
+    window.getSelection().setBaseAndExtent(input, 4, null, 0);
 
     document.designMode='on';
     document.execCommand('Transpose');
diff --git a/third_party/WebKit/LayoutTests/editing/selection/script-tests/DOMSelection-DocumentType.js b/third_party/WebKit/LayoutTests/editing/selection/script-tests/DOMSelection-DocumentType.js
index d44f417b..e82d6ab8 100644
--- a/third_party/WebKit/LayoutTests/editing/selection/script-tests/DOMSelection-DocumentType.js
+++ b/third_party/WebKit/LayoutTests/editing/selection/script-tests/DOMSelection-DocumentType.js
@@ -3,7 +3,7 @@
 var sel = window.getSelection();
 var docType = document.implementation.createDocumentType('c', null, null);
 
-sel.setBaseAndExtent(docType);
+sel.setBaseAndExtent(docType, 0, null, 0);
 shouldBeNull("sel.anchorNode");
 
 sel.setBaseAndExtent(null, 0, docType, 0);
diff --git a/third_party/WebKit/LayoutTests/fast/block/float/float-list-changed-before-layout-crash.html b/third_party/WebKit/LayoutTests/fast/block/float/float-list-changed-before-layout-crash.html
index 0a5d32a6..70bc0a6 100644
--- a/third_party/WebKit/LayoutTests/fast/block/float/float-list-changed-before-layout-crash.html
+++ b/third_party/WebKit/LayoutTests/fast/block/float/float-list-changed-before-layout-crash.html
@@ -6,7 +6,7 @@
       }
       #el1:nth-last-child(2n) {
         display: table-header-group;
-      } 
+      }
       #el2:first-child {
         display: inline-table;
       }
@@ -15,7 +15,7 @@
       }
       #el2 {
         display: table-header-group;
-      } 
+      }
       #el4 {
         visibility: collapse;
       }
@@ -24,7 +24,7 @@
       }
       #el5 {
         display: table-header-group;
-      } 
+      }
       #el6 {
         -webkit-border-after: solid;
         float: left;
@@ -64,7 +64,7 @@
         el7.setAttribute('id','el7')
         document.body.appendChild(el7)
         document.designMode='on'
-        window.getSelection().setBaseAndExtent(el3, 1)
+        window.getSelection().setBaseAndExtent(el3, 1, null, 0)
         document.execCommand('InsertLineBreak')
         document.execCommand('selectall')
         document.execCommand('strikethrough')
diff --git a/third_party/WebKit/LayoutTests/fast/css-generated-content/crash-selection-editing-removes-pseudo.html b/third_party/WebKit/LayoutTests/fast/css-generated-content/crash-selection-editing-removes-pseudo.html
index 18e3374..f498565 100644
--- a/third_party/WebKit/LayoutTests/fast/css-generated-content/crash-selection-editing-removes-pseudo.html
+++ b/third_party/WebKit/LayoutTests/fast/css-generated-content/crash-selection-editing-removes-pseudo.html
@@ -31,7 +31,7 @@
 var test = document.getElementById('test');
 
 // Select from the #start backwards to the start of the line.
-window.getSelection().setBaseAndExtent(document.getElementById('start'));
+window.getSelection().collapse(document.getElementById('start'));
 window.getSelection().modify('extend', 'backward', 'lineBoundary')
 
 // Replace the selection with a break. This replaces #before, text,
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-template-areas-get-set-expected.txt b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-template-areas-get-set-expected.txt
index d25615d9..33972e2 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-template-areas-get-set-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-template-areas-get-set-expected.txt
@@ -28,6 +28,8 @@
 PASS window.getComputedStyle(element).getPropertyValue('grid-template-areas') is "none"
 Test grid-template-areas: inherit
 PASS window.getComputedStyle(parentElement).getPropertyValue('grid-template-areas') is "\"foo bar\""
+PASS window.getComputedStyle(parentElement).getPropertyValue('grid-template-areas') is "\"foo bar\""
+PASS window.getComputedStyle(parentElement).getPropertyValue('grid-template-areas') is "\"foo bar\""
 PASS window.getComputedStyle(element).getPropertyValue('grid-template-areas') is "\"foo bar\""
 Test invalid grid-template-areas values.
 PASS window.getComputedStyle(element).getPropertyValue('grid-template-areas') is "none"
@@ -35,6 +37,10 @@
 PASS window.getComputedStyle(element).getPropertyValue('grid-template-areas') is "none"
 PASS window.getComputedStyle(element).getPropertyValue('grid-template-areas') is "none"
 PASS window.getComputedStyle(element).getPropertyValue('grid-template-areas') is "none"
+PASS window.getComputedStyle(element).getPropertyValue('grid-template-areas') is "none"
+PASS window.getComputedStyle(element).getPropertyValue('grid-template-areas') is "none"
+PASS window.getComputedStyle(element).getPropertyValue('grid-template-areas') is "none"
+PASS window.getComputedStyle(element).getPropertyValue('grid-template-areas') is "none"
 
 FIXME: We currently don't validate that the named grid areas are <indent>.
 FAIL window.getComputedStyle(element).getPropertyValue('grid-template-areas') should be none. Was "nav-up".
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-template-areas-get-set.html b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-template-areas-get-set.html
index 98ddb9e..4495c27 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-template-areas-get-set.html
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-template-areas-get-set.html
@@ -155,6 +155,10 @@
     document.body.appendChild(parentElement);
     parentElement.style.gridTemplateAreas = "'foo bar'";
     shouldBeEqualToString("window.getComputedStyle(parentElement).getPropertyValue('grid-template-areas')", '"foo bar"')
+    parentElement.style.gridTemplateAreas = "'foo" + "\t" + "bar'";
+    shouldBeEqualToString("window.getComputedStyle(parentElement).getPropertyValue('grid-template-areas')", '"foo bar"')
+    parentElement.style.gridTemplateAreas = "'foo" + "\n" + "bar'";
+    shouldBeEqualToString("window.getComputedStyle(parentElement).getPropertyValue('grid-template-areas')", '"foo bar"')
 
     var element = document.createElement("div");
     parentElement.appendChild(element);
@@ -186,6 +190,16 @@
     element.style.gridTemplateAreas = "'' ''";
     shouldBeEqualToString("window.getComputedStyle(element).getPropertyValue('grid-template-areas')", "none")
 
+    element.style.gridTemplateAreas = "'^nav'";
+    shouldBeEqualToString("window.getComputedStyle(element).getPropertyValue('grid-template-areas')", "none")
+    element.style.gridTemplateAreas = "'n^av'";
+    shouldBeEqualToString("window.getComputedStyle(element).getPropertyValue('grid-template-areas')", "none")
+
+    element.style.gridTemplateAreas = "'\x04nav'";
+    shouldBeEqualToString("window.getComputedStyle(element).getPropertyValue('grid-template-areas')", "none")
+    element.style.gridTemplateAreas = "'n\x04av'";
+    shouldBeEqualToString("window.getComputedStyle(element).getPropertyValue('grid-template-areas')", "none")
+
     debug("");
     debug("FIXME: We currently don't validate that the named grid areas are &lt;indent&gt;.");
     // <ident> only allows a leading '-'.
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-template-columns-rows-computed-style-gaps-content-alignment-expected.txt b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-template-columns-rows-computed-style-gaps-content-alignment-expected.txt
new file mode 100644
index 0000000..16ecae3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-template-columns-rows-computed-style-gaps-content-alignment-expected.txt
@@ -0,0 +1,37 @@
+Test that computed style for grid-template-columns and grid-template-rows works as expected with content alignment and gaps.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS window.getComputedStyle(gridContentStart, '').getPropertyValue('grid-template-columns') is "300px 200px 100px"
+PASS window.getComputedStyle(gridContentStart, '').getPropertyValue('grid-template-rows') is "150px 100px 50px"
+PASS window.getComputedStyle(gridContentCenter, '').getPropertyValue('grid-template-columns') is "300px 200px 100px"
+PASS window.getComputedStyle(gridContentCenter, '').getPropertyValue('grid-template-rows') is "150px 100px 50px"
+PASS window.getComputedStyle(gridContentEnd, '').getPropertyValue('grid-template-columns') is "300px 200px 100px"
+PASS window.getComputedStyle(gridContentEnd, '').getPropertyValue('grid-template-rows') is "150px 100px 50px"
+PASS window.getComputedStyle(gridContentSpaceBetween, '').getPropertyValue('grid-template-columns') is "300px 200px 100px"
+PASS window.getComputedStyle(gridContentSpaceBetween, '').getPropertyValue('grid-template-rows') is "150px 100px 50px"
+PASS window.getComputedStyle(gridContentSpaceAround, '').getPropertyValue('grid-template-columns') is "300px 200px 100px"
+PASS window.getComputedStyle(gridContentSpaceAround, '').getPropertyValue('grid-template-rows') is "150px 100px 50px"
+PASS window.getComputedStyle(gridContentSpaceEvenly, '').getPropertyValue('grid-template-columns') is "300px 200px 100px"
+PASS window.getComputedStyle(gridContentSpaceEvenly, '').getPropertyValue('grid-template-rows') is "150px 100px 50px"
+PASS window.getComputedStyle(gridContentStretch, '').getPropertyValue('grid-template-columns') is "300px 200px 100px"
+PASS window.getComputedStyle(gridContentStretch, '').getPropertyValue('grid-template-rows') is "150px 100px 50px"
+PASS window.getComputedStyle(gridGapsContentStart, '').getPropertyValue('grid-template-columns') is "300px 200px 100px"
+PASS window.getComputedStyle(gridGapsContentStart, '').getPropertyValue('grid-template-rows') is "150px 100px 50px"
+PASS window.getComputedStyle(gridGapsContentCenter, '').getPropertyValue('grid-template-columns') is "300px 200px 100px"
+PASS window.getComputedStyle(gridGapsContentCenter, '').getPropertyValue('grid-template-rows') is "150px 100px 50px"
+PASS window.getComputedStyle(gridGapsContentEnd, '').getPropertyValue('grid-template-columns') is "300px 200px 100px"
+PASS window.getComputedStyle(gridGapsContentEnd, '').getPropertyValue('grid-template-rows') is "150px 100px 50px"
+PASS window.getComputedStyle(gridGapsContentSpaceBetween, '').getPropertyValue('grid-template-columns') is "300px 200px 100px"
+PASS window.getComputedStyle(gridGapsContentSpaceBetween, '').getPropertyValue('grid-template-rows') is "150px 100px 50px"
+PASS window.getComputedStyle(gridGapsContentSpaceAround, '').getPropertyValue('grid-template-columns') is "300px 200px 100px"
+PASS window.getComputedStyle(gridGapsContentSpaceAround, '').getPropertyValue('grid-template-rows') is "150px 100px 50px"
+PASS window.getComputedStyle(gridGapsContentSpaceEvenly, '').getPropertyValue('grid-template-columns') is "300px 200px 100px"
+PASS window.getComputedStyle(gridGapsContentSpaceEvenly, '').getPropertyValue('grid-template-rows') is "150px 100px 50px"
+PASS window.getComputedStyle(gridGapsContentStretch, '').getPropertyValue('grid-template-columns') is "300px 200px 100px"
+PASS window.getComputedStyle(gridGapsContentStretch, '').getPropertyValue('grid-template-rows') is "150px 100px 50px"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-template-columns-rows-computed-style-gaps-content-alignment.html b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-template-columns-rows-computed-style-gaps-content-alignment.html
new file mode 100644
index 0000000..8b1c5c6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-template-columns-rows-computed-style-gaps-content-alignment.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<link href="resources/grid.css" rel="stylesheet">
+<link href="resources/grid-alignment.css" rel="stylesheet">
+<style>
+.grid {
+    grid-template-columns: 300px 200px 100px;
+    grid-template-rows: 150px 100px 50px;
+    width: 800px;
+    height: 500px;
+}
+
+.gaps {
+    grid-gap: 10px 20px;
+}
+</style>
+
+<div class="grid contentStart" id="gridContentStart"></div>
+<div class="grid contentCenter" id="gridContentCenter"></div>
+<div class="grid contentEnd" id="gridContentEnd"></div>
+<div class="grid contentSpaceBetween" id="gridContentSpaceBetween"></div>
+<div class="grid contentSpaceAround" id="gridContentSpaceAround"></div>
+<div class="grid contentSpaceEvenly" id="gridContentSpaceEvenly"></div>
+<div class="grid contentStretch" id="gridContentStretch"></div>
+
+<div class="grid gaps contentStart" id="gridGapsContentStart"></div>
+<div class="grid gaps contentCenter" id="gridGapsContentCenter"></div>
+<div class="grid gaps contentEnd" id="gridGapsContentEnd"></div>
+<div class="grid gaps contentSpaceBetween" id="gridGapsContentSpaceBetween"></div>
+<div class="grid gaps contentSpaceAround" id="gridGapsContentSpaceAround"></div>
+<div class="grid gaps contentSpaceEvenly" id="gridGapsContentSpaceEvenly"></div>
+<div class="grid gaps contentStretch" id="gridGapsContentStretch"></div>
+
+<script src="../../resources/js-test.js"></script>
+<script src="resources/grid-definitions-parsing-utils.js"></script>
+<script>
+    description("Test that computed style for grid-template-columns and grid-template-rows works as expected with content alignment and gaps.");
+
+    testGridDefinitionsValues(document.getElementById("gridContentStart"), "300px 200px 100px", "150px 100px 50px");
+    testGridDefinitionsValues(document.getElementById("gridContentCenter"), "300px 200px 100px", "150px 100px 50px");
+    testGridDefinitionsValues(document.getElementById("gridContentEnd"), "300px 200px 100px", "150px 100px 50px");
+    testGridDefinitionsValues(document.getElementById("gridContentSpaceBetween"), "300px 200px 100px", "150px 100px 50px");
+    testGridDefinitionsValues(document.getElementById("gridContentSpaceAround"), "300px 200px 100px", "150px 100px 50px");
+    testGridDefinitionsValues(document.getElementById("gridContentSpaceEvenly"), "300px 200px 100px", "150px 100px 50px");
+    testGridDefinitionsValues(document.getElementById("gridContentStretch"), "300px 200px 100px", "150px 100px 50px");
+
+    testGridDefinitionsValues(document.getElementById("gridGapsContentStart"), "300px 200px 100px", "150px 100px 50px");
+    testGridDefinitionsValues(document.getElementById("gridGapsContentCenter"), "300px 200px 100px", "150px 100px 50px");
+    testGridDefinitionsValues(document.getElementById("gridGapsContentEnd"), "300px 200px 100px", "150px 100px 50px");
+    testGridDefinitionsValues(document.getElementById("gridGapsContentSpaceBetween"), "300px 200px 100px", "150px 100px 50px");
+    testGridDefinitionsValues(document.getElementById("gridGapsContentSpaceAround"), "300px 200px 100px", "150px 100px 50px");
+    testGridDefinitionsValues(document.getElementById("gridGapsContentSpaceEvenly"), "300px 200px 100px", "150px 100px 50px");
+    testGridDefinitionsValues(document.getElementById("gridGapsContentStretch"), "300px 200px 100px", "150px 100px 50px");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Selection/missing-arguments-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/Selection/missing-arguments-expected.txt
index 755a35e..3c41d1f 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Selection/missing-arguments-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/Selection/missing-arguments-expected.txt
@@ -1,6 +1,10 @@
 PASS selection.addRange() threw exception TypeError: Failed to execute 'addRange' on 'Selection': 1 argument required, but only 0 present..
 PASS selection.getRangeAt() threw exception TypeError: Failed to execute 'getRangeAt' on 'Selection': 1 argument required, but only 0 present..
 PASS selection.selectAllChildren() threw exception TypeError: Failed to execute 'selectAllChildren' on 'Selection': 1 argument required, but only 0 present..
+PASS selection.setBaseAndExtent() threw exception TypeError: Failed to execute 'setBaseAndExtent' on 'Selection': 4 arguments required, but only 0 present..
+PASS selection.setBaseAndExtent(node) threw exception TypeError: Failed to execute 'setBaseAndExtent' on 'Selection': 4 arguments required, but only 1 present..
+PASS selection.setBaseAndExtent(node, 0) threw exception TypeError: Failed to execute 'setBaseAndExtent' on 'Selection': 4 arguments required, but only 2 present..
+PASS selection.setBaseAndExtent(node, 0, node) threw exception TypeError: Failed to execute 'setBaseAndExtent' on 'Selection': 4 arguments required, but only 3 present..
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Selection/missing-arguments.html b/third_party/WebKit/LayoutTests/fast/dom/Selection/missing-arguments.html
index 7a6fced7..22762386 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Selection/missing-arguments.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/Selection/missing-arguments.html
@@ -6,9 +6,14 @@
 <body>
 <script>
 var selection = getSelection();
+var node = document.body;
 shouldThrow("selection.addRange()");
 shouldThrow("selection.getRangeAt()");
 shouldThrow("selection.selectAllChildren()");
+shouldThrow("selection.setBaseAndExtent()");
+shouldThrow("selection.setBaseAndExtent(node)");
+shouldThrow("selection.setBaseAndExtent(node, 0)");
+shouldThrow("selection.setBaseAndExtent(node, 0, node)");
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/non-numeric-values-numeric-parameters-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/non-numeric-values-numeric-parameters-expected.txt
index c687974..49bf88870 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/non-numeric-values-numeric-parameters-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/non-numeric-values-numeric-parameters-expected.txt
@@ -56,7 +56,7 @@
 PASS nonNumericPolicy('document.createRange().isPointInRange(document, x)') is 'any type allowed (but not omitted)'
 PASS nonNumericPolicy('getSelection().collapse(document, x)') is 'any type allowed'
 PASS nonNumericPolicy('getSelection().setBaseAndExtent(document, x, document, 0)') is 'any type allowed'
-PASS nonNumericPolicy('getSelection().setBaseAndExtent(document, 0, document, x)') is 'any type allowed'
+PASS nonNumericPolicy('getSelection().setBaseAndExtent(document, 0, document, x)') is 'any type allowed (but not omitted)'
 PASS nonNumericPolicy('getSelection().collapse(document, x)') is 'any type allowed'
 PASS nonNumericPolicy('getSelection().extend(document, x)') is 'any type allowed'
 PASS nonNumericPolicy('getSelection().getRangeAt(x)') is 'any type allowed (but not omitted)'
diff --git a/third_party/WebKit/LayoutTests/fast/dom/script-tests/non-numeric-values-numeric-parameters.js b/third_party/WebKit/LayoutTests/fast/dom/script-tests/non-numeric-values-numeric-parameters.js
index 472b66a..a056201 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/script-tests/non-numeric-values-numeric-parameters.js
+++ b/third_party/WebKit/LayoutTests/fast/dom/script-tests/non-numeric-values-numeric-parameters.js
@@ -304,7 +304,7 @@
 
 shouldBe("nonNumericPolicy('getSelection().collapse(document, x)')", "'any type allowed'");
 shouldBe("nonNumericPolicy('getSelection().setBaseAndExtent(document, x, document, 0)')", "'any type allowed'");
-shouldBe("nonNumericPolicy('getSelection().setBaseAndExtent(document, 0, document, x)')", "'any type allowed'");
+shouldBe("nonNumericPolicy('getSelection().setBaseAndExtent(document, 0, document, x)')", "'any type allowed (but not omitted)'");
 shouldBe("nonNumericPolicy('getSelection().collapse(document, x)')", "'any type allowed'");
 shouldBe("nonNumericPolicy('getSelection().extend(document, x)')", "'any type allowed'");
 shouldBe("nonNumericPolicy('getSelection().getRangeAt(x)')", "'any type allowed (but not omitted)'");
@@ -397,7 +397,7 @@
 ../../../../WebCore/html/HTMLInputElement.idl:                 attribute long            tabIndex;
 ../../../../WebCore/html/HTMLInputElement.idl:                 attribute long            selectionStart;
 ../../../../WebCore/html/HTMLInputElement.idl:                 attribute long            selectionEnd;
-../../../../WebCore/html/HTMLLIElement.idl:        attribute long value;    
+../../../../WebCore/html/HTMLLIElement.idl:        attribute long value;
 ../../../../WebCore/html/HTMLMediaElement.idl:    attribute unsigned long playCount
 ../../../../WebCore/html/HTMLMediaElement.idl:    attribute unsigned long currentLoop;
 ../../../../WebCore/html/HTMLObjectElement.idl:                 attribute long            hspace;
@@ -429,13 +429,13 @@
 ../../../../WebCore/html/CanvasRenderingContext2D.idl:        attribute float shadowOffsetY;
 ../../../../WebCore/html/CanvasRenderingContext2D.idl:        attribute float shadowBlur;
 ../../../../WebCore/html/HTMLMediaElement.idl:    attribute float currentTime
-../../../../WebCore/html/HTMLMediaElement.idl:    attribute float defaultPlaybackRate 
-../../../../WebCore/html/HTMLMediaElement.idl:    attribute float playbackRate 
+../../../../WebCore/html/HTMLMediaElement.idl:    attribute float defaultPlaybackRate
+../../../../WebCore/html/HTMLMediaElement.idl:    attribute float playbackRate
 ../../../../WebCore/html/HTMLMediaElement.idl:    attribute float start;
 ../../../../WebCore/html/HTMLMediaElement.idl:    attribute float end;
 ../../../../WebCore/html/HTMLMediaElement.idl:    attribute float loopStart;
 ../../../../WebCore/html/HTMLMediaElement.idl:    attribute float loopEnd;
-../../../../WebCore/html/HTMLMediaElement.idl:    attribute float volume 
+../../../../WebCore/html/HTMLMediaElement.idl:    attribute float volume
 
 ../../../../WebCore/svg/SVGAnimatedInteger.idl:                 attribute long baseVal
 ../../../../WebCore/svg/SVGElementInstanceList.idl:        SVGElementInstance item(in unsigned long index);
@@ -459,14 +459,14 @@
 ../../../../WebCore/svg/SVGSVGElement.idl:        unsigned long suspendRedraw(in unsigned long maxWaitMilliseconds);
 ../../../../WebCore/svg/SVGSVGElement.idl:        void unsuspendRedraw(in unsigned long suspendHandleId)
 ../../../../WebCore/svg/SVGTextContentElement.idl:        long getNumberOfChars();
-../../../../WebCore/svg/SVGTextContentElement.idl:        float getSubStringLength(in unsigned long offset, 
+../../../../WebCore/svg/SVGTextContentElement.idl:        float getSubStringLength(in unsigned long offset,
 ../../../../WebCore/svg/SVGTextContentElement.idl:                                 in unsigned long length)
 ../../../../WebCore/svg/SVGTextContentElement.idl:        SVGPoint getStartPositionOfChar(in unsigned long offset)
 ../../../../WebCore/svg/SVGTextContentElement.idl:        SVGPoint getEndPositionOfChar(in unsigned long offset)
 ../../../../WebCore/svg/SVGTextContentElement.idl:        SVGRect getExtentOfChar(in unsigned long offset)
 ../../../../WebCore/svg/SVGTextContentElement.idl:        float getRotationOfChar(in unsigned long offset)
 ../../../../WebCore/svg/SVGTextContentElement.idl:        long getCharNumAtPosition(in SVGPoint point);
-../../../../WebCore/svg/SVGTextContentElement.idl:        void selectSubString(in unsigned long offset, 
+../../../../WebCore/svg/SVGTextContentElement.idl:        void selectSubString(in unsigned long offset,
 ../../../../WebCore/svg/SVGTextContentElement.idl:                             in unsigned long length)
 ../../../../WebCore/svg/SVGTransformList.idl:        [Custom] SVGTransform getItem(in unsigned long index)
 ../../../../WebCore/svg/SVGTransformList.idl:        [Custom] SVGTransform insertItemBefore(in SVGTransform item, in unsigned long index)
@@ -494,7 +494,7 @@
 ../../../../WebCore/svg/SVGSVGElement.idl:        float getCurrentTime();
 ../../../../WebCore/svg/SVGSVGElement.idl:        void setCurrentTime(in float seconds);
 ../../../../WebCore/svg/SVGTextContentElement.idl:        float getComputedTextLength();
-../../../../WebCore/svg/SVGTextContentElement.idl:        float getSubStringLength(in unsigned long offset, 
+../../../../WebCore/svg/SVGTextContentElement.idl:        float getSubStringLength(in unsigned long offset,
 ../../../../WebCore/svg/SVGTextContentElement.idl:        float getRotationOfChar(in unsigned long offset)
 ../../../../WebCore/svg/SVGTransform.idl:        void setTranslate(in float tx, in float ty);
 ../../../../WebCore/svg/SVGTransform.idl:        void setScale(in float sx, in float sy);
diff --git a/third_party/WebKit/LayoutTests/fast/domurl/url-constructor.html b/third_party/WebKit/LayoutTests/fast/domurl/url-constructor.html
index 0128c0c5..4660229 100644
--- a/third_party/WebKit/LayoutTests/fast/domurl/url-constructor.html
+++ b/third_party/WebKit/LayoutTests/fast/domurl/url-constructor.html
@@ -53,4 +53,31 @@
         function() { new URL('//abc', null); },
         'TypeError: Failed to construct \'URL\': Invalid base URL');
 }, 'Invalid URL parameters');
+
+test(function() {
+    function assert_enumerable(p) {
+        assert_true(p in URL.prototype);
+        assert_true(URL.prototype.propertyIsEnumerable(p));
+    }
+
+    assert_true('URL' in self);
+
+    // TODO: uncomment when implemented.
+    // assert_true('domainToASCII' in URL);
+    // assert_true('domainToUnicode' in URL);
+
+    // Arguably better failure stacks to spell them out this way..
+    assert_enumerable('toString');
+    assert_enumerable('origin');
+    assert_enumerable('protocol');
+    assert_enumerable('username');
+    assert_enumerable('password');
+    assert_enumerable('host');
+    assert_enumerable('hostname');
+    assert_enumerable('port');
+    assert_enumerable('pathname');
+    assert_enumerable('search');
+    assert_enumerable('searchParams');
+    assert_enumerable('hash');
+}, 'URL interface');
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/inputevents/before-input-data.html b/third_party/WebKit/LayoutTests/fast/events/inputevents/before-input-data.html
new file mode 100644
index 0000000..aad057d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/inputevents/before-input-data.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>InputEvent: beforeinput data</title>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<input type="text" id="txt">
+<script>
+test(function() {
+    var lastData = '';
+    var txt = document.getElementById('txt');
+    txt.addEventListener('beforeinput', function(event) {
+        lastData = event.data;
+    });
+    if (!window.eventSender) {
+        document.write('This test requires eventSender');
+    } else {
+        function testKeyDownData(key, modifiers, data) {
+            eventSender.keyDown(key, modifiers);
+            assert_equals(lastData, data, `${modifiers.toString()}+${key} should produce data: ${data}`);
+        }
+
+        txt.focus();
+        // Typing
+        testKeyDownData('a', [], 'a');
+        testKeyDownData('4', [], '4');
+        testKeyDownData('backspace', [], '');
+        // TODO(chongz): eventSender.keyDown('a', ['shiftKey']) should produce shifted character.
+        // https://crbug.com/604488
+        // testKeyDownData('l', ['shiftKey'], 'L');
+        // testKeyDownData('6', ['shiftKey'], '^');
+        testKeyDownData(' ', [], ' ');
+    }
+}, 'Testing beforeinput data');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/events/inputevents/before-input-inputtype.html b/third_party/WebKit/LayoutTests/fast/events/inputevents/before-input-inputtype.html
new file mode 100644
index 0000000..478fa7a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/inputevents/before-input-inputtype.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>InputEvent: beforeinput inputType</title>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<input type="text" id="txt">
+<script>
+test(function() {
+    var lastInputType = '';
+    var txt = document.getElementById('txt');
+    txt.addEventListener('beforeinput', function(event) {
+        lastInputType = event.inputType;
+    });
+    if (!window.eventSender) {
+        document.write('This test requires eventSender');
+    } else {
+        var kNoBeforeInputFired = 'noBeforeInputFired';
+        function testKeyDownInputType(key, modifiers, inputType) {
+            lastInputType = kNoBeforeInputFired;
+            eventSender.keyDown(key, modifiers);
+            assert_equals(lastInputType, inputType, `${modifiers.toString()}+${key} should produce inputType: ${inputType}`);
+        }
+
+        txt.focus();
+        // Typing
+        testKeyDownInputType('a', [], 'insertText');
+        testKeyDownInputType('6', [], 'insertText');
+        testKeyDownInputType('backspace', [], 'deleteContent');
+        testKeyDownInputType('l', ['shiftKey'], 'insertText');
+        testKeyDownInputType('w', ['shiftKey'], 'insertText');
+
+        // Keyboard commands
+        var isMacOS = (navigator.userAgent.indexOf('Mac OS X') != -1);
+        if (!isMacOS) {
+            // MacOS's eventSender does not work on hot keys other than arrows.
+            testKeyDownInputType('z', ['ctrlKey'], 'undo');
+            testKeyDownInputType('z', ['ctrlKey', 'shiftKey'], 'redo');
+        }
+        // Move command should not generate input events.
+        testKeyDownInputType('leftArrow', [], kNoBeforeInputFired);
+        testKeyDownInputType('leftArrow', ['shiftKey'], kNoBeforeInputFired);
+        testKeyDownInputType('home', [], kNoBeforeInputFired);
+    }
+}, 'Testing beforeinput inputType');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/events/inputevents/before-input-order-typing-command.html b/third_party/WebKit/LayoutTests/fast/events/inputevents/before-input-order-typing-command.html
new file mode 100644
index 0000000..d24eadb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/inputevents/before-input-order-typing-command.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>InputEvent: beforeinput order on typing and command</title>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<input type="text" id="txt">
+<script>
+test(function() {
+    var eventList = ['keydown', 'keypress', 'beforeinput', 'input', 'keyup'];
+    var expectedEventOrder = [
+        // Pressing 'a'.
+        'keydown', 'keypress', 'beforeinput', 'input', 'keyup',
+        // Pressing 'z' with modifier 'ctrlKey'.
+        'keydown', 'beforeinput', 'input', 'keyup',
+    ];
+    var actualEventOrder = [];
+    var txt = document.getElementById('txt');
+    eventList.forEach(function(eventType) {
+        txt.addEventListener(eventType, function(event) {
+            actualEventOrder.push(event.type);
+        });
+    });
+    if (!window.eventSender) {
+        document.write('This test requires eventSender');
+    } else {
+        txt.focus();
+        eventSender.keyDown('a');
+        var isMacOSX = navigator.userAgent.indexOf('Mac OS X') != -1;
+        if (!isMacOSX) {
+            // MacOS's eventSender does not work on hot keys other than arrows.
+            eventSender.keyDown('z', ['ctrlKey']);
+            assert_array_equals(actualEventOrder, expectedEventOrder, actualEventOrder.toString());
+        }
+    }
+}, 'Testing beforeinput order on typing and command');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/js/toString-dontEnum-expected.txt b/third_party/WebKit/LayoutTests/fast/js/toString-dontEnum-expected.txt
index 773eb29..1c52f9c 100644
--- a/third_party/WebKit/LayoutTests/fast/js/toString-dontEnum-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/js/toString-dontEnum-expected.txt
@@ -1,6 +1,5 @@
 This tests that the toString() function does not enumerate.
 
-PASS: the toString function is not enumerable for HTMLAnchorElement.
 PASS: the toString function is not enumerable for Location.
 PASS: the toString function is not enumerable for Selection.
 PASS: the toString function is not enumerable for HTMLDivElement.
diff --git a/third_party/WebKit/LayoutTests/fast/js/toString-dontEnum.html b/third_party/WebKit/LayoutTests/fast/js/toString-dontEnum.html
index d376d53..05493ca 100644
--- a/third_party/WebKit/LayoutTests/fast/js/toString-dontEnum.html
+++ b/third_party/WebKit/LayoutTests/fast/js/toString-dontEnum.html
@@ -25,7 +25,6 @@
                 testRunner.dumpAsText();
 
             // DOM objects with custom toString() functions
-            test(document.createElement('a'), "HTMLAnchorElement");
             test(window.location, "Location");
             test(window.getSelection(), "Selection");
 
diff --git a/third_party/WebKit/LayoutTests/fast/mediastream/RTCPeerConnection-expected.txt b/third_party/WebKit/LayoutTests/fast/mediastream/RTCPeerConnection-expected.txt
index 37860bd0..206c6c758 100644
--- a/third_party/WebKit/LayoutTests/fast/mediastream/RTCPeerConnection-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/mediastream/RTCPeerConnection-expected.txt
@@ -54,6 +54,8 @@
 PASS new webkitRTCPeerConnection({iceServers:[], certificates:[1337]}); threw exception TypeError: Failed to construct 'RTCPeerConnection': Malformed sequence<RTCCertificate>.
 PASS new webkitRTCPeerConnection({iceServers:[], certificates:[certRSA]}, null); did not throw exception.
 PASS new webkitRTCPeerConnection({iceServers:[], certificates:[certECDSA]}, null); did not throw exception.
+PASS certExpired.expires <= new Date().getTime() is true
+PASS new webkitRTCPeerConnection({iceServers:[], certificates:[certExpired]}, null); threw exception InvalidStateError: Failed to construct 'RTCPeerConnection': Expired certificate(s)..
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/mediastream/RTCPeerConnection.html b/third_party/WebKit/LayoutTests/fast/mediastream/RTCPeerConnection.html
index 2624d778..577fd44 100644
--- a/third_party/WebKit/LayoutTests/fast/mediastream/RTCPeerConnection.html
+++ b/third_party/WebKit/LayoutTests/fast/mediastream/RTCPeerConnection.html
@@ -66,6 +66,7 @@
 // Global certificate variables so that the "should..." methods can evaluate them.
 var certRSA = null;
 var certECDSA = null;
+var certExpired = null;
 
 function testCertificates1RSA()
 {
@@ -86,6 +87,20 @@
         .then(function(certificate) {
                   certECDSA = certificate;
                   shouldNotThrow('new webkitRTCPeerConnection({iceServers:[], certificates:[certECDSA]}, null);');
+                  testCertificates3Expired();
+              },
+              function() {
+                  testFailed('Generating ECDSA P-256');
+                  testCertificates3Expired();
+              });
+}
+function testCertificates3Expired()
+{
+    webkitRTCPeerConnection.generateCertificate({ name: "ECDSA", namedCurve: "P-256", expires:0 })
+        .then(function(certificate) {
+                  certExpired = certificate;
+                  shouldBeTrue('certExpired.expires <= new Date().getTime()');
+                  shouldThrow('new webkitRTCPeerConnection({iceServers:[], certificates:[certExpired]}, null);');
                   finishJSTest();
               },
               function() {
@@ -94,7 +109,7 @@
               });
 }
 // Sequentially test construction with RSA and ECDSA certificates.
-// testCertificates2ECDSA's callback methods mark the end of the async tests.
+// testCertificates3Expired's callback methods mark the end of the async tests.
 testCertificates1RSA();
 
 window.jsTestIsAsync = true;
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-multiple-headers-sameorigin-deny-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-multiple-headers-sameorigin-deny-expected.txt
index 817c493de..a4b9e2b 100644
--- a/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-multiple-headers-sameorigin-deny-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-multiple-headers-sameorigin-deny-expected.txt
@@ -1,7 +1,5 @@
-http://localhost:8000/security/XFrameOptions/resources/x-frame-options-multiple-headers-sameorigin.cgi - willSendRequest <NSURLRequest URL http://localhost:8000/security/XFrameOptions/resources/x-frame-options-multiple-headers-sameorigin.cgi, main document URL http://127.0.0.1:8000/security/XFrameOptions/x-frame-options-multiple-headers-sameorigin-deny.html, http method GET> redirectResponse (null)
 CONSOLE ERROR: Refused to display 'http://localhost:8000/security/XFrameOptions/resources/x-frame-options-multiple-headers-sameorigin.cgi' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN, SAMEORIGIN'.
-http://localhost:8000/security/XFrameOptions/resources/x-frame-options-multiple-headers-sameorigin.cgi - didFinishLoading
-CONSOLE MESSAGE: line 17: PASS: Access to contentWindow.location.href threw an exception.
+CONSOLE MESSAGE: line 16: PASS: Access to contentWindow.location.href threw an exception.
 The frame below should not load, proving that 'sameorigin, sameorigin' === 'sameorigin'.
 
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-multiple-headers-sameorigin-deny.html b/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-multiple-headers-sameorigin-deny.html
index e4804ec..f27f333 100644
--- a/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-multiple-headers-sameorigin-deny.html
+++ b/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-multiple-headers-sameorigin-deny.html
@@ -5,7 +5,6 @@
         if (window.testRunner) {
             testRunner.dumpAsText();
             testRunner.dumpChildFramesAsText();
-            testRunner.dumpResourceLoadCallbacks();
             testRunner.waitUntilDone();
         }
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-parent-same-origin-deny-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-parent-same-origin-deny-expected.txt
index 6f2799c..3034b45 100644
--- a/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-parent-same-origin-deny-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-parent-same-origin-deny-expected.txt
@@ -1,7 +1,5 @@
-http://localhost:8000/security/XFrameOptions/resources/x-frame-options-parent-same-origin-allow.cgi - willSendRequest <NSURLRequest URL http://localhost:8000/security/XFrameOptions/resources/x-frame-options-parent-same-origin-allow.cgi, main document URL http://127.0.0.1:8000/security/XFrameOptions/x-frame-options-parent-same-origin-deny.html, http method GET> redirectResponse (null)
 CONSOLE ERROR: Refused to display 'http://localhost:8000/security/XFrameOptions/resources/x-frame-options-parent-same-origin-allow.cgi' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
-http://localhost:8000/security/XFrameOptions/resources/x-frame-options-parent-same-origin-allow.cgi - didFinishLoading
-CONSOLE MESSAGE: line 14: PASS: Access to contentWindow.location.href threw an exception.
+CONSOLE MESSAGE: line 13: PASS: Access to contentWindow.location.href threw an exception.
 There should be no content in the iframe below
 
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-parent-same-origin-deny.html b/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-parent-same-origin-deny.html
index 7145cf4b..a6c86b4 100644
--- a/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-parent-same-origin-deny.html
+++ b/third_party/WebKit/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-parent-same-origin-deny.html
@@ -2,7 +2,6 @@
     if (window.testRunner) {
         testRunner.dumpAsText();
         testRunner.dumpChildFramesAsText();
-        testRunner.dumpResourceLoadCallbacks();
         testRunner.waitUntilDone();
     }
 
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
index d9aa8213..5fced73 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
@@ -211,6 +211,7 @@
     property tagName
     property textContent
     property title
+    property toString
     property translate
     property webkitMatchesSelector
     property webkitRequestFullScreen
@@ -1260,6 +1261,7 @@
     property tagName
     property textContent
     property title
+    property toString
     property translate
     property webkitMatchesSelector
     property webkitRequestFullScreen
diff --git a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
index 8821f44..5d0de9e0 100644
--- a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
@@ -225,6 +225,7 @@
     property tagName
     property textContent
     property title
+    property toString
     property translate
     property webkitMatchesSelector
     property webkitRequestFullScreen
@@ -1314,6 +1315,7 @@
     property tagName
     property textContent
     property title
+    property toString
     property translate
     property webkitMatchesSelector
     property webkitRequestFullScreen
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index b5eb1b3..ccd3ac797 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -3391,6 +3391,8 @@
     method constructor
 interface InputEvent : UIEvent
     attribute @@toStringTag
+    getter data
+    getter inputType
     method constructor
 interface IntersectionObserver
     attribute @@toStringTag
diff --git a/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md b/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md
index 28d0e01..65b85b16 100644
--- a/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md
+++ b/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md
@@ -1269,6 +1269,32 @@
 
 The `[SetWrapperReferenceTo]` extended attribute takes a value, which is the method name to call to get the target object. For example, with the above declaration a call will be made to `YYY::targetMethod()` to get the target of the reference.
 
+### [TraceWrappers=(list)] _(i)_
+
+Summary: This generates code that traces script-wrappable references (which are used to keep wrappers alive during V8 GC).
+
+Usage: `[TraceWrappers=(list)]` can be specified on an interface.
+
+```webidl
+[
+  TraceWrappers=(element1, element2)
+] interface XXX : YYY { ... };
+```
+
+The generator generates a function called `XXX::traceWrappers` which is called by `ScriptWrappableVisitor` during V8 GC. The function adds references from the XXX instance to this object's element1() and element2() children.
+
+The generated code is then:
+
+```c++
+DEFINE_TRACE_WRAPPERS(XXX)
+{
+    visitor->traceWrappers(element1());
+    visitor->traceWrappers(element2());
+
+    YYY::traceWrappers(visitor);
+}
+```
+
 ## Rare Blink-specific IDL Extended Attributes
 
 These extended attributes are rarely used, generally only in one or two places. These are often replacements for `[Custom]` bindings, and may be candidates for deprecation and removal.
diff --git a/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt b/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt
index 9cd3ebb..37a7a066 100644
--- a/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt
+++ b/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt
@@ -88,6 +88,7 @@
 # Source/core/page/RuntimeEnabledFeatures.in
 RuntimeEnabled=*
 SameObject
+TraceWrappers=*
 SetWrapperReferenceFrom=*
 SetWrapperReferenceTo=*
 SetterCallWith=ExecutionContext|ScriptArguments|CurrentWindow|EnteredWindow
diff --git a/third_party/WebKit/Source/bindings/core/v8/ActiveScriptWrappable.cpp b/third_party/WebKit/Source/bindings/core/v8/ActiveScriptWrappable.cpp
index 437bf83..fe1e210 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ActiveScriptWrappable.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ActiveScriptWrappable.cpp
@@ -4,6 +4,7 @@
 
 #include "bindings/core/v8/ActiveScriptWrappable.h"
 
+#include "bindings/core/v8/ScriptWrappable.h"
 #include "wtf/HashSet.h"
 #include "wtf/ThreadSpecific.h"
 #include "wtf/Threading.h"
@@ -38,4 +39,14 @@
     return m_scriptWrappable;
 }
 
+void ActiveScriptWrappable::traceActiveScriptWrappables(ScriptWrappableVisitor* visitor)
+{
+    for (auto activeWrappable : activeScriptWrappables()) {
+        if (!activeWrappable->hasPendingActivity())
+            continue;
+
+        visitor->traceWrappers(activeWrappable->toScriptWrappable());
+    }
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/ActiveScriptWrappable.h b/third_party/WebKit/Source/bindings/core/v8/ActiveScriptWrappable.h
index aab62ff..d5804194 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ActiveScriptWrappable.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ActiveScriptWrappable.h
@@ -11,6 +11,7 @@
 namespace blink {
 
 class ScriptWrappable;
+class ScriptWrappableVisitor;
 
 /**
  * Classes deriving from ActiveScriptWrappable will be registered in a
@@ -22,6 +23,8 @@
 public:
     explicit ActiveScriptWrappable(ScriptWrappable*);
 
+    static void traceActiveScriptWrappables(ScriptWrappableVisitor*);
+
     virtual bool hasPendingActivity() const = 0;
 
     ScriptWrappable* toScriptWrappable() const;
diff --git a/third_party/WebKit/Source/bindings/core/v8/DOMDataStore.h b/third_party/WebKit/Source/bindings/core/v8/DOMDataStore.h
index 62484cd..476c4e3 100644
--- a/third_party/WebKit/Source/bindings/core/v8/DOMDataStore.h
+++ b/third_party/WebKit/Source/bindings/core/v8/DOMDataStore.h
@@ -153,6 +153,11 @@
         return m_wrapperMap->newLocal(isolate, object);
     }
 
+    void markWrapper(ScriptWrappable* scriptWrappable)
+    {
+        m_wrapperMap->markWrapper(scriptWrappable);
+    }
+
     void setReference(const v8::Persistent<v8::Object>& parent, ScriptWrappable* child, v8::Isolate* isolate)
     {
         if (m_isMainWorld) {
diff --git a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperMap.h b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperMap.h
index 33da418..ff04464 100644
--- a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperMap.h
+++ b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperMap.h
@@ -93,6 +93,11 @@
         m_map.Remove(key);
     }
 
+    void markWrapper(KeyType* object)
+    {
+        m_map.RegisterExternallyReferencedObject(object);
+    }
+
 private:
     class PersistentValueMapTraits {
         STATIC_ONLY(PersistentValueMapTraits);
diff --git a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp
index 82d8d0d..3faa6aaa 100644
--- a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp
@@ -136,6 +136,27 @@
         worlds.append(it->value);
 }
 
+void DOMWrapperWorld::markWrappersInAllWorlds(ScriptWrappable* scriptWrappable, v8::Isolate* isolate)
+{
+    // TODO(hlopko): Currently wrapper in one world will keep wrappers in all
+    // worlds alive (possibly holding on entire documents). This is neither
+    // needed (there is no way to get from one wrapper to another), nor wanted
+    // (big performance and memory overhead).
+
+    // Marking for the main world
+    scriptWrappable->markWrapper(isolate);
+    if (!isMainThread())
+        return;
+    WorldMap& isolatedWorlds = isolatedWorldMap();
+    for (auto& keyValuePair : isolatedWorlds) {
+        DOMDataStore& dataStore = keyValuePair.value->domDataStore();
+        if (dataStore.containsWrapper(scriptWrappable)) {
+            // Marking for the isolated worlds
+            dataStore.markWrapper(scriptWrappable);
+        }
+    }
+}
+
 DOMWrapperWorld::~DOMWrapperWorld()
 {
     ASSERT(!isMainWorld());
diff --git a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.h b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.h
index 317ce4b..27c3cc1 100644
--- a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.h
+++ b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.h
@@ -54,6 +54,7 @@
 };
 
 class DOMObjectHolderBase;
+class DOMWrapperWorldVisitor;
 template<typename T> class DOMObjectHolder;
 
 // This class represent a collection of DOM wrappers for a specific world.
@@ -69,6 +70,7 @@
 
     static bool isolatedWorldsExist() { return isolatedWorldCount; }
     static void allWorldsInMainThread(Vector<RefPtr<DOMWrapperWorld>>& worlds);
+    static void markWrappersInAllWorlds(ScriptWrappable*, v8::Isolate*);
 
     static DOMWrapperWorld& world(v8::Local<v8::Context> context)
     {
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappable.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappable.cpp
index 3534a4e..3c44ae6 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappable.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappable.cpp
@@ -35,4 +35,10 @@
     return V8DOMWrapper::associateObjectWithWrapper(isolate, this, wrapperTypeInfo, wrapper);
 }
 
+void ScriptWrappable::markWrapper(v8::Isolate* isolate) const
+{
+    if (containsWrapper())
+        ScriptWrappableVisitor::markWrapper(m_wrapper, isolate);
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappable.h b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappable.h
index a6150c7..31597a0 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappable.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappable.h
@@ -31,6 +31,7 @@
 #ifndef ScriptWrappable_h
 #define ScriptWrappable_h
 
+#include "bindings/core/v8/ScriptWrappableVisitor.h"
 #include "bindings/core/v8/WrapperTypeInfo.h"
 #include "core/CoreExport.h"
 #include "platform/heap/Handle.h"
@@ -149,6 +150,15 @@
 
     bool containsWrapper() const { return !m_wrapper.IsEmpty(); }
 
+    /**
+     *  Mark wrapper of this ScriptWrappable as alive in V8. Only marks
+     *  wrapper in the main world. To mark wrappers in all worlds call
+     *  ScriptWrappableVisitor::markWrapper(ScriptWrappable*, v8::Isolate*)
+     */
+    void markWrapper(v8::Isolate*) const;
+
+    DECLARE_VIRTUAL_TRACE_WRAPPERS() {};
+
     // With Oilpan we don't need a ScriptWrappable destructor.
     //
     // 'RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!containsWrapper())' is not needed
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.cpp
new file mode 100644
index 0000000..bb28a752
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.cpp
@@ -0,0 +1,104 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "bindings/core/v8/ScriptWrappableVisitor.h"
+
+#include "bindings/core/v8/ActiveScriptWrappable.h"
+#include "bindings/core/v8/DOMDataStore.h"
+#include "bindings/core/v8/ScriptWrappable.h"
+#include "bindings/core/v8/WrapperTypeInfo.h"
+#include "core/dom/NodeRareData.h"
+#include "core/events/EventListenerMap.h"
+#include "core/events/EventTarget.h"
+#include "platform/heap/HeapPage.h"
+
+namespace blink {
+
+ScriptWrappableVisitor::~ScriptWrappableVisitor()
+{
+}
+
+void ScriptWrappableVisitor::TracePrologue()
+{
+    m_tracingInProgress = true;
+    ActiveScriptWrappable::traceActiveScriptWrappables(this);
+}
+
+void ScriptWrappableVisitor::TraceEpilogue()
+{
+    for (auto header : m_headersToUnmark)
+        header->unmarkWrapperHeader();
+
+    m_headersToUnmark.clear();
+    m_tracingInProgress = false;
+}
+
+void ScriptWrappableVisitor::TraceWrappersFrom(const std::vector<std::pair<void*, void*>>& internalFieldsOfPotentialWrappers)
+{
+    ASSERT(m_tracingInProgress);
+    for (auto pair : internalFieldsOfPotentialWrappers) {
+        traceWrappersFrom(pair);
+    }
+}
+
+void ScriptWrappableVisitor::traceWrappersFrom(std::pair<void*, void*> internalFields)
+{
+    if (reinterpret_cast<WrapperTypeInfo*>(internalFields.first)->ginEmbedder != gin::GinEmbedder::kEmbedderBlink)
+        return;
+
+    ScriptWrappable* scriptWrappable = reinterpret_cast<ScriptWrappable*>(internalFields.second);
+    ASSERT(scriptWrappable->wrapperTypeInfo()->wrapperClassId == WrapperTypeInfo::NodeClassId
+        || scriptWrappable->wrapperTypeInfo()->wrapperClassId == WrapperTypeInfo::ObjectClassId);
+
+    traceWrappers(scriptWrappable);
+}
+
+bool ScriptWrappableVisitor::isHeaderMarked(const void* garbageCollected) const
+{
+    return HeapObjectHeader::fromPayload(garbageCollected)->isWrapperHeaderMarked();
+}
+
+void ScriptWrappableVisitor::markHeader(const void* garbageCollected) const
+{
+    HeapObjectHeader* header = HeapObjectHeader::fromPayload(garbageCollected);
+    header->markWrapperHeader();
+    addHeaderToUnmark(header);
+}
+
+void ScriptWrappableVisitor::markHeader(const ScriptWrappable* scriptWrappable) const
+{
+    markHeader(static_cast<const void*>(scriptWrappable));
+
+    markWrappersInAllWorlds(scriptWrappable, m_isolate);
+}
+
+void ScriptWrappableVisitor::addHeaderToUnmark(HeapObjectHeader* header) const
+{
+    m_headersToUnmark.append(header);
+}
+
+void ScriptWrappableVisitor::markWrapper(const v8::Persistent<v8::Object>& handle, v8::Isolate* isolate)
+{
+    handle.RegisterExternalReference(isolate);
+}
+
+void ScriptWrappableVisitor::markWrappersInAllWorlds(const ScriptWrappable* scriptWrappable, v8::Isolate* isolate)
+{
+    DOMWrapperWorld::markWrappersInAllWorlds(const_cast<ScriptWrappable*>(scriptWrappable), isolate);
+}
+
+void ScriptWrappableVisitor::traceWrappers(const ScriptWrappable* wrappable) const
+{
+    if (wrappable && !isHeaderMarked(wrappable)) {
+        markHeader(wrappable);
+        wrappable->traceWrappers(this);
+    }
+}
+
+void ScriptWrappableVisitor::traceWrappers(const ScriptWrappable& wrappable) const
+{
+    traceWrappers(&wrappable);
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.h b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.h
new file mode 100644
index 0000000..a26c8e5
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.h
@@ -0,0 +1,106 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ScriptWrappableVisitor_h
+#define ScriptWrappableVisitor_h
+
+#include "platform/heap/HeapAllocator.h"
+#include <v8.h>
+#include <vector>
+
+
+namespace blink {
+
+class HeapObjectHeader;
+class ScriptWrappable;
+class ScriptWrappableHeapTracer;
+class NodeRareData;
+
+/**
+ * Declares non-virtual traceWrappers method. Should be used on
+ * non-ScriptWrappable classes which should participate in wrapper tracing (e.g.
+ * NodeRareData):
+ *
+ *     class NodeRareData {
+ *     public:
+ *         DECLARE_TRACE_WRAPPERS();
+ *     }
+ */
+#define DECLARE_TRACE_WRAPPERS()                               \
+    void traceWrappers(const ScriptWrappableVisitor*) const
+
+/**
+ * Declares virtual traceWrappers method. It is used in ScriptWrappable, can be
+ * used to override the method in the subclasses, and can be used by
+ * non-ScriptWrappable classes which expect to be inherited.
+ */
+#define DECLARE_VIRTUAL_TRACE_WRAPPERS()                       \
+    virtual DECLARE_TRACE_WRAPPERS()
+
+/**
+ * Provides definition of traceWrappers method. Custom code will usually call
+ * visitor->traceWrappers with all objects which could contribute to the set of
+ * reachable wrappers:
+ *
+ *     DEFINE_TRACE_WRAPPERS(NodeRareData)
+ *     {
+ *         visitor->traceWrappers(m_nodeLists);
+ *         visitor->traceWrappers(m_mutationObserverData);
+ *     }
+ */
+#define DEFINE_TRACE_WRAPPERS(T)                              \
+    void T::traceWrappers(const ScriptWrappableVisitor* visitor) const
+
+/**
+ * ScriptWrappableVisitor is able to trace through the script wrappable
+ * references. It is used during V8 garbage collection.  When this visitor is
+ * set to the v8::Isolate as its embedder heap tracer, V8 will call it during
+ * its garbage collection. At the beginning, it will call TracePrologue, then
+ * repeatedly (as v8 discovers more wrappers) it will call TraceWrappersFrom,
+ * and at the end it will call TraceEpilogue.
+ */
+class ScriptWrappableVisitor : public v8::EmbedderHeapTracer {
+public:
+    ScriptWrappableVisitor(v8::Isolate* isolate) : m_isolate(isolate) {};
+    ~ScriptWrappableVisitor() override;
+    /**
+     * Mark wrappers in all worlds for the given script wrappable as alive in
+     * V8.
+     */
+    static void markWrappersInAllWorlds(const ScriptWrappable*, v8::Isolate*);
+    /**
+     * Mark given wrapper as alive in V8.
+     */
+    static void markWrapper(const v8::Persistent<v8::Object>& handle, v8::Isolate*);
+
+    void TracePrologue() override;
+    void TraceWrappersFrom(const std::vector<std::pair<void*, void*>>& internalFieldsOfPotentialWrappers) override;
+    void TraceEpilogue() override;
+
+    inline void addHeaderToUnmark(HeapObjectHeader*) const;
+    void traceWrappers(const ScriptWrappable* wrappable) const;
+    void traceWrappers(const ScriptWrappable& wrappable) const;
+private:
+    inline void traceWrappersFrom(std::pair<void*, void*> internalFields);
+    inline void markHeader(const ScriptWrappable* scriptWrappable) const;
+    inline void markHeader(const void* garbageCollected) const;
+    inline bool isHeaderMarked(const void* garbageCollected) const;
+    bool m_tracingInProgress = false;
+    /**
+     * Collection of headers we need to unmark after the tracing finished. We
+     * assume it is safe to hold on to the headers because:
+     *     * oilpan objects cannot move
+     *     * objects this headers belong to are considered alive by the oilpan
+     *       gc (so they cannot be reclaimed). For the oilpan gc, wrappers are
+     *       part of the root set and wrapper will keep its ScriptWrappable
+     *       alive. Wrapper reachability is a subgraph of oilpan reachability,
+     *       therefore anything we find during tracing wrappers will be found by
+     *       oilpan gc too.
+     */
+    mutable WTF::Vector<HeapObjectHeader*> m_headersToUnmark;
+    v8::Isolate* m_isolate;
+};
+
+}
+#endif
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8BindingDesign.md b/third_party/WebKit/Source/bindings/core/v8/V8BindingDesign.md
index 5c98972..2a76b980 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8BindingDesign.md
+++ b/third_party/WebKit/Source/bindings/core/v8/V8BindingDesign.md
@@ -137,7 +137,8 @@
 an isolated world and a worker world.
 A main world is a world where a normal JavaScript downloaded from the web
 is executed.
-An isolated world is a world where a content script of a Chrome extension.
+An isolated world is a world where a content script of a Chrome extension is
+executed.
 An isolate of the main thread has 1 main world and N isolated worlds.
 An isolate of a worker thread has 1 worker world and 0 isolated world.
 [This diagram](https://drive.google.com/file/d/0B1obCOyvTnPKQmJEWkVtOEN2TmM/view?usp=sharing)
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
index f110bad..70a0efc 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
@@ -32,6 +32,7 @@
 
 #include "bindings/core/v8/ActiveScriptWrappable.h"
 #include "bindings/core/v8/RetainedDOMInfo.h"
+#include "bindings/core/v8/ScriptWrappableVisitor.h"
 #include "bindings/core/v8/V8AbstractEventListener.h"
 #include "bindings/core/v8/V8Binding.h"
 #include "bindings/core/v8/V8MutationObserver.h"
@@ -168,7 +169,7 @@
         if (type->hasPendingActivity(wrapper)) {
             // If you hit this assert, you'll need to add a [DependentiLifetime]
             // extended attribute to the DOM interface. A DOM interface that
-            // overrides hasPendingActivity must be marked as [DependentiLifetime].
+            // overrides hasPendingActivity must be marked as [DependentLifetime].
             RELEASE_ASSERT(!value->IsIndependent());
             m_isolate->SetObjectGroupId(*value, liveRootId());
             ++m_domObjectsWithPendingActivity;
@@ -259,6 +260,9 @@
 
 void gcPrologueForMajorGC(v8::Isolate* isolate, bool constructRetainedObjectInfos)
 {
+    if (RuntimeEnabledFeatures::traceWrappablesEnabled())
+        return;
+
     objectGroupingForMajorGC(isolate, constructRetainedObjectInfos);
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
index e89a717..2282dac 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
@@ -334,6 +334,10 @@
 {
     isolate->AddGCPrologueCallback(V8GCController::gcPrologue);
     isolate->AddGCEpilogueCallback(V8GCController::gcEpilogue);
+    if (RuntimeEnabledFeatures::traceWrappablesEnabled()) {
+        ScriptWrappableVisitor* visitor = new ScriptWrappableVisitor(isolate);
+        isolate->SetEmbedderHeapTracer(visitor);
+    }
 
     v8::Debug::SetLiveEditEnabled(isolate, false);
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/v8.gypi b/third_party/WebKit/Source/bindings/core/v8/v8.gypi
index a748fb0..eabe3d8 100644
--- a/third_party/WebKit/Source/bindings/core/v8/v8.gypi
+++ b/third_party/WebKit/Source/bindings/core/v8/v8.gypi
@@ -127,6 +127,8 @@
             'V8EventListenerList.h',
             'V8GCController.cpp',
             'V8GCController.h',
+            'ScriptWrappableVisitor.cpp',
+            'ScriptWrappableVisitor.h',
             'V8GCForContextDispose.cpp',
             'V8GCForContextDispose.h',
             'V8GlobalValueMap.h',
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_interface.py b/third_party/WebKit/Source/bindings/scripts/v8_interface.py
index f82a0579..6e565e4 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_interface.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_interface.py
@@ -145,11 +145,16 @@
         }
         set_wrapper_reference_to['idl_type'].add_includes_for_type()
 
-    # [SetWrapperReferenceFrom]
+    # [Custom=VisitDOMWrapper]
     has_visit_dom_wrapper = (
         has_extended_attribute_value(interface, 'Custom', 'VisitDOMWrapper') or
         set_wrapper_reference_from or set_wrapper_reference_to)
 
+    # [TraceWrappers]
+    trace_wrappers = extended_attribute_value_as_list(interface, 'TraceWrappers')
+    if trace_wrappers:
+        includes.add('bindings/core/v8/ScriptWrappableVisitor.h')
+
     wrapper_class_id = ('NodeClassId' if inherits_interface(interface.name, 'Node') else 'ObjectClassId')
 
     v8_class_name = v8_utilities.v8_class_name(interface)
@@ -168,6 +173,7 @@
         'has_custom_legacy_call_as_function': has_extended_attribute_value(interface, 'Custom', 'LegacyCallAsFunction'),  # [Custom=LegacyCallAsFunction]
         'has_partial_interface': len(interface.partial_interfaces) > 0,
         'has_visit_dom_wrapper': has_visit_dom_wrapper,
+        'trace_wrappers': trace_wrappers,
         'header_includes': header_includes,
         'interface_name': interface.name,
         'is_array_buffer_or_view': is_array_buffer_or_view,
@@ -178,7 +184,7 @@
         'is_node': inherits_interface(interface.name, 'Node'),
         'is_partial': interface.is_partial,
         'is_typed_array_type': is_typed_array_type,
-        'lifetime': 'Dependent' if (has_visit_dom_wrapper or is_dependent_lifetime) else 'Independent',
+        'lifetime': 'Dependent' if (has_visit_dom_wrapper or trace_wrappers or is_dependent_lifetime) else 'Independent',
         'measure_as': v8_utilities.measure_as(interface, None),  # [MeasureAs]
         'origin_trial_enabled_function': v8_utilities.origin_trial_enabled_function_name(interface, None),
         'parent_interface': parent_interface,
diff --git a/third_party/WebKit/Source/bindings/templates/interface.cpp b/third_party/WebKit/Source/bindings/templates/interface.cpp
index 2b9d96f..4d3ec220 100644
--- a/third_party/WebKit/Source/bindings/templates/interface.cpp
+++ b/third_party/WebKit/Source/bindings/templates/interface.cpp
@@ -534,6 +534,21 @@
 {% endif %}
 {% endblock %}
 
+{##############################################################################}
+
+{% block trace_wrappers %}
+{% if trace_wrappers %}
+DEFINE_TRACE_WRAPPERS({{cpp_class_or_partial}})
+{
+    {% for traceable in trace_wrappers %}
+    visitor->traceWrappers({{traceable}}());
+    {% endfor %}
+    {% if parent_interface %}
+    {{parent_interface}}::traceWrappers(visitor);
+    {% endif %}
+}
+{% endif %}
+{% endblock %}
 
 {##############################################################################}
 {% block visit_dom_wrapper %}
diff --git a/third_party/WebKit/Source/bindings/templates/interface_base.cpp b/third_party/WebKit/Source/bindings/templates/interface_base.cpp
index ceda80d..42ac08e 100644
--- a/third_party/WebKit/Source/bindings/templates/interface_base.cpp
+++ b/third_party/WebKit/Source/bindings/templates/interface_base.cpp
@@ -198,6 +198,7 @@
 } // namespace {{cpp_class_or_partial}}V8Internal
 
 {% block visit_dom_wrapper %}{% endblock %}
+{% block trace_wrappers %}{% endblock %}
 {##############################################################################}
 {% block install_attributes %}
 {% from 'attributes.cpp' import attribute_configuration with context %}
diff --git a/third_party/WebKit/Source/bindings/tests/idls/core/TestInterface.idl b/third_party/WebKit/Source/bindings/tests/idls/core/TestInterface.idl
index a5ccf532..8ce95aa 100644
--- a/third_party/WebKit/Source/bindings/tests/idls/core/TestInterface.idl
+++ b/third_party/WebKit/Source/bindings/tests/idls/core/TestInterface.idl
@@ -40,6 +40,7 @@
     Iterable,
     RuntimeEnabled=FeatureName,
     SetWrapperReferenceTo(TestInterface referencedName),
+    TraceWrappers=(firstChild,nextSibling,prevSibling,parent),
     Exposed=(Worker,Window),
 ] interface TestInterface : TestInterfaceEmpty {
     // members needed to test [ImplementedAs], as this affect attribute
diff --git a/third_party/WebKit/Source/bindings/tests/idls/core/TestInterface3.idl b/third_party/WebKit/Source/bindings/tests/idls/core/TestInterface3.idl
index 4470f7c..de08b550 100644
--- a/third_party/WebKit/Source/bindings/tests/idls/core/TestInterface3.idl
+++ b/third_party/WebKit/Source/bindings/tests/idls/core/TestInterface3.idl
@@ -49,4 +49,6 @@
 
     [RuntimeEnabled=FeatureName] iterable<any>;
     [RuntimeEnabled=FeatureName, CallWith=ScriptState, RaisesException, ImplementedAs=iterableKeys] Iterator keys();
+
+    stringifier readonly attribute DOMString readonlyStringifierAttribute;
 };
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
index 5195ef7..8fe86bdf 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
@@ -11,6 +11,7 @@
 #include "bindings/core/v8/ScriptPromise.h"
 #include "bindings/core/v8/ScriptState.h"
 #include "bindings/core/v8/ScriptValue.h"
+#include "bindings/core/v8/ScriptWrappableVisitor.h"
 #include "bindings/core/v8/UnionTypesCore.h"
 #include "bindings/core/v8/V8AbstractEventListener.h"
 #include "bindings/core/v8/V8DOMConfiguration.h"
@@ -1979,6 +1980,14 @@
     }
 }
 
+DEFINE_TRACE_WRAPPERS(TestInterfaceImplementation)
+{
+    visitor->traceWrappers(firstChild());
+    visitor->traceWrappers(nextSibling());
+    visitor->traceWrappers(prevSibling());
+    visitor->traceWrappers(parent());
+    TestInterfaceEmpty::traceWrappers(visitor);
+}
 // Suppress warning: global constructors, because AttributeConfiguration is trivial
 // and does not depend on another global objects.
 #if defined(COMPONENT_BUILD) && defined(WIN32) && COMPILER(CLANG)
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
index d5081ac..228435e1 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
@@ -39,6 +39,18 @@
 
 namespace TestInterface3V8Internal {
 
+static void readonlyStringifierAttributeAttributeGetter(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+    v8::Local<v8::Object> holder = info.Holder();
+    TestInterface3* impl = V8TestInterface3::toImpl(holder);
+    v8SetReturnValueString(info, impl->readonlyStringifierAttribute(), info.GetIsolate());
+}
+
+static void readonlyStringifierAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+    TestInterface3V8Internal::readonlyStringifierAttributeAttributeGetter(info);
+}
+
 static void voidMethodDocumentMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     if (UNLIKELY(info.Length() < 1)) {
@@ -149,6 +161,17 @@
     TestInterface3V8Internal::forEachMethod(info);
 }
 
+static void toStringMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+    TestInterface3* impl = V8TestInterface3::toImpl(info.Holder());
+    v8SetReturnValueString(info, impl->readonlyStringifierAttribute(), info.GetIsolate());
+}
+
+static void toStringMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+    TestInterface3V8Internal::toStringMethod(info);
+}
+
 static void iteratorMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "iterator", "TestInterface3", info.Holder(), info.GetIsolate());
@@ -209,8 +232,13 @@
 
 } // namespace TestInterface3V8Internal
 
+const V8DOMConfiguration::AccessorConfiguration V8TestInterface3Accessors[] = {
+    {"readonlyStringifierAttribute", TestInterface3V8Internal::readonlyStringifierAttributeAttributeGetterCallback, 0, 0, 0, 0, v8::DEFAULT, static_cast<v8::PropertyAttribute>(v8::ReadOnly), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnPrototype, V8DOMConfiguration::CheckHolder},
+};
+
 const V8DOMConfiguration::MethodConfiguration V8TestInterface3Methods[] = {
     {"voidMethodDocument", TestInterface3V8Internal::voidMethodDocumentMethodCallback, 0, 1, v8::None, V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnPrototype},
+    {"toString", TestInterface3V8Internal::toStringMethodCallback, 0, 0, v8::None, V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnPrototype},
 };
 
 static void installV8TestInterface3Template(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate)
@@ -224,6 +252,7 @@
     v8::Local<v8::ObjectTemplate> prototypeTemplate = interfaceTemplate->PrototypeTemplate();
     ALLOW_UNUSED_LOCAL(prototypeTemplate);
     // Register DOM constants, attributes and operations.
+    V8DOMConfiguration::installAccessors(isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate, signature, V8TestInterface3Accessors, WTF_ARRAY_LENGTH(V8TestInterface3Accessors));
     V8DOMConfiguration::installMethods(isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate, signature, V8TestInterface3Methods, WTF_ARRAY_LENGTH(V8TestInterface3Methods));
 
     // Indexed properties
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp
index 210977f..c5b280d2 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp
@@ -9,6 +9,7 @@
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/PrivateScriptRunner.h"
 #include "bindings/core/v8/ScriptPromise.h"
+#include "bindings/core/v8/ScriptWrappableVisitor.h"
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8Document.h"
 #include "bindings/core/v8/V8Node.h"
diff --git a/third_party/WebKit/Source/build/scripts/templates/RuntimeEnabledFeatures.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/RuntimeEnabledFeatures.h.tmpl
index bfdc7cba..d531966 100644
--- a/third_party/WebKit/Source/build/scripts/templates/RuntimeEnabledFeatures.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/RuntimeEnabledFeatures.h.tmpl
@@ -7,14 +7,16 @@
 #include <string>
 
 #include "platform/PlatformExport.h"
-#include "wtf/build_config.h"
+#include "wtf/Allocator.h"
 #include "wtf/Forward.h"
+#include "wtf/build_config.h"
 
 namespace blink {
 
 // A class that stores static enablers for all experimental features.
 
 class PLATFORM_EXPORT RuntimeEnabledFeatures {
+    STATIC_ONLY(RuntimeEnabledFeatures);
 public:
     class PLATFORM_EXPORT Backup {
     public:
@@ -53,8 +55,6 @@
     {% endfor %}
 
 private:
-    RuntimeEnabledFeatures() { }
-
     {% for feature in standard_features %}
     static bool is{{feature.name}}Enabled;
     {% endfor %}
diff --git a/third_party/WebKit/Source/core/css/CSSMarkup.cpp b/third_party/WebKit/Source/core/css/CSSMarkup.cpp
index d038527..55987e9 100644
--- a/third_party/WebKit/Source/core/css/CSSMarkup.cpp
+++ b/third_party/WebKit/Source/core/css/CSSMarkup.cpp
@@ -26,6 +26,7 @@
 
 #include "core/css/CSSMarkup.h"
 
+#include "core/css/parser/CSSParserIdioms.h"
 #include "wtf/HexNumber.h"
 #include "wtf/text/StringBuffer.h"
 #include "wtf/text/StringBuilder.h"
@@ -42,13 +43,13 @@
         ++characters;
 
     // {nmstart}
-    if (characters == end || !(characters[0] == '_' || characters[0] >= 128 || isASCIIAlpha(characters[0])))
+    if (characters == end || !isNameStartCodePoint(characters[0]))
         return false;
     ++characters;
 
     // {nmchar}*
     for (; characters != end; ++characters) {
-        if (!(characters[0] == '_' || characters[0] == '-' || characters[0] >= 128 || isASCIIAlphanumeric(characters[0])))
+        if (!isNameCodePoint(characters[0]))
             return false;
     }
 
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
index 4b9e74e5..e4083c36 100644
--- a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
+++ b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
@@ -644,18 +644,20 @@
     CSSValueList* list = CSSValueList::createSpaceSeparated();
     size_t insertionIndex;
     if (isLayoutGrid) {
-        const Vector<LayoutUnit>& trackPositions = direction == ForColumns ? toLayoutGrid(layoutObject)->columnPositions() : toLayoutGrid(layoutObject)->rowPositions();
+        const auto* grid = toLayoutGrid(layoutObject);
+        const Vector<LayoutUnit>& trackPositions = direction == ForColumns ? grid->columnPositions() : grid->rowPositions();
         // There are at least #tracks + 1 grid lines (trackPositions). Apart from that, the grid container can generate implicit grid tracks,
         // so we'll have more trackPositions than trackSizes as the latter only contain the explicit grid.
         ASSERT(trackPositions.size() - 1 >= trackSizes.size());
 
         size_t i;
-        LayoutUnit gutterSize = toLayoutGrid(layoutObject)->guttersSize(direction, 2);
+        LayoutUnit gutterSize = grid->guttersSize(direction, 2);
+        LayoutUnit offsetBetweenTracks = grid->offsetBetweenTracks(direction);
         for (i = 0; i < trackPositions.size() - 2; ++i) {
             addValuesForNamedGridLinesAtIndex(orderedNamedGridLines, i, *list);
-            list->append(zoomAdjustedPixelValue(trackPositions[i + 1] - trackPositions[i] - gutterSize, style));
+            list->append(zoomAdjustedPixelValue(trackPositions[i + 1] - trackPositions[i] - gutterSize - offsetBetweenTracks, style));
         }
-        // Last track line does not have any gutter.
+        // Last track line does not have any gutter or distribution offset.
         addValuesForNamedGridLinesAtIndex(orderedNamedGridLines, i, *list);
         list->append(zoomAdjustedPixelValue(trackPositions[i + 1] - trackPositions[i], style));
         insertionIndex = trackPositions.size() - 1;
diff --git a/third_party/WebKit/Source/core/css/MediaQueryEvaluator.cpp b/third_party/WebKit/Source/core/css/MediaQueryEvaluator.cpp
index 92f06db..d720cb9a 100644
--- a/third_party/WebKit/Source/core/css/MediaQueryEvaluator.cpp
+++ b/third_party/WebKit/Source/core/css/MediaQueryEvaluator.cpp
@@ -173,6 +173,20 @@
     return false;
 }
 
+bool compareDoubleValue(double a, double b, MediaFeaturePrefix op)
+{
+    const double precision = std::numeric_limits<double>::epsilon();
+    switch (op) {
+    case MinPrefix:
+        return a >= (b - precision);
+    case MaxPrefix:
+        return a <= (b + precision);
+    case NoPrefix:
+        return std::abs(a - b) <= precision;
+    }
+    return false;
+}
+
 static bool compareAspectRatioValue(const MediaQueryExpValue& value, int width, int height, MediaFeaturePrefix op)
 {
     if (value.isRatio)
@@ -374,7 +388,7 @@
 static bool computeLengthAndCompare(const MediaQueryExpValue& value, MediaFeaturePrefix op, const MediaValues& mediaValues, double compareToValue)
 {
     double length;
-    return computeLength(value, mediaValues, length) && compareValue(compareToValue, length, op);
+    return computeLength(value, mediaValues, length) && compareDoubleValue(compareToValue, length, op);
 }
 
 static bool deviceHeightMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix op, const MediaValues& mediaValues)
diff --git a/third_party/WebKit/Source/core/css/MediaQueryEvaluatorTest.cpp b/third_party/WebKit/Source/core/css/MediaQueryEvaluatorTest.cpp
index 2cb2eb368..3f4fdab 100644
--- a/third_party/WebKit/Source/core/css/MediaQueryEvaluatorTest.cpp
+++ b/third_party/WebKit/Source/core/css/MediaQueryEvaluatorTest.cpp
@@ -115,6 +115,18 @@
     {0, 0} // Do not remove the terminator line.
 };
 
+TestCase floatNonFriendlyViewportTestCases[] = {
+    {"(min-width: 821px)", 1},
+    {"(max-width: 821px)", 1},
+    {"(width: 821px)", 1},
+    {"(min-height: 821px)", 1},
+    {"(max-height: 821px)", 1},
+    {"(height: 821px)", 1},
+    {"(width: 100vw)", 1},
+    {"(height: 100vh)", 1},
+    {0, 0} // Do not remove the terminator line.
+};
+
 TestCase printTestCases[] = {
     {"print and (min-resolution: 1dppx)", 1},
     {"print and (min-resolution: 118dpcm)", 1},
@@ -127,7 +139,7 @@
     Persistent<MediaQuerySet> querySet = nullptr;
     for (unsigned i = 0; testCases[i].input; ++i) {
         querySet = MediaQuerySet::create(testCases[i].input);
-        ASSERT_EQ(testCases[i].output, mediaQueryEvaluator.eval(querySet.get()));
+        EXPECT_EQ(testCases[i].output, mediaQueryEvaluator.eval(querySet.get()));
     }
 }
 
@@ -193,4 +205,15 @@
     testMQEvaluator(floatViewportTestCases, mediaQueryEvaluator);
 }
 
+TEST(MediaQueryEvaluatorTest, CachedFloatViewportNonFloatFriendly)
+{
+    MediaValuesCached::MediaValuesCachedData data;
+    data.viewportWidth = 821;
+    data.viewportHeight = 821;
+    MediaValues* mediaValues = MediaValuesCached::create(data);
+
+    MediaQueryEvaluator mediaQueryEvaluator(*mediaValues);
+    testMQEvaluator(floatNonFriendlyViewportTestCases, mediaQueryEvaluator);
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/css/MediaValues.cpp b/third_party/WebKit/Source/core/css/MediaValues.cpp
index 6f7cbc2..2b52736 100644
--- a/third_party/WebKit/Source/core/css/MediaValues.cpp
+++ b/third_party/WebKit/Source/core/css/MediaValues.cpp
@@ -159,61 +159,52 @@
     // CSSToLengthConversionData::zoomedComputedPixels() more generic (to solve both cases) without hurting performance.
 
     // FIXME - Unite the logic here with CSSToLengthConversionData in a performant way.
-    double factor = 0;
     switch (type) {
     case CSSPrimitiveValue::UnitType::Ems:
     case CSSPrimitiveValue::UnitType::Rems:
-        factor = defaultFontSize;
-        break;
+        result = value * defaultFontSize;
+        return true;
     case CSSPrimitiveValue::UnitType::Pixels:
     case CSSPrimitiveValue::UnitType::UserUnits:
-        factor = 1;
-        break;
+        result = value;
+        return true;
     case CSSPrimitiveValue::UnitType::Exs:
         // FIXME: We have a bug right now where the zoom will be applied twice to EX units.
-        // FIXME: We don't seem to be able to cache fontMetrics related values.
-        // Trying to access them is triggering some sort of microtask. Serving the spec's default instead.
-        factor = defaultFontSize / 2.0;
-        break;
     case CSSPrimitiveValue::UnitType::Chs:
         // FIXME: We don't seem to be able to cache fontMetrics related values.
-        // Trying to access them is triggering some sort of microtask. Serving the (future) spec default instead.
-        factor = defaultFontSize / 2.0;
-        break;
+        // Trying to access them is triggering some sort of microtask. Serving the spec's default instead.
+        result = (value * defaultFontSize) / 2.0;
+        return true;
     case CSSPrimitiveValue::UnitType::ViewportWidth:
-        factor = viewportWidth / 100.0;
-        break;
+        result = (value * viewportWidth) / 100.0;
+        return true;
     case CSSPrimitiveValue::UnitType::ViewportHeight:
-        factor = viewportHeight / 100.0;
-        break;
+        result = (value * viewportHeight) / 100.0;
+        return true;
     case CSSPrimitiveValue::UnitType::ViewportMin:
-        factor = std::min(viewportWidth, viewportHeight) / 100.0;
-        break;
+        result = (value * std::min(viewportWidth, viewportHeight)) / 100.0;
+        return true;
     case CSSPrimitiveValue::UnitType::ViewportMax:
-        factor = std::max(viewportWidth, viewportHeight) / 100.0;
-        break;
+        result = (value * std::max(viewportWidth, viewportHeight)) / 100.0;
+        return true;
     case CSSPrimitiveValue::UnitType::Centimeters:
-        factor = cssPixelsPerCentimeter;
-        break;
+        result = value * cssPixelsPerCentimeter;
+        return true;
     case CSSPrimitiveValue::UnitType::Millimeters:
-        factor = cssPixelsPerMillimeter;
-        break;
+        result = value * cssPixelsPerMillimeter;
+        return true;
     case CSSPrimitiveValue::UnitType::Inches:
-        factor = cssPixelsPerInch;
-        break;
+        result = value * cssPixelsPerInch;
+        return true;
     case CSSPrimitiveValue::UnitType::Points:
-        factor = cssPixelsPerPoint;
-        break;
+        result = value * cssPixelsPerPoint;
+        return true;
     case CSSPrimitiveValue::UnitType::Picas:
-        factor = cssPixelsPerPica;
-        break;
+        result = value * cssPixelsPerPica;
+        return true;
     default:
         return false;
     }
-
-    ASSERT(factor >= 0);
-    result = value * factor;
-    return true;
 }
 
 LocalFrame* MediaValues::frameFrom(Document& document)
diff --git a/third_party/WebKit/Source/core/css/MediaValuesTest.cpp b/third_party/WebKit/Source/core/css/MediaValuesTest.cpp
index af9176bb0..3ff0e48 100644
--- a/third_party/WebKit/Source/core/css/MediaValuesTest.cpp
+++ b/third_party/WebKit/Source/core/css/MediaValuesTest.cpp
@@ -17,7 +17,7 @@
     unsigned viewportWidth;
     unsigned viewportHeight;
     bool success;
-    int output;
+    double output;
 };
 
 TEST(MediaValuesTest, Basic)
@@ -28,15 +28,16 @@
         { 40.0, CSSPrimitiveValue::UnitType::Rems, 16, 300, 300, true, 640 },
         { 40.0, CSSPrimitiveValue::UnitType::Exs, 16, 300, 300, true, 320 },
         { 40.0, CSSPrimitiveValue::UnitType::Chs, 16, 300, 300, true, 320 },
-        { 43.0, CSSPrimitiveValue::UnitType::ViewportWidth, 16, 848, 976, true, 364 },
-        { 43.0, CSSPrimitiveValue::UnitType::ViewportHeight, 16, 848, 976, true, 419 },
-        { 43.0, CSSPrimitiveValue::UnitType::ViewportMin, 16, 848, 976, true, 364 },
-        { 43.0, CSSPrimitiveValue::UnitType::ViewportMax, 16, 848, 976, true, 419 },
-        { 1.3, CSSPrimitiveValue::UnitType::Centimeters, 16, 300, 300, true, 49 },
-        { 1.3, CSSPrimitiveValue::UnitType::Millimeters, 16, 300, 300, true, 4 },
-        { 1.3, CSSPrimitiveValue::UnitType::Inches, 16, 300, 300, true, 124 },
-        { 13, CSSPrimitiveValue::UnitType::Points, 16, 300, 300, true, 17 },
-        { 1.3, CSSPrimitiveValue::UnitType::Picas, 16, 300, 300, true, 20 },
+        { 43.0, CSSPrimitiveValue::UnitType::ViewportWidth, 16, 848, 976, true, 364.64 },
+        { 100.0, CSSPrimitiveValue::UnitType::ViewportWidth, 16, 821, 976, true, 821 },
+        { 43.0, CSSPrimitiveValue::UnitType::ViewportHeight, 16, 848, 976, true, 419.68 },
+        { 43.0, CSSPrimitiveValue::UnitType::ViewportMin, 16, 848, 976, true, 364.64 },
+        { 43.0, CSSPrimitiveValue::UnitType::ViewportMax, 16, 848, 976, true, 419.68 },
+        { 1.3, CSSPrimitiveValue::UnitType::Centimeters, 16, 300, 300, true, 49.133858 },
+        { 1.3, CSSPrimitiveValue::UnitType::Millimeters, 16, 300, 300, true, 4.913386 },
+        { 1.3, CSSPrimitiveValue::UnitType::Inches, 16, 300, 300, true, 124.8 },
+        { 13, CSSPrimitiveValue::UnitType::Points, 16, 300, 300, true, 17.333333 },
+        { 1.3, CSSPrimitiveValue::UnitType::Picas, 16, 300, 300, true, 20.8 },
         { 40.0, CSSPrimitiveValue::UnitType::UserUnits, 16, 300, 300, true, 40 },
         { 1.3, CSSPrimitiveValue::UnitType::Unknown, 16, 300, 300, false, 20 },
         { 0.0, CSSPrimitiveValue::UnitType::Unknown, 0, 0, 0, false, 0.0 } // Do not remove the terminating line.
@@ -44,16 +45,16 @@
 
 
     for (unsigned i = 0; testCases[i].viewportWidth; ++i) {
-        int output = 0;
+        double output = 0;
         bool success = MediaValues::computeLength(testCases[i].value,
             testCases[i].type,
             testCases[i].fontSize,
             testCases[i].viewportWidth,
             testCases[i].viewportHeight,
             output);
-        ASSERT_EQ(testCases[i].success, success);
+        EXPECT_EQ(testCases[i].success, success);
         if (success)
-            ASSERT_EQ(testCases[i].output, output);
+            EXPECT_FLOAT_EQ(testCases[i].output, output);
     }
 }
 
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserIdioms.h b/third_party/WebKit/Source/core/css/parser/CSSParserIdioms.h
index b9ad905c..86d7aeca 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserIdioms.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserIdioms.h
@@ -42,6 +42,20 @@
     return c == ' ' || c == '\t' || c == '\n';
 }
 
+// http://dev.w3.org/csswg/css-syntax/#name-start-code-point
+template <typename CharacterType>
+bool isNameStartCodePoint(CharacterType c)
+{
+    return isASCIIAlpha(c) || c == '_' || !isASCII(c);
+}
+
+// http://dev.w3.org/csswg/css-syntax/#name-code-point
+template <typename CharacterType>
+bool isNameCodePoint(CharacterType c)
+{
+    return isNameStartCodePoint(c) || isASCIIDigit(c) || c == '-';
+}
+
 }
 
 #endif
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index 5e73636..cf70950 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -37,6 +37,7 @@
 #include "core/css/FontFace.h"
 #include "core/css/HashTools.h"
 #include "core/css/parser/CSSParserFastPaths.h"
+#include "core/css/parser/CSSParserIdioms.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/css/parser/CSSVariableParser.h"
 #include "core/frame/UseCounter.h"
@@ -3172,10 +3173,7 @@
 
     StringBuilder areaName;
     for (unsigned i = 0; i < text.length(); ++i) {
-        // TODO(rob.buis): this whitespace check misses \n and \t.
-        // https://drafts.csswg.org/css-grid/#valdef-grid-template-areas-string
-        // https://drafts.csswg.org/css-syntax-3/#whitespace
-        if (text[i] == ' ') {
+        if (isCSSSpace(text[i])) {
             if (!areaName.isEmpty()) {
                 columnNames.append(areaName.toString());
                 areaName.clear();
@@ -3190,7 +3188,8 @@
                 areaName.clear();
             }
         } else {
-            // TODO(rob.buis): only allow name code points here.
+            if (!isNameCodePoint(text[i]))
+                return Vector<String>();
             if (areaName == ".") {
                 columnNames.append(areaName.toString());
                 areaName.clear();
@@ -3214,7 +3213,8 @@
     Vector<String> columnNames = parseGridTemplateAreasColumnNames(gridRowNames);
     if (rowCount == 0) {
         columnCount = columnNames.size();
-        ASSERT(columnCount);
+        if (columnCount == 0)
+            return false;
     } else if (columnCount != columnNames.size()) {
         // The declaration is invalid if all the rows don't have the number of columns.
         return false;
diff --git a/third_party/WebKit/Source/core/css/parser/CSSTokenizer.cpp b/third_party/WebKit/Source/core/css/parser/CSSTokenizer.cpp
index 6d4a2abd..a4d30292 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSTokenizer.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSTokenizer.cpp
@@ -8,6 +8,7 @@
 #include "core/CSSTokenizerCodepoints.cpp"
 }
 
+#include "core/css/parser/CSSParserIdioms.h"
 #include "core/css/parser/CSSParserObserverWrapper.h"
 #include "core/css/parser/CSSParserTokenRange.h"
 #include "core/css/parser/CSSTokenizerInputStream.h"
@@ -83,22 +84,6 @@
     return m_tokens.size();
 }
 
-// http://dev.w3.org/csswg/css-syntax/#name-start-code-point
-static bool isNameStart(UChar c)
-{
-    if (isASCIIAlpha(c))
-        return true;
-    if (c == '_')
-        return true;
-    return !isASCII(c);
-}
-
-// http://dev.w3.org/csswg/css-syntax/#name-code-point
-static bool isNameChar(UChar c)
-{
-    return isNameStart(c) || isASCIIDigit(c) || c == '-';
-}
-
 static bool isNewLine(UChar cc)
 {
     // We check \r and \f here, since we have no preprocessing stage
@@ -271,7 +256,7 @@
 CSSParserToken CSSTokenizer::hash(UChar cc)
 {
     UChar nextChar = m_input.nextInputChar();
-    if (isNameChar(nextChar) || twoCharsAreValidEscape(nextChar, m_input.peek(1))) {
+    if (isNameCodePoint(nextChar) || twoCharsAreValidEscape(nextChar, m_input.peek(1))) {
         HashTokenType type = nextCharsAreIdentifier() ? HashTokenId : HashTokenUnrestricted;
         return CSSParserToken(type, consumeName());
     }
@@ -684,7 +669,7 @@
         UChar cc = m_input.peekWithoutReplacement(size);
         if (cc == '\0' || cc == '\\')
             break;
-        if (!isNameChar(cc)) {
+        if (!isNameCodePoint(cc)) {
             unsigned startOffset = m_input.offset();
             m_input.advance(size);
             return m_input.rangeAsCSSParserString(startOffset, size);
@@ -694,7 +679,7 @@
     StringBuilder result;
     while (true) {
         UChar cc = consume();
-        if (isNameChar(cc)) {
+        if (isNameCodePoint(cc)) {
             result.append(cc);
             continue;
         }
@@ -765,11 +750,11 @@
 bool CSSTokenizer::nextCharsAreIdentifier(UChar first)
 {
     UChar second = m_input.nextInputChar();
-    if (isNameStart(first) || twoCharsAreValidEscape(first, second))
+    if (isNameStartCodePoint(first) || twoCharsAreValidEscape(first, second))
         return true;
 
     if (first == '-')
-        return isNameStart(second) || second == '-' || nextTwoCharsAreValidEscape();
+        return isNameStartCodePoint(second) || second == '-' || nextTwoCharsAreValidEscape();
 
     return false;
 }
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h
index 6a7f6d6c..168234f 100644
--- a/third_party/WebKit/Source/core/dom/Document.h
+++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -996,7 +996,6 @@
     bool isActive() const { return m_lifecycle.isActive(); }
     bool isDetached() const { return m_lifecycle.state() >= DocumentLifecycle::Stopping; }
     bool isStopped() const { return m_lifecycle.state() == DocumentLifecycle::Stopped; }
-    bool isDisposed() const { return m_lifecycle.state() == DocumentLifecycle::Disposed; }
 
     enum HttpRefreshType {
         HttpRefreshFromHeader,
diff --git a/third_party/WebKit/Source/core/dom/DocumentLifecycle.cpp b/third_party/WebKit/Source/core/dom/DocumentLifecycle.cpp
index f68a509..382a94d 100644
--- a/third_party/WebKit/Source/core/dom/DocumentLifecycle.cpp
+++ b/third_party/WebKit/Source/core/dom/DocumentLifecycle.cpp
@@ -100,8 +100,6 @@
     case Inactive:
         if (nextState == StyleClean)
             return true;
-        if (nextState == Disposed)
-            return true;
         break;
     case VisualUpdatePending:
         if (nextState == InPreLayout)
@@ -239,11 +237,7 @@
     case Stopping:
         return nextState == Stopped;
     case Stopped:
-        return nextState == Disposed;
-    case Disposed:
-        // FIXME: We can dispose a document multiple times. This seems wrong.
-        // See https://code.google.com/p/chromium/issues/detail?id=301668.
-        return nextState == Disposed;
+        return false;
     }
     return false;
 }
@@ -320,7 +314,6 @@
         DEBUG_STRING_CASE(PaintClean);
         DEBUG_STRING_CASE(Stopping);
         DEBUG_STRING_CASE(Stopped);
-        DEBUG_STRING_CASE(Disposed);
     }
 
     ASSERT_NOT_REACHED();
diff --git a/third_party/WebKit/Source/core/dom/DocumentLifecycle.h b/third_party/WebKit/Source/core/dom/DocumentLifecycle.h
index f8c98d4..6a2d1f062 100644
--- a/third_party/WebKit/Source/core/dom/DocumentLifecycle.h
+++ b/third_party/WebKit/Source/core/dom/DocumentLifecycle.h
@@ -80,7 +80,6 @@
         // to the style/layout/compositing states.
         Stopping,
         Stopped,
-        Disposed,
     };
 
     class Scope {
diff --git a/third_party/WebKit/Source/core/dom/Node.h b/third_party/WebKit/Source/core/dom/Node.h
index 5f523d02..6e5933f 100644
--- a/third_party/WebKit/Source/core/dom/Node.h
+++ b/third_party/WebKit/Source/core/dom/Node.h
@@ -661,6 +661,8 @@
 
     DECLARE_VIRTUAL_TRACE();
 
+    DECLARE_VIRTUAL_TRACE_WRAPPERS();
+
     unsigned lengthOfContents() const;
 
     v8::Local<v8::Object> wrap(v8::Isolate*, v8::Local<v8::Object> creationContext) override;
diff --git a/third_party/WebKit/Source/core/dom/Node.idl b/third_party/WebKit/Source/core/dom/Node.idl
index 2dab0ce..9d58923 100644
--- a/third_party/WebKit/Source/core/dom/Node.idl
+++ b/third_party/WebKit/Source/core/dom/Node.idl
@@ -22,6 +22,7 @@
 
 [
     DependentLifetime,
+    TraceWrappers=(ownerDocument,parentNode,parentElement,nextSibling,previousSibling,firstChild)
 ] interface Node : EventTarget {
     const unsigned short ELEMENT_NODE = 1;
     // FIXME: Attr should not inherit from Node. crbug.com/305105
diff --git a/third_party/WebKit/Source/core/dom/NodeRareData.cpp b/third_party/WebKit/Source/core/dom/NodeRareData.cpp
index 04a158e..86ac338 100644
--- a/third_party/WebKit/Source/core/dom/NodeRareData.cpp
+++ b/third_party/WebKit/Source/core/dom/NodeRareData.cpp
@@ -30,6 +30,7 @@
 
 #include "core/dom/NodeRareData.h"
 
+#include "bindings/core/v8/ScriptWrappableVisitor.h"
 #include "core/dom/Element.h"
 #include "core/dom/ElementRareData.h"
 #include "core/frame/FrameHost.h"
diff --git a/third_party/WebKit/Source/core/dom/URL.idl b/third_party/WebKit/Source/core/dom/URL.idl
index 35f6f7fe..881851b 100644
--- a/third_party/WebKit/Source/core/dom/URL.idl
+++ b/third_party/WebKit/Source/core/dom/URL.idl
@@ -44,16 +44,7 @@
     [RaisesException, CallWith=ExecutionContext] static DOMString? createObjectURL(Blob blob);
     [CallWith=ExecutionContext] static void revokeObjectURL(DOMString url);
 
-    // TODO(sof): 'stringifier' entails an enumerable toString(),
-    //   http://heycam.github.io/webidl/#es-stringifier
-    // something URL currently doesn't provide. Switch it over to being
-    // enumerable (http://crbug.com/306606).
-    //
-    // Until that time, do not use 'stringifier'.
-    // stringifier attribute USVString href;
-    attribute USVString href;
-    [NotEnumerable, ImplementedAs=href] USVString toString();
-
+    stringifier attribute USVString href;
     readonly attribute USVString origin;
 
     attribute USVString protocol;
diff --git a/third_party/WebKit/Source/core/dom/URLUtilsReadOnly.idl b/third_party/WebKit/Source/core/dom/URLUtilsReadOnly.idl
index 9f5aac0..e2cc46d1 100644
--- a/third_party/WebKit/Source/core/dom/URLUtilsReadOnly.idl
+++ b/third_party/WebKit/Source/core/dom/URLUtilsReadOnly.idl
@@ -29,10 +29,7 @@
     NoInterfaceObject, // Always used on target of 'implements'
     Exposed=(Window,Worker),
 ] interface URLUtilsReadOnly {
-    // FIXME: should be stringifier: http://crbug.com/306606
-    // stringifier readonly attribute USVString href;
-    readonly attribute USVString href;
-    [NotEnumerable, ImplementedAs=href] USVString toString();
+    stringifier readonly attribute USVString href;
     readonly attribute USVString origin;
 
     readonly attribute USVString protocol;
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
index 1009d71..bdfadf91 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
@@ -1732,4 +1732,34 @@
     return node && node->layoutObject() && node->layoutObject()->style()->textSecurity() != TSNONE;
 }
 
+DispatchEventResult dispatchBeforeInputInsertText(EventTarget* target, const String& data)
+{
+    if (!RuntimeEnabledFeatures::inputEventEnabled())
+        return DispatchEventResult::NotCanceled;
+    if (!target)
+        return DispatchEventResult::NotCanceled;
+    InputEvent* beforeInputEvent = InputEvent::createBeforeInput(InputEvent::InputType::InsertText, data, InputEvent::EventCancelable::IsCancelable);
+    return target->dispatchEvent(beforeInputEvent);
+}
+
+DispatchEventResult dispatchBeforeInputFromComposition(EventTarget* target, InputEvent::InputType inputType, const String& data)
+{
+    if (!RuntimeEnabledFeatures::inputEventEnabled())
+        return DispatchEventResult::NotCanceled;
+    if (!target)
+        return DispatchEventResult::NotCanceled;
+    InputEvent* beforeInputEvent = InputEvent::createBeforeInput(inputType, data, InputEvent::EventCancelable::NotCancelable);
+    return target->dispatchEvent(beforeInputEvent);
+}
+
+DispatchEventResult dispatchBeforeInputEditorCommand(EventTarget* target, InputEvent::InputType inputType, const String& data)
+{
+    if (!RuntimeEnabledFeatures::inputEventEnabled())
+        return DispatchEventResult::NotCanceled;
+    if (!target)
+        return DispatchEventResult::NotCanceled;
+    InputEvent* beforeInputEvent = InputEvent::createBeforeInput(inputType, data, InputEvent::EventCancelable::IsCancelable);
+    return target->dispatchEvent(beforeInputEvent);
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.h b/third_party/WebKit/Source/core/editing/EditingUtilities.h
index 18f4cb3..49f2b52 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilities.h
+++ b/third_party/WebKit/Source/core/editing/EditingUtilities.h
@@ -33,6 +33,7 @@
 #include "core/editing/PositionWithAffinity.h"
 #include "core/editing/VisiblePosition.h"
 #include "core/editing/VisibleSelection.h"
+#include "core/events/InputEvent.h"
 #include "platform/text/TextDirection.h"
 #include "wtf/Forward.h"
 #include "wtf/text/CharacterNames.h"
@@ -346,6 +347,15 @@
 String stringWithRebalancedWhitespace(const String&, bool startIsStartOfParagraph, bool endIsEndOfParagraph);
 const String& nonBreakingSpaceString();
 
+// -------------------------------------------------------------------------
+// Events
+// -------------------------------------------------------------------------
+
+// Functions dispatch InputEvent
+DispatchEventResult dispatchBeforeInputInsertText(EventTarget*, const String& data);
+DispatchEventResult dispatchBeforeInputFromComposition(EventTarget*, InputEvent::InputType, const String& data);
+DispatchEventResult dispatchBeforeInputEditorCommand(EventTarget*, InputEvent::InputType, const String& data = "");
+
 } // namespace blink
 
 #endif
diff --git a/third_party/WebKit/Source/core/editing/EditorKeyBindings.cpp b/third_party/WebKit/Source/core/editing/EditorKeyBindings.cpp
index 6f3dca9..589c314 100644
--- a/third_party/WebKit/Source/core/editing/EditorKeyBindings.cpp
+++ b/third_party/WebKit/Source/core/editing/EditorKeyBindings.cpp
@@ -26,6 +26,7 @@
 
 #include "core/editing/Editor.h"
 
+#include "core/editing/EditingUtilities.h"
 #include "core/events/KeyboardEvent.h"
 #include "core/frame/LocalFrame.h"
 #include "core/page/EditorClient.h"
@@ -60,6 +61,10 @@
     if (!behavior().shouldInsertCharacter(*evt) || !canEdit())
         return false;
 
+    // Return true to prevent default action. e.g. Space key scroll.
+    if (dispatchBeforeInputInsertText(evt->target(), evt->keyEvent()->text()) != DispatchEventResult::NotCanceled)
+        return true;
+
     return insertText(evt->keyEvent()->text(), evt);
 }
 
diff --git a/third_party/WebKit/Source/core/editing/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
index e0bec0d..ca051a0c 100644
--- a/third_party/WebKit/Source/core/editing/InputMethodController.cpp
+++ b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
@@ -172,6 +172,11 @@
 
     clear();
 
+    // TODO(chongz): DOM update should happen before 'compositionend' and along with 'compositionupdate'.
+    // https://crbug.com/575294
+    if (dispatchBeforeInputInsertText(frame().document()->focusedElement(), text) != DispatchEventResult::NotCanceled)
+        return false;
+
     insertTextForConfirmedComposition(text);
 
     return true;
@@ -182,6 +187,10 @@
     if (!hasComposition()) {
         if (!text.length())
             return false;
+
+        if (dispatchBeforeInputInsertText(frame().document()->focusedElement(), text) != DispatchEventResult::NotCanceled)
+            return false;
+
         editor().insertText(text, 0);
         return true;
     }
@@ -278,8 +287,13 @@
             else
                 event = CompositionEvent::create(EventTypeNames::compositionend, frame().domWindow(), text);
         }
-        if (event)
+        if (event) {
+            // TODO(chongz): Support canceling IME composition.
+            // TODO(chongz): Should fire InsertText or DeleteComposedCharacter based on action.
+            if (event->type() == EventTypeNames::compositionupdate)
+                dispatchBeforeInputFromComposition(target, InputEvent::InputType::InsertText, text);
             target->dispatchEvent(event);
+        }
     }
 
     // If text is empty, then delete the old composition here. If text is non-empty, InsertTextCommand::input
@@ -453,6 +467,8 @@
             break;
         ++before;
     } while (frame().selection().start() == frame().selection().end() && before <= static_cast<int>(selectionOffsets.start()));
+    // TODO(chongz): According to spec |data| should be "forward" or "backward".
+    dispatchBeforeInputEditorCommand(frame().document()->focusedElement(), InputEvent::InputType::DeleteContent);
     TypingCommand::deleteSelection(*frame().document());
 }
 
diff --git a/third_party/WebKit/Source/core/editing/Selection.idl b/third_party/WebKit/Source/core/editing/Selection.idl
index ad3935ef..19be361 100644
--- a/third_party/WebKit/Source/core/editing/Selection.idl
+++ b/third_party/WebKit/Source/core/editing/Selection.idl
@@ -52,12 +52,9 @@
     [MeasureAs=SelectionCollapseToEnd, RaisesException] void collapseToEnd();
     [MeasureAs=SelectionExtend, RaisesException] void extend(Node node, optional long offset = 0);
     // TODO(philipj): The arguments should be anchorNode, anchorOffset,
-    // focusNode and focusOffset, and none of them are optional or nullable in
-    // the spec.
-    [MeasureAs=SelectionSetBaseAndExtent, RaisesException] void setBaseAndExtent([Default=Undefined] optional Node? baseNode,
-                                                                                 [Default=Undefined] optional long baseOffset,
-                                                                                 [Default=Undefined] optional Node? extentNode,
-                                                                                 [Default=Undefined] optional long extentOffset);
+    // focusNode and focusOffset, and none of them are nullable in the spec.
+    [MeasureAs=SelectionSetBaseAndExtent, RaisesException] void setBaseAndExtent(Node? baseNode, long baseOffset,
+                                                                                 Node? extentNode, long extentOffset);
     [MeasureAs=SelectionSelectAllChildren, RaisesException] void selectAllChildren(Node node);
     [MeasureAs=SelectionDeleteDromDocument, CustomElementCallbacks] void deleteFromDocument();
     [MeasureAs=SelectionContainsNode] boolean containsNode(Node node, optional boolean allowPartialContainment = false);
diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
index 82083270..b71feb9 100644
--- a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
@@ -104,6 +104,33 @@
     return WebEditingCommandType::Invalid;
 }
 
+InputEvent::InputType InputTypeFromCommandType(WebEditingCommandType commandType)
+{
+    switch (commandType) {
+    case WebEditingCommandType::Delete:
+    case WebEditingCommandType::DeleteBackward:
+    case WebEditingCommandType::DeleteBackwardByDecomposingPreviousCharacter:
+    case WebEditingCommandType::DeleteForward:
+    case WebEditingCommandType::DeleteToBeginningOfLine:
+    case WebEditingCommandType::DeleteToBeginningOfParagraph:
+    case WebEditingCommandType::DeleteToEndOfLine:
+    case WebEditingCommandType::DeleteToEndOfParagraph:
+    case WebEditingCommandType::DeleteToMark:
+    case WebEditingCommandType::DeleteWordBackward:
+    case WebEditingCommandType::DeleteWordForward:
+        return InputEvent::InputType::DeleteContent;
+    case WebEditingCommandType::Redo:
+        return InputEvent::InputType::Redo;
+    case WebEditingCommandType::Undo:
+        return InputEvent::InputType::Undo;
+    case WebEditingCommandType::InsertBacktab:
+    case WebEditingCommandType::InsertText:
+        return InputEvent::InputType::InsertText;
+    default:
+        return InputEvent::InputType::None;
+    }
+}
+
 } // anonymous namespace
 
 class EditorInternalCommand {
@@ -1751,6 +1778,19 @@
         if (!isSupported() || !m_frame || !m_command->allowExecutionWhenDisabled)
             return false;
     }
+
+    if (m_source == CommandFromMenuOrKeyBinding) {
+        InputEvent::InputType inputType = InputTypeFromCommandType(m_command->commandType);
+        if (inputType != InputEvent::InputType::None) {
+            if (dispatchBeforeInputEditorCommand(eventTargetNodeForDocument(m_frame->document()), inputType) != DispatchEventResult::NotCanceled)
+                return true;
+        }
+    }
+
+    // 'beforeinput' event handler may destroy |frame()|.
+    if (!m_frame || !frame().document())
+        return false;
+
     frame().document()->updateLayoutIgnorePendingStylesheets();
     DEFINE_STATIC_LOCAL(SparseHistogram, commandHistogram, ("WebCore.Editing.Commands"));
     commandHistogram.sample(static_cast<int>(m_command->commandType));
diff --git a/third_party/WebKit/Source/core/events/EventTypeNames.in b/third_party/WebKit/Source/core/events/EventTypeNames.in
index a7f5ac4..f9f9c81 100644
--- a/third_party/WebKit/Source/core/events/EventTypeNames.in
+++ b/third_party/WebKit/Source/core/events/EventTypeNames.in
@@ -28,6 +28,7 @@
 availablechange
 beforecopy
 beforecut
+beforeinput
 beforeinstallprompt
 beforepaste
 beforeunload
diff --git a/third_party/WebKit/Source/core/events/InputEvent.cpp b/third_party/WebKit/Source/core/events/InputEvent.cpp
index f7eb07a..e5bef79 100644
--- a/third_party/WebKit/Source/core/events/InputEvent.cpp
+++ b/third_party/WebKit/Source/core/events/InputEvent.cpp
@@ -5,9 +5,48 @@
 #include "core/events/InputEvent.h"
 
 #include "core/events/EventDispatcher.h"
+#include "public/platform/WebEditingCommandType.h"
 
 namespace blink {
 
+namespace {
+
+const struct {
+    InputEvent::InputType inputType;
+    const char* stringName;
+} kInputTypeStringNameMap[] = {
+    {InputEvent::InputType::None, ""},
+    {InputEvent::InputType::InsertText, "insertText"},
+    {InputEvent::InputType::ReplaceContent, "replaceContent"},
+    {InputEvent::InputType::DeleteContent, "deleteContent"},
+    {InputEvent::InputType::DeleteComposedCharacter, "deleteComposedCharacter"},
+    {InputEvent::InputType::Undo, "undo"},
+    {InputEvent::InputType::Redo, "redo"},
+};
+
+static_assert(arraysize(kInputTypeStringNameMap) == static_cast<size_t>(InputEvent::InputType::NumberOfInputTypes),
+    "must handle all InputEvent::InputType");
+
+String convertInputTypeToString(InputEvent::InputType inputType)
+{
+    const auto& it = std::begin(kInputTypeStringNameMap) + static_cast<size_t>(inputType);
+    if (it >= std::begin(kInputTypeStringNameMap) && it < std::end(kInputTypeStringNameMap))
+        return AtomicString(it->stringName);
+    return emptyString();
+}
+
+InputEvent::InputType convertStringToInputType(const String& stringName)
+{
+    // TODO(chongz): Use binary search if the map goes larger.
+    for (const auto& entry : kInputTypeStringNameMap) {
+        if (stringName == entry.stringName)
+            return entry.inputType;
+    }
+    return InputEvent::InputType::None;
+}
+
+} // anonymous namespace
+
 InputEvent::InputEvent()
 {
 }
@@ -15,6 +54,32 @@
 InputEvent::InputEvent(const AtomicString& type, const InputEventInit& initializer)
     : UIEvent(type, initializer)
 {
+    // TODO(ojan): We should find a way to prevent conversion like String->enum->String just in order to use initializer.
+    // See InputEvent::createBeforeInput() for the first conversion.
+    if (initializer.hasInputType())
+        m_inputType = convertStringToInputType(initializer.inputType());
+    if (initializer.hasData())
+        m_data = initializer.data();
+}
+
+/* static */
+InputEvent* InputEvent::createBeforeInput(InputType inputType, const String& data, EventCancelable cancelable)
+{
+    InputEventInit inputEventInit;
+
+    inputEventInit.setBubbles(true);
+    inputEventInit.setCancelable(cancelable == IsCancelable);
+    // TODO(ojan): We should find a way to prevent conversion like String->enum->String just in order to use initializer.
+    // See InputEvent::InputEvent() for the second conversion.
+    inputEventInit.setInputType(convertInputTypeToString(inputType));
+    inputEventInit.setData(data);
+
+    return InputEvent::create(EventTypeNames::beforeinput, inputEventInit);
+}
+
+String InputEvent::inputType() const
+{
+    return convertInputTypeToString(m_inputType);
 }
 
 bool InputEvent::isInputEvent() const
diff --git a/third_party/WebKit/Source/core/events/InputEvent.h b/third_party/WebKit/Source/core/events/InputEvent.h
index 8bfb45ef..4c14550f 100644
--- a/third_party/WebKit/Source/core/events/InputEvent.h
+++ b/third_party/WebKit/Source/core/events/InputEvent.h
@@ -24,6 +24,29 @@
         return new InputEvent(type, initializer);
     }
 
+    enum class InputType {
+        None,
+        InsertText,
+        ReplaceContent,
+        DeleteContent,
+        DeleteComposedCharacter,
+        Undo,
+        Redo,
+
+        // Add new input types immediately above this line.
+        NumberOfInputTypes,
+    };
+
+    enum EventCancelable : bool {
+        NotCancelable = false,
+        IsCancelable = true,
+    };
+
+    static InputEvent* createBeforeInput(InputType, const String& data, EventCancelable);
+
+    String inputType() const;
+    const String& data() const { return m_data; }
+
     bool isInputEvent() const override;
 
     DECLARE_VIRTUAL_TRACE();
@@ -31,6 +54,9 @@
 private:
     InputEvent();
     InputEvent(const AtomicString&, const InputEventInit&);
+
+    InputType m_inputType;
+    String m_data;
 };
 
 DEFINE_EVENT_TYPE_CASTS(InputEvent);
diff --git a/third_party/WebKit/Source/core/events/InputEvent.idl b/third_party/WebKit/Source/core/events/InputEvent.idl
index cc1d595..6d6dfa7 100644
--- a/third_party/WebKit/Source/core/events/InputEvent.idl
+++ b/third_party/WebKit/Source/core/events/InputEvent.idl
@@ -8,5 +8,7 @@
     Constructor(DOMString type, optional InputEventInit eventInitDict),
     RuntimeEnabled=InputEvent,
 ] interface InputEvent : UIEvent {
-    // TODO(chongz): Add 'inputType', 'data', 'isComposing' and 'targetRanges'
+    readonly attribute DOMString inputType;
+    readonly attribute DOMString data;
+    // TODO(chongz): Add 'isComposing' and 'targetRanges'
 };
diff --git a/third_party/WebKit/Source/core/events/InputEventInit.idl b/third_party/WebKit/Source/core/events/InputEventInit.idl
index 6b2d07d..89c8e09 100644
--- a/third_party/WebKit/Source/core/events/InputEventInit.idl
+++ b/third_party/WebKit/Source/core/events/InputEventInit.idl
@@ -7,5 +7,7 @@
 [
     RuntimeEnabled=InputEvent,
 ] dictionary InputEventInit : UIEventInit {
-    // TODO(chongz): Add 'inputType', 'data', 'isComposing' and 'targetRanges'
+    DOMString inputType = "";
+    DOMString data = "";
+    // TODO(chongz): Add 'isComposing' and 'targetRanges'
 };
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp
index 864a48a..363f4c2 100644
--- a/third_party/WebKit/Source/core/frame/FrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -38,6 +38,7 @@
 #include "core/editing/RenderedPosition.h"
 #include "core/editing/markers/DocumentMarkerController.h"
 #include "core/fetch/ResourceFetcher.h"
+#include "core/frame/EventHandlerRegistry.h"
 #include "core/frame/FrameHost.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/Location.h"
@@ -1623,7 +1624,7 @@
 
 bool FrameView::computeCompositedSelection(LocalFrame& frame, CompositedSelection& selection)
 {
-    if (frame.view()->shouldThrottleRendering())
+    if (!frame.view() || frame.view()->shouldThrottleRendering())
         return false;
 
     const VisibleSelection& visibleSelection = frame.selection().selection();
@@ -4028,9 +4029,10 @@
     }
 
     bool becameUnthrottled = wasThrottled && !canThrottleRendering();
+    ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
     if (becameUnthrottled) {
         // ScrollingCoordinator needs to update according to the new throttling status.
-        if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+        if (scrollingCoordinator)
             scrollingCoordinator->notifyGeometryChanged();
         // Start ticking animation frames again if necessary.
         page()->animator().scheduleVisualUpdate(m_frame.get());
@@ -4040,6 +4042,10 @@
         if (LayoutView* layoutView = this->layoutView())
             layoutView->invalidatePaintForViewAndCompositedLayers();
     }
+
+    bool hasHandlers = m_frame->document()->frameHost()->eventHandlerRegistry().hasEventHandlers(EventHandlerRegistry::TouchStartOrMoveEventBlocking);
+    if (wasThrottled != canThrottleRendering() && scrollingCoordinator && hasHandlers)
+        scrollingCoordinator->touchEventTargetRectsDidChange();
 }
 
 bool FrameView::shouldThrottleRendering() const
diff --git a/third_party/WebKit/Source/core/html/HTMLHyperlinkElementUtils.idl b/third_party/WebKit/Source/core/html/HTMLHyperlinkElementUtils.idl
index f30281e..554cb3ad 100644
--- a/third_party/WebKit/Source/core/html/HTMLHyperlinkElementUtils.idl
+++ b/third_party/WebKit/Source/core/html/HTMLHyperlinkElementUtils.idl
@@ -7,15 +7,7 @@
 [
     NoInterfaceObject, // Always used on target of 'implements'
 ] interface HTMLHyperlinkElementUtils {
-    // TODO(sof): 'stringifier' entails an enumerable toString(),
-    //   http://heycam.github.io/webidl/#es-stringifier
-    // something implementations of HTMLHyperlinkElementUtils currently
-    // provide. Make them to comply with the spec (http://crbug.com/306606).
-    //
-    // Until that time, do not use 'stringifier'.
-    // stringifier attribute USVString href;
-    attribute USVString href;
-    [NotEnumerable, ImplementedAs=href] USVString toString();
+    stringifier attribute USVString href;
     readonly attribute USVString origin;
 
     attribute USVString protocol;
diff --git a/third_party/WebKit/Source/core/html/HTMLInputElement.cpp b/third_party/WebKit/Source/core/html/HTMLInputElement.cpp
index 93524f6f..560b519 100644
--- a/third_party/WebKit/Source/core/html/HTMLInputElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLInputElement.cpp
@@ -225,7 +225,7 @@
 
 bool HTMLInputElement::hasBadInput() const
 {
-    return willValidate() && m_inputType->hasBadInput();
+    return willValidate() && m_inputTypeView->hasBadInput();
 }
 
 bool HTMLInputElement::patternMismatch() const
@@ -438,7 +438,7 @@
 
     const AtomicString& newTypeName = InputType::normalizeTypeName(fastGetAttribute(typeAttr));
     m_inputType = InputType::create(*this, newTypeName);
-    m_inputTypeView = m_inputType;
+    m_inputTypeView = m_inputType->createView();
     ensureUserAgentShadowRoot();
 
     updateTouchEventHandlerRegistry();
@@ -547,12 +547,12 @@
 
 FormControlState HTMLInputElement::saveFormControlState() const
 {
-    return m_inputType->saveFormControlState();
+    return m_inputTypeView->saveFormControlState();
 }
 
 void HTMLInputElement::restoreFormControlState(const FormControlState& state)
 {
-    m_inputType->restoreFormControlState(state);
+    m_inputTypeView->restoreFormControlState(state);
     m_stateRestored = true;
 }
 
@@ -637,7 +637,7 @@
 
 void HTMLInputElement::accessKeyAction(bool sendMouseEvents)
 {
-    m_inputType->accessKeyAction(sendMouseEvents);
+    m_inputTypeView->accessKeyAction(sendMouseEvents);
 }
 
 bool HTMLInputElement::isPresentationAttribute(const QualifiedName& name) const
@@ -1211,7 +1211,7 @@
     // on the element, or presses enter while it is the active element. JavaScript code wishing to activate the element
     // must dispatch a DOMActivate event - a click event will not do the job.
     if (evt->type() == EventTypeNames::DOMActivate) {
-        m_inputType->handleDOMActivateEvent(evt);
+        m_inputTypeView->handleDOMActivateEvent(evt);
         if (evt->defaultHandled())
             return;
     }
@@ -1858,7 +1858,7 @@
     parameters.anchorRectInScreen = document().view()->contentsToScreen(pixelSnappedBoundingBox());
     parameters.currentValue = value();
     parameters.doubleValue = m_inputType->valueAsDouble();
-    parameters.isAnchorElementRTL = m_inputType->computedTextDirection() == RTL;
+    parameters.isAnchorElementRTL = m_inputTypeView->computedTextDirection() == RTL;
     if (HTMLDataListElement* dataList = this->dataList()) {
         HTMLDataListOptionsCollection* options = dataList->options();
         for (unsigned i = 0; HTMLOptionElement* option = options->item(i); ++i) {
diff --git a/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.cpp b/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.cpp
index 136f2de..159edb84 100644
--- a/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.cpp
@@ -32,6 +32,7 @@
 
 #include "core/html/HTMLInputElement.h"
 #include "core/html/forms/BaseChooserOnlyDateAndTimeInputType.h"
+#include "core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h"
 #include "platform/text/PlatformLocale.h"
 #include "wtf/CurrentTime.h"
 #include "wtf/DateMath.h"
@@ -47,13 +48,16 @@
 static const int msecPerMinute = 60 * 1000;
 static const int msecPerSecond = 1000;
 
+String BaseDateAndTimeInputType::badInputText() const
+{
+    return locale().queryString(WebLocalizedString::ValidationBadInputForDateTime);
+}
+
 InputTypeView* BaseDateAndTimeInputType::createView()
 {
-    if (!RuntimeEnabledFeatures::inputMultipleFieldsUIEnabled())
-        return BaseChooserOnlyDateAndTimeInputType::create(element(), *this);
-    // TODO(tkent): Returns MultipleFieldsDateAndTimeInputTypeView.
-    // crbug.com/243714
-    return this;
+    if (RuntimeEnabledFeatures::inputMultipleFieldsUIEnabled())
+        return BaseMultipleFieldsDateAndTimeInputType::create(element(), *this);
+    return BaseChooserOnlyDateAndTimeInputType::create(element(), *this);
 }
 
 double BaseDateAndTimeInputType::valueAsDate() const
diff --git a/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.h b/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.h
index e6638e1aa4..bbc1eb0 100644
--- a/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.h
@@ -40,9 +40,21 @@
 class ExceptionState;
 
 // A super class of date, datetime, datetime-local, month, time, and week types.
+// TODO(tkent): A single temporal input type creates two InputTypeView instances
+// unnecessarily.  One is BaseChooserOnlyDateAndTimeInputType or
+// BaseMultipleFieldsDateAndTimeInputType, and another is
+// BaseDateAndTimeInputType, which inherits from InputTypeView through
+// InputType.  The latter is not used.
 class BaseDateAndTimeInputType : public InputType {
 public:
     String visibleValue() const override;
+    String sanitizeValue(const String&) const override;
+    // Parses the specified string for this InputType, and returns true if it
+    // is successfully parsed. An instance pointed by the DateComponents*
+    // parameter will have parsed values and be modified even if the parsing
+    // fails. The DateComponents* parameter may be 0.
+    bool parseToDateComponents(const String&, DateComponents*) const;
+    virtual bool setMillisecondToDateComponents(double, DateComponents*) const = 0;
 
     // Provide some helpers for BaseMultipleFieldsDateAndTimeInputType.
     virtual String formatDateTimeFieldsState(const DateTimeFieldsState&) const = 0;
@@ -52,20 +64,14 @@
 protected:
     BaseDateAndTimeInputType(HTMLInputElement& element) : InputType(element) { }
     Decimal parseToNumber(const String&, const Decimal&) const override;
-    // Parses the specified string for this InputType, and returns true if it
-    // is successfully parsed. An instance pointed by the DateComponents*
-    // parameter will have parsed values and be modified even if the parsing
-    // fails. The DateComponents* parameter may be 0.
-    bool parseToDateComponents(const String&, DateComponents*) const;
-    String sanitizeValue(const String&) const override;
     String serialize(const Decimal&) const override;
     String serializeWithComponents(const DateComponents&) const;
-    virtual bool setMillisecondToDateComponents(double, DateComponents*) const = 0;
     bool shouldHaveSecondField(const DateComponents&) const;
 
 private:
     virtual bool parseToDateComponentsInternal(const String&, DateComponents*) const = 0;
 
+    String badInputText() const override;
     InputTypeView* createView() override;
     double valueAsDate() const override;
     void setValueAsDate(double, ExceptionState&) const override;
diff --git a/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp b/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp
index 9807bf3..1c4b493 100644
--- a/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp
@@ -30,7 +30,6 @@
 
 #include "core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h"
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 #include "core/CSSValueKeywords.h"
 #include "core/dom/StyleChangeReason.h"
 #include "core/dom/shadow/ShadowRoot.h"
@@ -39,6 +38,7 @@
 #include "core/html/HTMLDataListElement.h"
 #include "core/html/HTMLInputElement.h"
 #include "core/html/HTMLOptionElement.h"
+#include "core/html/forms/BaseDateAndTimeInputType.h"
 #include "core/html/forms/DateTimeFieldsState.h"
 #include "core/html/forms/FormController.h"
 #include "core/html/shadow/ShadowElementNames.h"
@@ -68,7 +68,7 @@
     void visitField(DateTimeFormat::FieldType, int) final;
     void visitLiteral(const String&) final { }
 
-    bool validateFormat(const String& format, const BaseMultipleFieldsDateAndTimeInputType&);
+    bool validateFormat(const String& format, const BaseDateAndTimeInputType&);
 
 private:
     bool m_hasYear;
@@ -120,7 +120,7 @@
     }
 }
 
-bool DateTimeFormatValidator::validateFormat(const String& format, const BaseMultipleFieldsDateAndTimeInputType& inputType)
+bool DateTimeFormatValidator::validateFormat(const String& format, const BaseDateAndTimeInputType& inputType)
 {
     if (!DateTimeFormat::parse(format, *this))
         return false;
@@ -181,7 +181,7 @@
 void BaseMultipleFieldsDateAndTimeInputType::editControlValueChanged()
 {
     String oldValue = element().value();
-    String newValue = sanitizeValue(dateTimeEditElement()->value());
+    String newValue = m_inputType->sanitizeValue(dateTimeEditElement()->value());
     // Even if oldValue is null and newValue is "", we should assume they are same.
     if ((oldValue.isEmpty() && newValue.isEmpty()) || oldValue == newValue) {
         element().setNeedsValidityCheck();
@@ -194,6 +194,11 @@
     element().updateClearButtonVisibility();
 }
 
+String BaseMultipleFieldsDateAndTimeInputType::formatDateTimeFieldsState(const DateTimeFieldsState& state) const
+{
+    return m_inputType->formatDateTimeFieldsState(state);
+}
+
 bool BaseMultipleFieldsDateAndTimeInputType::hasCustomFocusLogic() const
 {
     return false;
@@ -289,21 +294,28 @@
     return element().setupDateTimeChooserParameters(parameters);
 }
 
-BaseMultipleFieldsDateAndTimeInputType::BaseMultipleFieldsDateAndTimeInputType(HTMLInputElement& element)
-    : BaseDateAndTimeInputType(element)
+BaseMultipleFieldsDateAndTimeInputType::BaseMultipleFieldsDateAndTimeInputType(HTMLInputElement& element, BaseDateAndTimeInputType& inputType)
+    : InputTypeView(element)
+    , m_inputType(inputType)
     , m_isDestroyingShadowSubtree(false)
     , m_pickerIndicatorIsVisible(false)
     , m_pickerIndicatorIsAlwaysVisible(false)
 {
 }
 
+BaseMultipleFieldsDateAndTimeInputType* BaseMultipleFieldsDateAndTimeInputType::create(HTMLInputElement& element, BaseDateAndTimeInputType& inputType)
+{
+    return new BaseMultipleFieldsDateAndTimeInputType(element, inputType);
+}
+
 BaseMultipleFieldsDateAndTimeInputType::~BaseMultipleFieldsDateAndTimeInputType()
 {
 }
 
-String BaseMultipleFieldsDateAndTimeInputType::badInputText() const
+DEFINE_TRACE(BaseMultipleFieldsDateAndTimeInputType)
 {
-    return locale().queryString(WebLocalizedString::ValidationBadInputForDateTime);
+    visitor->trace(m_inputType);
+    InputTypeView::trace(visitor);
 }
 
 void BaseMultipleFieldsDateAndTimeInputType::blur()
@@ -349,7 +361,7 @@
     container->appendChild(ClearButtonElement::create(document, *this));
     container->appendChild(SpinButtonElement::create(document, *this));
 
-    if (LayoutTheme::theme().supportsCalendarPicker(formControlType()))
+    if (LayoutTheme::theme().supportsCalendarPicker(m_inputType->formControlType()))
         m_pickerIndicatorIsAlwaysVisible = true;
     container->appendChild(PickerIndicatorElement::create(document, *this));
     m_pickerIndicatorIsVisible = true;
@@ -374,7 +386,7 @@
     if (containsFocusedShadowElement())
         element().focus();
 
-    BaseDateAndTimeInputType::destroyShadowSubtree();
+    InputTypeView::destroyShadowSubtree();
     m_isDestroyingShadowSubtree = false;
 }
 
@@ -468,7 +480,7 @@
         return;
     DateTimeFieldsState dateTimeFieldsState = DateTimeFieldsState::restoreFormControlState(state);
     edit->setValueAsDateTimeFieldsState(dateTimeFieldsState);
-    element().setValueInternal(sanitizeValue(edit->value()), DispatchNoEvent);
+    element().setValueInternal(m_inputType->sanitizeValue(edit->value()), DispatchNoEvent);
     updateClearButtonVisibility();
 }
 
@@ -499,18 +511,18 @@
     if (!edit)
         return;
 
-    DateTimeEditElement::LayoutParameters layoutParameters(element().locale(), createStepRange(AnyIsDefaultStep));
+    DateTimeEditElement::LayoutParameters layoutParameters(element().locale(), m_inputType->createStepRange(AnyIsDefaultStep));
 
     DateComponents date;
     bool hasValue = false;
     if (!element().suggestedValue().isNull())
-        hasValue = parseToDateComponents(element().suggestedValue(), &date);
+        hasValue = m_inputType->parseToDateComponents(element().suggestedValue(), &date);
     else
-        hasValue = parseToDateComponents(element().value(), &date);
+        hasValue = m_inputType->parseToDateComponents(element().value(), &date);
     if (!hasValue)
-        setMillisecondToDateComponents(layoutParameters.stepRange.minimum().toDouble(), &date);
+        m_inputType->setMillisecondToDateComponents(layoutParameters.stepRange.minimum().toDouble(), &date);
 
-    setupLayoutParameters(layoutParameters, date);
+    m_inputType->setupLayoutParameters(layoutParameters, date);
 
     DEFINE_STATIC_LOCAL(AtomicString, datetimeformatAttr, ("datetimeformat"));
     edit->setAttribute(datetimeformatAttr, AtomicString(layoutParameters.dateTimeFormat), ASSERT_NO_EXCEPTION);
@@ -518,7 +530,7 @@
     if (!pattern.isEmpty())
         layoutParameters.dateTimeFormat = pattern;
 
-    if (!DateTimeFormatValidator().validateFormat(layoutParameters.dateTimeFormat, *this))
+    if (!DateTimeFormatValidator().validateFormat(layoutParameters.dateTimeFormat, *m_inputType))
         layoutParameters.dateTimeFormat = layoutParameters.fallbackDateTimeFormat;
 
     if (hasValue)
@@ -619,5 +631,3 @@
 }
 
 } // namespace blink
-
-#endif
diff --git a/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h b/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h
index 9b059a1..e603b7f 100644
--- a/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h
@@ -31,10 +31,7 @@
 #ifndef BaseMultipleFieldsDateAndTimeInputType_h
 #define BaseMultipleFieldsDateAndTimeInputType_h
 
-#include "wtf/build_config.h"
-
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-#include "core/html/forms/BaseDateAndTimeInputType.h"
+#include "core/html/forms/InputTypeView.h"
 #include "core/html/shadow/ClearButtonElement.h"
 #include "core/html/shadow/DateTimeEditElement.h"
 #include "core/html/shadow/PickerIndicatorElement.h"
@@ -42,10 +39,12 @@
 
 namespace blink {
 
+class BaseDateAndTimeInputType;
 struct DateTimeChooserParameters;
 
-class BaseMultipleFieldsDateAndTimeInputType
-    : public BaseDateAndTimeInputType
+// TODO(tkent): Rename this to MultipleFieldsTemporalInputTypeView.
+class BaseMultipleFieldsDateAndTimeInputType final
+    : public InputTypeView
     , protected DateTimeEditElement::EditControlOwner
     , protected PickerIndicatorElement::PickerIndicatorOwner
     , protected SpinButtonElement::SpinButtonOwner
@@ -53,17 +52,18 @@
     USING_GARBAGE_COLLECTED_MIXIN(BaseMultipleFieldsDateAndTimeInputType);
 
 public:
-    DEFINE_INLINE_VIRTUAL_TRACE() { BaseDateAndTimeInputType::trace(visitor); }
-
-protected:
-    BaseMultipleFieldsDateAndTimeInputType(HTMLInputElement&);
+    static BaseMultipleFieldsDateAndTimeInputType* create(HTMLInputElement&, BaseDateAndTimeInputType&);
     ~BaseMultipleFieldsDateAndTimeInputType() override;
+    DECLARE_VIRTUAL_TRACE();
 
 private:
+    BaseMultipleFieldsDateAndTimeInputType(HTMLInputElement&, BaseDateAndTimeInputType&);
+
     // DateTimeEditElement::EditControlOwner functions
     void didBlurFromControl() final;
     void didFocusOnControl() final;
     void editControlValueChanged() final;
+    String formatDateTimeFieldsState(const DateTimeFieldsState&) const override;
     bool isEditControlOwnerDisabled() const final;
     bool isEditControlOwnerReadOnly() const final;
     AtomicString localeIdentifier() const final;
@@ -89,8 +89,7 @@
     bool shouldClearButtonRespondToMouseEvents() override;
     void clearValue() override;
 
-    // InputType functions
-    String badInputText() const override;
+    // InputTypeView functions
     void blur() final;
     void closePopupView() override;
     PassRefPtr<ComputedStyle> customStyleForLayoutObject(PassRefPtr<ComputedStyle>) override;
@@ -125,6 +124,7 @@
     void hidePickerIndicator();
     void updatePickerIndicatorVisibility();
 
+    Member<BaseDateAndTimeInputType> m_inputType;
     bool m_isDestroyingShadowSubtree;
     bool m_pickerIndicatorIsVisible;
     bool m_pickerIndicatorIsAlwaysVisible;
@@ -132,5 +132,4 @@
 
 } // namespace blink
 
-#endif
 #endif // BaseMultipleFieldsDateAndTimeInputType_h
diff --git a/third_party/WebKit/Source/core/html/forms/DateInputType.cpp b/third_party/WebKit/Source/core/html/forms/DateInputType.cpp
index 0a69f9b..15080ce 100644
--- a/third_party/WebKit/Source/core/html/forms/DateInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/DateInputType.cpp
@@ -49,7 +49,7 @@
 static const int dateStepScaleFactor = 86400000;
 
 inline DateInputType::DateInputType(HTMLInputElement& element)
-    : BaseDateInputType(element)
+    : BaseDateAndTimeInputType(element)
 {
 }
 
diff --git a/third_party/WebKit/Source/core/html/forms/DateInputType.h b/third_party/WebKit/Source/core/html/forms/DateInputType.h
index 86ba0e7..c6b3236 100644
--- a/third_party/WebKit/Source/core/html/forms/DateInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/DateInputType.h
@@ -32,17 +32,10 @@
 #define DateInputType_h
 
 #include "core/html/forms/BaseDateAndTimeInputType.h"
-#include "core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h"
 
 namespace blink {
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-using BaseDateInputType = BaseMultipleFieldsDateAndTimeInputType;
-#else
-using BaseDateInputType = BaseDateAndTimeInputType;
-#endif
-
-class DateInputType final : public BaseDateInputType {
+class DateInputType final : public BaseDateAndTimeInputType {
 public:
     static InputType* create(HTMLInputElement&);
 
diff --git a/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.h b/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.h
index 5a4dbf4..6b773b8 100644
--- a/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.h
@@ -32,24 +32,17 @@
 #define DateTimeLocalInputType_h
 
 #include "core/html/forms/BaseDateAndTimeInputType.h"
-#include "core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h"
 
 namespace blink {
 
 class ExceptionState;
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-using BaseDateTimeLocalInputType = BaseMultipleFieldsDateAndTimeInputType;
-#else
-using BaseDateTimeLocalInputType = BaseDateAndTimeInputType;
-#endif
-
-class DateTimeLocalInputType final : public BaseDateTimeLocalInputType {
+class DateTimeLocalInputType final : public BaseDateAndTimeInputType {
 public:
     static InputType* create(HTMLInputElement&);
 
 private:
-    explicit DateTimeLocalInputType(HTMLInputElement& element) : BaseDateTimeLocalInputType(element) { }
+    explicit DateTimeLocalInputType(HTMLInputElement& element) : BaseDateAndTimeInputType(element) {}
 
     void countUsage() override;
     const AtomicString& formControlType() const override;
diff --git a/third_party/WebKit/Source/core/html/forms/MonthInputType.h b/third_party/WebKit/Source/core/html/forms/MonthInputType.h
index 1016917e..f9d12156 100644
--- a/third_party/WebKit/Source/core/html/forms/MonthInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/MonthInputType.h
@@ -32,22 +32,15 @@
 #define MonthInputType_h
 
 #include "core/html/forms/BaseDateAndTimeInputType.h"
-#include "core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h"
 
 namespace blink {
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-using BaseMonthInputType = BaseMultipleFieldsDateAndTimeInputType;
-#else
-using BaseMonthInputType = BaseDateAndTimeInputType;
-#endif
-
-class MonthInputType final : public BaseMonthInputType {
+class MonthInputType final : public BaseDateAndTimeInputType {
 public:
     static InputType* create(HTMLInputElement&);
 
 private:
-    explicit MonthInputType(HTMLInputElement& element) : BaseMonthInputType(element) { }
+    explicit MonthInputType(HTMLInputElement& element) : BaseDateAndTimeInputType(element) {}
 
     void countUsage() override;
     const AtomicString& formControlType() const override;
diff --git a/third_party/WebKit/Source/core/html/forms/TimeInputType.cpp b/third_party/WebKit/Source/core/html/forms/TimeInputType.cpp
index a5f9583..36ac43dd 100644
--- a/third_party/WebKit/Source/core/html/forms/TimeInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/TimeInputType.cpp
@@ -53,7 +53,7 @@
 static const int timeStepScaleFactor = 1000;
 
 TimeInputType::TimeInputType(HTMLInputElement& element)
-    : BaseTimeInputType(element)
+    : BaseDateAndTimeInputType(element)
 {
 }
 
diff --git a/third_party/WebKit/Source/core/html/forms/TimeInputType.h b/third_party/WebKit/Source/core/html/forms/TimeInputType.h
index 3def9ae..8644f09 100644
--- a/third_party/WebKit/Source/core/html/forms/TimeInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/TimeInputType.h
@@ -32,17 +32,10 @@
 #define TimeInputType_h
 
 #include "core/html/forms/BaseDateAndTimeInputType.h"
-#include "core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h"
 
 namespace blink {
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-using BaseTimeInputType = BaseMultipleFieldsDateAndTimeInputType;
-#else
-using BaseTimeInputType = BaseDateAndTimeInputType;
-#endif
-
-class TimeInputType final : public BaseTimeInputType {
+class TimeInputType final : public BaseDateAndTimeInputType {
 public:
     static InputType* create(HTMLInputElement&);
 
diff --git a/third_party/WebKit/Source/core/html/forms/WeekInputType.h b/third_party/WebKit/Source/core/html/forms/WeekInputType.h
index 16163188..b5f9563a 100644
--- a/third_party/WebKit/Source/core/html/forms/WeekInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/WeekInputType.h
@@ -32,22 +32,15 @@
 #define WeekInputType_h
 
 #include "core/html/forms/BaseDateAndTimeInputType.h"
-#include "core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h"
 
 namespace blink {
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-using BaseWeekInputType = BaseMultipleFieldsDateAndTimeInputType;
-#else
-using BaseWeekInputType = BaseDateAndTimeInputType;
-#endif
-
-class WeekInputType final : public BaseWeekInputType {
+class WeekInputType final : public BaseDateAndTimeInputType {
 public:
     static InputType* create(HTMLInputElement&);
 
 private:
-    explicit WeekInputType(HTMLInputElement& element) : BaseWeekInputType(element) { }
+    explicit WeekInputType(HTMLInputElement& element) : BaseDateAndTimeInputType(element) {}
 
     void countUsage() override;
     const AtomicString& formControlType() const override;
diff --git a/third_party/WebKit/Source/core/html/shadow/PickerIndicatorElement.cpp b/third_party/WebKit/Source/core/html/shadow/PickerIndicatorElement.cpp
index 4dd7cf3..604fa168 100644
--- a/third_party/WebKit/Source/core/html/shadow/PickerIndicatorElement.cpp
+++ b/third_party/WebKit/Source/core/html/shadow/PickerIndicatorElement.cpp
@@ -30,7 +30,6 @@
 
 #include "core/html/shadow/PickerIndicatorElement.h"
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 #include "core/events/Event.h"
 #include "core/events/KeyboardEvent.h"
 #include "core/frame/Settings.h"
@@ -190,5 +189,3 @@
 }
 
 } // namespace blink
-
-#endif // ENABLE(INPUT_MULTIPLE_FIELDS_UI)
diff --git a/third_party/WebKit/Source/core/html/shadow/PickerIndicatorElement.h b/third_party/WebKit/Source/core/html/shadow/PickerIndicatorElement.h
index 8e150c87..344b36ce 100644
--- a/third_party/WebKit/Source/core/html/shadow/PickerIndicatorElement.h
+++ b/third_party/WebKit/Source/core/html/shadow/PickerIndicatorElement.h
@@ -31,9 +31,6 @@
 #ifndef PickerIndicatorElement_h
 #define PickerIndicatorElement_h
 
-#include "wtf/build_config.h"
-
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 #include "core/html/HTMLDivElement.h"
 #include "core/html/forms/DateTimeChooser.h"
 #include "core/html/forms/DateTimeChooserClient.h"
@@ -93,4 +90,3 @@
 
 } // namespace blink
 #endif
-#endif
diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.h b/third_party/WebKit/Source/core/layout/LayoutGrid.h
index efdf629..fe0cfc0 100644
--- a/third_party/WebKit/Source/core/layout/LayoutGrid.h
+++ b/third_party/WebKit/Source/core/layout/LayoutGrid.h
@@ -74,6 +74,11 @@
 
     LayoutUnit guttersSize(GridTrackSizingDirection, size_t span) const;
 
+    LayoutUnit offsetBetweenTracks(GridTrackSizingDirection direction) const
+    {
+        return direction == ForColumns ? m_offsetBetweenColumns : m_offsetBetweenRows;
+    }
+
     typedef Vector<LayoutBox*, 1> GridCell;
     const GridCell& gridCell(int row, int column) const
     {
diff --git a/third_party/WebKit/Source/core/layout/LayoutTheme.cpp b/third_party/WebKit/Source/core/layout/LayoutTheme.cpp
index e5320a0..6f3258c 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTheme.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTheme.cpp
@@ -847,16 +847,15 @@
     return false;
 }
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 bool LayoutTheme::supportsCalendarPicker(const AtomicString& type) const
 {
+    DCHECK(RuntimeEnabledFeatures::inputMultipleFieldsUIEnabled());
     return type == InputTypeNames::date
         || type == InputTypeNames::datetime
         || type == InputTypeNames::datetime_local
         || type == InputTypeNames::month
         || type == InputTypeNames::week;
 }
-#endif
 
 bool LayoutTheme::shouldUseFallbackTheme(const ComputedStyle&) const
 {
diff --git a/third_party/WebKit/Source/core/layout/LayoutTheme.h b/third_party/WebKit/Source/core/layout/LayoutTheme.h
index e09d38f..2d396723 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTheme.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTheme.h
@@ -96,10 +96,9 @@
     // A method asking if the theme's controls actually care about redrawing when hovered.
     virtual bool supportsHover(const ComputedStyle&) const { return false; }
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-    // A method asking if the platform is able to show a calendar picker for a given input type.
+    // A method asking if the platform is able to show a calendar picker for a
+    // given input type.
     virtual bool supportsCalendarPicker(const AtomicString&) const;
-#endif
 
     // Text selection colors.
     Color activeSelectionBackgroundColor() const;
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGContainer.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGContainer.cpp
index 85d5adb..b53b91a 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGContainer.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGContainer.cpp
@@ -36,6 +36,7 @@
     : LayoutSVGModelObject(node)
     , m_objectBoundingBoxValid(false)
     , m_needsBoundariesUpdate(true)
+    , m_didTransformToRootUpdate(false)
     , m_hasNonIsolatedBlendingDescendants(false)
     , m_hasNonIsolatedBlendingDescendantsDirty(false)
 {
@@ -55,12 +56,11 @@
 
     // Allow LayoutSVGTransformableContainer to update its transform.
     bool updatedTransform = calculateLocalTransform();
+    m_didTransformToRootUpdate = updatedTransform || SVGLayoutSupport::transformToRootChanged(parent());
 
     // LayoutSVGViewportContainer needs to set the 'layout size changed' flag.
     determineIfLayoutSizeChanged();
 
-    bool transformChanged = SVGLayoutSupport::transformToRootChanged(this);
-
     // When hasRelativeLengths() is false, no descendants have relative lengths
     // (hence no one is interested in viewport size changes).
     bool layoutSizeChanged = element()->hasRelativeLengths()
@@ -71,7 +71,7 @@
     // the descendants.
     bool forceLayoutOfChildren = selfNeedsLayout()
         || (normalChildNeedsLayout() && SVGLayoutSupport::hasFilterResource(*this));
-    SVGLayoutSupport::layoutChildren(firstChild(), forceLayoutOfChildren, transformChanged, layoutSizeChanged);
+    SVGLayoutSupport::layoutChildren(firstChild(), forceLayoutOfChildren, m_didTransformToRootUpdate, layoutSizeChanged);
 
     // Invalidate all resources of this client if our layout changed.
     if (everHadLayout() && needsLayout())
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGContainer.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGContainer.h
index 49caa18..e5c9709 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGContainer.h
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGContainer.h
@@ -44,7 +44,7 @@
     void paint(const PaintInfo&, const LayoutPoint&) const override;
     void styleDidChange(StyleDifference, const ComputedStyle* oldStyle) override;
     void setNeedsBoundariesUpdate() final { m_needsBoundariesUpdate = true; }
-    virtual bool didTransformToRootUpdate() const { return false; }
+    bool didTransformToRootUpdate() const { return m_didTransformToRootUpdate; }
     bool isObjectBoundingBoxValid() const { return m_objectBoundingBoxValid; }
 
     bool selfWillPaint() const;
@@ -91,7 +91,8 @@
     FloatRect m_objectBoundingBox;
     FloatRect m_strokeBoundingBox;
     bool m_objectBoundingBoxValid;
-    bool m_needsBoundariesUpdate;
+    bool m_needsBoundariesUpdate : 1;
+    bool m_didTransformToRootUpdate : 1;
     mutable bool m_hasNonIsolatedBlendingDescendants : 1;
     mutable bool m_hasNonIsolatedBlendingDescendantsDirty : 1;
 };
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGTransformableContainer.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGTransformableContainer.cpp
index a29b47c..e27c088 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGTransformableContainer.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGTransformableContainer.cpp
@@ -31,7 +31,6 @@
 LayoutSVGTransformableContainer::LayoutSVGTransformableContainer(SVGGraphicsElement* node)
     : LayoutSVGContainer(node)
     , m_needsTransformUpdate(true)
-    , m_didTransformToRootUpdate(false)
 {
 }
 
@@ -94,7 +93,6 @@
         m_additionalTranslation = translation;
     }
 
-    m_didTransformToRootUpdate = m_needsTransformUpdate || SVGLayoutSupport::transformToRootChanged(parent());
     if (!m_needsTransformUpdate)
         return false;
 
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGTransformableContainer.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGTransformableContainer.h
index 6abe13a..2e3868e 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGTransformableContainer.h
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGTransformableContainer.h
@@ -38,14 +38,12 @@
     const FloatSize& additionalTranslation() const { return m_additionalTranslation; }
 
     void setNeedsTransformUpdate() override { m_needsTransformUpdate = true; }
-    bool didTransformToRootUpdate() const override { return m_didTransformToRootUpdate; }
 
 private:
     bool calculateLocalTransform() override;
     AffineTransform localSVGTransform() const override { return m_localTransform; }
 
     bool m_needsTransformUpdate : 1;
-    bool m_didTransformToRootUpdate : 1;
     AffineTransform m_localTransform;
     FloatSize m_additionalTranslation;
 };
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGViewportContainer.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGViewportContainer.cpp
index 25b9a88..d0d6937 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGViewportContainer.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGViewportContainer.cpp
@@ -32,7 +32,6 @@
 
 LayoutSVGViewportContainer::LayoutSVGViewportContainer(SVGElement* node)
     : LayoutSVGContainer(node)
-    , m_didTransformToRootUpdate(false)
     , m_isLayoutSizeChanged(false)
     , m_needsTransformUpdate(true)
 {
@@ -67,7 +66,6 @@
 
 bool LayoutSVGViewportContainer::calculateLocalTransform()
 {
-    m_didTransformToRootUpdate = m_needsTransformUpdate || SVGLayoutSupport::transformToRootChanged(parent());
     if (!m_needsTransformUpdate)
         return false;
 
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGViewportContainer.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGViewportContainer.h
index f223704..545e396 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGViewportContainer.h
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGViewportContainer.h
@@ -35,7 +35,6 @@
     FloatRect viewport() const { return m_viewport; }
 
     bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; }
-    bool didTransformToRootUpdate() const override { return m_didTransformToRootUpdate; }
 
     void determineIfLayoutSizeChanged() override;
     void setNeedsTransformUpdate() override { m_needsTransformUpdate = true; }
@@ -57,7 +56,6 @@
 
     FloatRect m_viewport;
     mutable AffineTransform m_localToParentTransform;
-    bool m_didTransformToRootUpdate : 1;
     bool m_isLayoutSizeChanged : 1;
     bool m_needsTransformUpdate : 1;
 };
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
index e6c9e2c3..ae3ef656 100644
--- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
+++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
@@ -791,7 +791,13 @@
         for (const auto& eventTarget : *targets) {
             EventTarget* target = eventTarget.key;
             Node* node = target->toNode();
-            if (target->toLocalDOMWindow() || node == document || node == document->documentElement() || node == document->body()) {
+            LocalDOMWindow* window = target->toLocalDOMWindow();
+            // If the target is inside a throttled frame, skip it.
+            if (window && window->frame()->view() && window->frame()->view()->shouldThrottleRendering())
+                continue;
+            if (node && node->document().view() && node->document().view()->shouldThrottleRendering())
+                continue;
+            if (window || node == document || node == document->documentElement() || node == document->body()) {
                 if (LayoutViewItem layoutView = document->layoutViewItem()) {
                     layoutView.computeLayerHitTestRects(rects);
                 }
@@ -811,6 +817,10 @@
         if (node->document().isInInvisibleSubframe())
             continue;
 
+        // If the node belongs to a throttled frame, skip it.
+        if (node->document().view() && node->document().view()->shouldThrottleRendering())
+            continue;
+
         if (node->isDocumentNode() && node != document) {
             accumulateDocumentTouchEventTargetRects(rects, toDocument(node));
         } else if (LayoutObject* layoutObject = node->layoutObject()) {
diff --git a/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.cpp b/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.cpp
index fbc8b05..1ff1f53 100644
--- a/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.cpp
@@ -42,6 +42,7 @@
 #include "bindings/modules/v8/UnionTypesModules.h"
 #include "bindings/modules/v8/V8RTCCertificate.h"
 #include "core/dom/DOMException.h"
+#include "core/dom/DOMTimeStamp.h"
 #include "core/dom/Document.h"
 #include "core/dom/ExceptionCode.h"
 #include "core/dom/ExecutionContext.h"
@@ -88,6 +89,7 @@
 #include "public/platform/WebRTCSessionDescriptionRequest.h"
 #include "public/platform/WebRTCStatsRequest.h"
 #include "public/platform/WebRTCVoidRequest.h"
+#include "wtf/CurrentTime.h"
 
 #include <memory>
 
@@ -321,7 +323,6 @@
             rtcConfiguration->appendCertificate(certificate->certificateShallowCopy());
         }
     }
-
     return rtcConfiguration;
 }
 
@@ -388,6 +389,18 @@
     if (exceptionState.hadException())
         return 0;
 
+    // Make sure no certificates have expired.
+    if (configuration && configuration->numberOfCertificates() > 0) {
+        DOMTimeStamp now = convertSecondsToDOMTimeStamp(currentTime());
+        for (size_t i = 0; i < configuration->numberOfCertificates(); ++i) {
+            DOMTimeStamp expires = configuration->certificate(i)->expires();
+            if (expires <= now) {
+                exceptionState.throwDOMException(InvalidStateError, "Expired certificate(s).");
+                return 0;
+            }
+        }
+    }
+
     MediaErrorState mediaErrorState;
     WebMediaConstraints constraints = MediaConstraintsImpl::create(context, mediaConstraints, mediaErrorState);
     if (mediaErrorState.hadException()) {
diff --git a/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.h b/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.h
index bd4ac8ae..b04bbf0a 100644
--- a/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.h
+++ b/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.h
@@ -70,7 +70,6 @@
     USING_GARBAGE_COLLECTED_MIXIN(RTCPeerConnection);
     USING_PRE_FINALIZER(RTCPeerConnection, dispose);
 public:
-    // TODO(hbos): Create with expired RTCCertificate should fail, see crbug.com/565278.
     static RTCPeerConnection* create(ExecutionContext*, const Dictionary&, const Dictionary&, ExceptionState&);
     ~RTCPeerConnection() override;
 
diff --git a/third_party/WebKit/Source/modules/notifications/OWNERS b/third_party/WebKit/Source/modules/notifications/OWNERS
index 2fca67fd..6ce739c6 100644
--- a/third_party/WebKit/Source/modules/notifications/OWNERS
+++ b/third_party/WebKit/Source/modules/notifications/OWNERS
@@ -1 +1,2 @@
+mvanouwerkerk@chromium.org
 peter@chromium.org
\ No newline at end of file
diff --git a/third_party/WebKit/Source/platform/heap/HeapPage.h b/third_party/WebKit/Source/platform/heap/HeapPage.h
index 91dc1703..1bcfc82 100644
--- a/third_party/WebKit/Source/platform/heap/HeapPage.h
+++ b/third_party/WebKit/Source/platform/heap/HeapPage.h
@@ -142,7 +142,7 @@
 // - 1 bit used to mark DOM trees for V8.
 // - 14 bit is enough for gcInfoIndex because there are less than 2^14 types
 //   in Blink.
-const size_t headerDOMMarkBitMask = 1u << 17;
+const size_t headerWrapperMarkBitMask = 1u << 17;
 const size_t headerGCInfoIndexShift = 18;
 const size_t headerGCInfoIndexMask = (static_cast<size_t>((1 << 14) - 1)) << headerGCInfoIndexShift;
 const size_t headerSizeMask = (static_cast<size_t>((1 << 14) - 1)) << 3;
@@ -205,6 +205,9 @@
         ASSERT(size < nonLargeObjectPageSizeMax);
         m_encoded = static_cast<uint32_t>(size) | (m_encoded & ~headerSizeMask);
     }
+    bool isWrapperHeaderMarked() const;
+    void markWrapperHeader();
+    void unmarkWrapperHeader();
     bool isMarked() const;
     void mark();
     void unmark();
@@ -835,6 +838,29 @@
 }
 
 NO_SANITIZE_ADDRESS inline
+bool HeapObjectHeader::isWrapperHeaderMarked() const
+{
+    ASSERT(checkHeader());
+    return m_encoded & headerWrapperMarkBitMask;
+}
+
+NO_SANITIZE_ADDRESS inline
+void HeapObjectHeader::markWrapperHeader()
+{
+    ASSERT(checkHeader());
+    ASSERT(!isWrapperHeaderMarked());
+    m_encoded |= headerWrapperMarkBitMask;
+}
+
+NO_SANITIZE_ADDRESS inline
+void HeapObjectHeader::unmarkWrapperHeader()
+{
+    ASSERT(checkHeader());
+    ASSERT(isWrapperHeaderMarked());
+    m_encoded &= ~headerWrapperMarkBitMask;
+}
+
+NO_SANITIZE_ADDRESS inline
 bool HeapObjectHeader::isMarked() const
 {
     ASSERT(checkHeader());
diff --git a/third_party/WebKit/Source/web/tests/FrameThrottlingTest.cpp b/third_party/WebKit/Source/web/tests/FrameThrottlingTest.cpp
index 3353b15..60faa0b8 100644
--- a/third_party/WebKit/Source/web/tests/FrameThrottlingTest.cpp
+++ b/third_party/WebKit/Source/web/tests/FrameThrottlingTest.cpp
@@ -8,8 +8,10 @@
 #include "core/html/HTMLIFrameElement.h"
 #include "core/page/FocusController.h"
 #include "core/page/Page.h"
+#include "core/paint/PaintLayer.h"
 #include "platform/testing/URLTestHelpers.h"
 #include "platform/testing/UnitTestHelpers.h"
+#include "public/platform/WebLayer.h"
 #include "public/web/WebHitTestResult.h"
 #include "public/web/WebSettings.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -40,6 +42,12 @@
         testing::runPendingTasks();
         return displayItems;
     }
+
+    // Number of rectangles that make up the root layer's touch handler region.
+    size_t touchHandlerRegionSize()
+    {
+        return webView().mainFrameImpl()->frame()->contentLayoutItem().layer()->graphicsLayerBacking()->platformLayer()->touchEventHandlerRegion().size();
+    }
 };
 
 TEST_F(FrameThrottlingTest, ThrottleInvisibleFrames)
@@ -546,4 +554,71 @@
     EXPECT_FALSE(frameElement->contentDocument()->view()->canThrottleRendering());
 }
 
+TEST_F(FrameThrottlingTest, ThrottledTopLevelEventHandlerIgnored)
+{
+    webView().settings()->setAcceleratedCompositingEnabled(true);
+    webView().settings()->setJavaScriptEnabled(true);
+    EXPECT_EQ(0u, touchHandlerRegionSize());
+
+    // Create a frame which is throttled and has two different types of
+    // top-level touchstart handlers.
+    SimRequest mainResource("https://example.com/", "text/html");
+    SimRequest frameResource("https://example.com/iframe.html", "text/html");
+
+    loadURL("https://example.com/");
+    mainResource.complete("<iframe id=frame sandbox=allow-scripts src=iframe.html></iframe>");
+    frameResource.complete(
+        "<script>"
+        "window.addEventListener('touchstart', function(){});"
+        "document.addEventListener('touchstart', function(){});"
+        "</script>");
+    auto* frameElement = toHTMLIFrameElement(document().getElementById("frame"));
+    frameElement->setAttribute(styleAttr, "transform: translateY(480px)");
+    compositeFrame(); // Throttle the frame.
+    compositeFrame(); // Update touch handler regions.
+
+    // The touch handlers in the throttled frame should have been ignored.
+    EXPECT_EQ(0u, touchHandlerRegionSize());
+
+    // Unthrottling the frame makes the touch handlers active again. Note that
+    // both handlers get combined into the same rectangle in the region, so
+    // there is only one rectangle in total.
+    frameElement->setAttribute(styleAttr, "transform: translateY(0px)");
+    compositeFrame(); // Unthrottle the frame.
+    compositeFrame(); // Update touch handler regions.
+    EXPECT_EQ(1u, touchHandlerRegionSize());
+}
+
+TEST_F(FrameThrottlingTest, ThrottledEventHandlerIgnored)
+{
+    webView().settings()->setAcceleratedCompositingEnabled(true);
+    webView().settings()->setJavaScriptEnabled(true);
+    EXPECT_EQ(0u, touchHandlerRegionSize());
+
+    // Create a frame which is throttled and has a non-top-level touchstart handler.
+    SimRequest mainResource("https://example.com/", "text/html");
+    SimRequest frameResource("https://example.com/iframe.html", "text/html");
+
+    loadURL("https://example.com/");
+    mainResource.complete("<iframe id=frame sandbox=allow-scripts src=iframe.html></iframe>");
+    frameResource.complete(
+        "<div id=d>touch handler</div>"
+        "<script>"
+        "document.querySelector('#d').addEventListener('touchstart', function(){});"
+        "</script>");
+    auto* frameElement = toHTMLIFrameElement(document().getElementById("frame"));
+    frameElement->setAttribute(styleAttr, "transform: translateY(480px)");
+    compositeFrame(); // Throttle the frame.
+    compositeFrame(); // Update touch handler regions.
+
+    // The touch handler in the throttled frame should have been ignored.
+    EXPECT_EQ(0u, touchHandlerRegionSize());
+
+    // Unthrottling the frame makes the touch handler active again.
+    frameElement->setAttribute(styleAttr, "transform: translateY(0px)");
+    compositeFrame(); // Unthrottle the frame.
+    compositeFrame(); // Update touch handler regions.
+    EXPECT_EQ(1u, touchHandlerRegionSize());
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/web/tests/WebViewTest.cpp b/third_party/WebKit/Source/web/tests/WebViewTest.cpp
index 805e58a2c..af01507 100644
--- a/third_party/WebKit/Source/web/tests/WebViewTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebViewTest.cpp
@@ -2067,7 +2067,13 @@
     webView->handleInputEvent(keyEvent);
 }
 
-TEST_F(WebViewTest, ChooseValueFromDateTimeChooser)
+// TODO(crbug.com/605112) This test is crashing on Android (Nexus 4) bot.
+#if OS(ANDROID)
+#define MAYBE_ChooseValueFromDateTimeChooser DISABLED_ChooseValueFromDateTimeChooser
+#else
+#define MAYBE_ChooseValueFromDateTimeChooser ChooseValueFromDateTimeChooser
+#endif
+TEST_F(WebViewTest, MAYBE_ChooseValueFromDateTimeChooser)
 {
     DateTimeChooserWebViewClient client;
     std::string url = m_baseURL + "date_time_chooser.html";
diff --git a/third_party/WebKit/Source/wtf/allocator/PageAllocator.cpp b/third_party/WebKit/Source/wtf/allocator/PageAllocator.cpp
index 8546387..12c9a7b 100644
--- a/third_party/WebKit/Source/wtf/allocator/PageAllocator.cpp
+++ b/third_party/WebKit/Source/wtf/allocator/PageAllocator.cpp
@@ -31,6 +31,7 @@
 #include "wtf/allocator/PageAllocator.h"
 
 #include "wtf/Assertions.h"
+#include "wtf/Atomics.h"
 #include "wtf/allocator/AddressSpaceRandomization.h"
 
 #include <limits.h>
@@ -50,7 +51,7 @@
 
 // On POSIX memmap uses a nearby address if the hint address is blocked.
 static const bool kHintIsAdvisory = true;
-static uint32_t allocPageErrorCode = 0;
+static uint32_t s_allocPageErrorCode = 0;
 
 #elif OS(WIN)
 
@@ -58,7 +59,7 @@
 
 // VirtualAlloc will fail if allocation at the hint address is blocked.
 static const bool kHintIsAdvisory = false;
-static uint32_t allocPageErrorCode = ERROR_SUCCESS;
+static uint32_t s_allocPageErrorCode = ERROR_SUCCESS;
 
 #else
 #error Unknown OS
@@ -80,12 +81,12 @@
     DWORD accessFlag = pageAccessibility == PageAccessible ? PAGE_READWRITE : PAGE_NOACCESS;
     ret = VirtualAlloc(hint, len, MEM_RESERVE | MEM_COMMIT, accessFlag);
     if (!ret)
-        allocPageErrorCode = GetLastError();
+        releaseStore(&s_allocPageErrorCode, GetLastError());
 #else
     int accessFlag = pageAccessibility == PageAccessible ? (PROT_READ | PROT_WRITE) : PROT_NONE;
     ret = mmap(hint, len, accessFlag, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
     if (ret == MAP_FAILED) {
-        allocPageErrorCode = errno;
+        releaseStore(&s_allocPageErrorCode, errno);
         ret = 0;
     }
 #endif
@@ -270,7 +271,7 @@
 
 uint32_t getAllocPageErrorCode()
 {
-    return allocPageErrorCode;
+    return acquireLoad(&s_allocPageErrorCode);
 }
 
 } // namespace WTF
diff --git a/third_party/libjingle/README.chromium b/third_party/libjingle/README.chromium
index 7b993a1..558808a 100644
--- a/third_party/libjingle/README.chromium
+++ b/third_party/libjingle/README.chromium
@@ -1,7 +1,7 @@
 Name: libjingle
 URL: http://www.webrtc.org
 Version: unknown
-Revision: 12291
+Revision: 12410
 License: BSD
 License File: source/talk/COPYING
 Security Critical: yes
diff --git a/third_party/woff2/README.chromium b/third_party/woff2/README.chromium
index 70deff2e..e45a118 100644
--- a/third_party/woff2/README.chromium
+++ b/third_party/woff2/README.chromium
@@ -14,3 +14,6 @@
 - BUILD.gn: Added.
 - woff2.gyp: Added.
 - src/port.h: Include <assert.h>.
+- src/woff2_dec.cc: Msan error fix.
+
+Changes under src/ will be fixed in the upstream repository soon.
diff --git a/third_party/woff2/src/woff2_dec.cc b/third_party/woff2/src/woff2_dec.cc
index 837eede1..ea1f1693 100644
--- a/third_party/woff2/src/woff2_dec.cc
+++ b/third_party/woff2/src/woff2_dec.cc
@@ -603,13 +603,12 @@
     *glyf_checksum += ComputeULongSum(glyph_buf.get(), glyph_size);
 
     // We may need x_min to reconstruct 'hmtx'
-    Buffer x_min_buf(glyph_buf.get() + 2, 2);
-    int16_t x_min;
-    if (PREDICT_FALSE(!x_min_buf.ReadS16(&x_min))) {
-      return FONT_COMPRESSION_FAILURE();
+    if (n_contours > 0) {
+      Buffer x_min_buf(glyph_buf.get() + 2, 2);
+      if (PREDICT_FALSE(!x_min_buf.ReadS16(&info->x_mins[i]))) {
+        return FONT_COMPRESSION_FAILURE();
+      }
     }
-
-    info->x_mins[i] = n_contours != 0 ? x_min : 0;
   }
 
   // glyf_table dst_offset was set by ReconstructFont
diff --git a/tools/android/loading/chrome_cache.py b/tools/android/loading/chrome_cache.py
index 9d486e9c..4c1f226 100644
--- a/tools/android/loading/chrome_cache.py
+++ b/tools/android/loading/chrome_cache.py
@@ -219,7 +219,11 @@
           f.write(zip_input.read(file_archive_name))
 
     assert timestamps
-    for relative_path, stats in timestamps.iteritems():
+    # os.utime(file_path, ...) modifies modification time of file_path's parent
+    # directories. Therefore we call os.utime on files and directories that have
+    # longer relative paths first.
+    for relative_path in sorted(timestamps.keys(), key=len, reverse=True):
+      stats = timestamps[relative_path]
       output_path = os.path.join(directory_dest_path, relative_path)
       if not os.path.exists(output_path):
         os.makedirs(output_path)
diff --git a/tools/android/loading/cloud/backend/README.md b/tools/android/loading/cloud/backend/README.md
index 5f534f22..b181cfa9 100644
--- a/tools/android/loading/cloud/backend/README.md
+++ b/tools/android/loading/cloud/backend/README.md
@@ -95,15 +95,21 @@
     https://www.googleapis.com/auth/cloud-platform
 ```
 
-Create a JSON file describing the deployment configuration:
+Create a JSON dictionary file describing the deployment configuration, with the
+keys:
 
+-   `project_name` (string): Name of the Google Cloud project
+-   `cloud_storage_path` (string): Path in Google Storage where generated traces
+    will be stored.
+-   `chrome_path` (string): Path to the Chrome executable.
+-   `src_path` (string): Path to the Chromium source directory.
+-   `taskqueue_tag` (string):
+-   `trace_database_filename` (string, optional): Filename for the trace
+    database in Cloud Storage. Must be unique per worker to avoid concurrent
+    access. Defaults to `trace_database.json`.
+
+Example:
 ```shell
-# CONFIG_FILE is the output json file.
-# PROJECT_NAME is the Google Cloud project.
-# CLOUD_STORAGE_PATH is the path in Google Storage where generated traces will
-# be stored.
-# CHROME_PATH is the path to the Chrome executable on the host.
-# CHROMIUM_SRC is the Chromium src directory.
 cat >$CONFIG_FILE << EOF
 {
   "project_name" : "$PROJECT_NAME",
diff --git a/tools/android/loading/cloud/backend/google_storage_accessor.py b/tools/android/loading/cloud/backend/google_storage_accessor.py
index 86e238e8..ded3fe8 100644
--- a/tools/android/loading/cloud/backend/google_storage_accessor.py
+++ b/tools/android/loading/cloud/backend/google_storage_accessor.py
@@ -2,7 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-from gcloud import storage
+import gcloud.exceptions
+import gcloud.storage
 
 
 class GoogleStorageAccessor(object):
@@ -18,12 +19,26 @@
 
   def _GetStorageClient(self):
     """Returns the storage client associated with the project"""
-    return storage.Client(project = self._project_name,
-                          credentials = self._credentials)
+    return gcloud.storage.Client(project = self._project_name,
+                                 credentials = self._credentials)
 
   def _GetStorageBucket(self, storage_client):
     return storage_client.get_bucket(self._bucket_name)
 
+  def DownloadAsString(self, remote_filename):
+    """Returns the content of a remote file as a string, or None if the file
+    does not exist.
+    """
+    client = self._GetStorageClient()
+    bucket = self._GetStorageBucket(client)
+    blob = bucket.get_blob(remote_filename)
+    if not blob:
+      return None
+    try:
+      return blob.download_as_string()
+    except gcloud.exceptions.NotFound:
+      return None
+
   def UploadFile(self, filename_src, filename_dest):
     """Uploads a file to Google Cloud Storage
 
diff --git a/tools/android/loading/cloud/backend/startup-script.sh b/tools/android/loading/cloud/backend/startup-script.sh
index e429c1e..3d3084f0 100644
--- a/tools/android/loading/cloud/backend/startup-script.sh
+++ b/tools/android/loading/cloud/backend/startup-script.sh
@@ -12,11 +12,15 @@
       -H "Metadata-Flavor: Google"
 }
 
-# Talk to the metadata server to get the project id
+# Talk to the metadata server to get the project id and the instance id
 PROJECTID=$(curl -s \
     "http://metadata.google.internal/computeMetadata/v1/project/project-id" \
     -H "Metadata-Flavor: Google")
 
+INSTANCE_ID=$(curl -s \
+    "http://metadata.google.internal/computeMetadata/v1/instance/hostname" \
+    -H "Metadata-Flavor: Google")
+
 # Install dependencies from apt
 apt-get update
 # Basic dependencies
@@ -73,7 +77,8 @@
   "cloud_storage_path" : "$CLOUD_STORAGE_PATH",
   "chrome_path" : "/opt/app/clovis/binaries/chrome",
   "src_path" : "/opt/app/clovis/src",
-  "taskqueue_tag" : "$TASKQUEUE_TAG"
+  "taskqueue_tag" : "$TASKQUEUE_TAG",
+  "trace_database_filename" : "trace_database_${INSTANCE_ID}.json"
 }
 EOF
 
diff --git a/tools/android/loading/cloud/backend/worker.py b/tools/android/loading/cloud/backend/worker.py
index b9900cec..9518171 100644
--- a/tools/android/loading/cloud/backend/worker.py
+++ b/tools/android/loading/cloud/backend/worker.py
@@ -32,6 +32,7 @@
     """See README.md for the config format."""
     self._project_name = config['project_name']
     self._taskqueue_tag = config['taskqueue_tag']
+    self._src_path = config['src_path']
     self._credentials = GoogleCredentials.get_application_default()
     self._logger = logger
 
@@ -45,15 +46,18 @@
       if not self._base_path_in_bucket.endswith('/'):
         self._base_path_in_bucket += '/'
 
-    # TODO: improve the trace database to support concurrent access.
-    self._traces_dir = self._base_path_in_bucket + 'traces/'
-    self._trace_database = LoadingTraceDatabase({})
-
-    self._src_path = config['src_path']
     self._google_storage_accessor = GoogleStorageAccessor(
         credentials=self._credentials, project_name=self._project_name,
         bucket_name=self._bucket_name)
 
+    self._traces_dir = os.path.join(self._base_path_in_bucket, 'traces')
+    self._trace_database_path = os.path.join(
+        self._traces_dir,
+        config.get('trace_database_filename', 'trace_database.json'))
+
+    # Recover any existing trace database in case the worker died.
+    self._DownloadTraceDatabase()
+
     # Initialize the global options that will be used during trace generation.
     options.OPTIONS.ParseArgs([])
     options.OPTIONS.local_binary = config['chrome_path']
@@ -94,6 +98,21 @@
       self._logger.info('Finished task %s' % task_id)
     self._Finalize()
 
+  def _DownloadTraceDatabase(self):
+    """Downloads the trace database from CloudStorage."""
+    self._logger.info('Downloading trace database')
+    trace_database_string = self._google_storage_accessor.DownloadAsString(
+        self._trace_database_path) or '{}'
+    trace_database_dict = json.loads(trace_database_string)
+    self._trace_database = LoadingTraceDatabase(trace_database_dict)
+
+  def _UploadTraceDatabase(self):
+    """Uploads the trace database to CloudStorage."""
+    self._logger.info('Uploading trace database')
+    self._google_storage_accessor.UploadString(
+        json.dumps(self._trace_database.ToJsonDict(), indent=2),
+        self._trace_database_path)
+
   def _FetchClovisTask(self, project_name, task_api, queue_name):
     """Fetches a ClovisTask from the task queue.
 
@@ -119,14 +138,9 @@
 
   def _Finalize(self):
     """Called before exiting."""
-    self._logger.info('Uploading trace database')
-    self._google_storage_accessor.UploadString(
-        json.dumps(self._trace_database.ToJsonDict(), indent=2),
-        self._traces_dir + 'trace_database.json')
     # TODO(droger): Implement automatic instance destruction.
     self._logger.info('Done')
 
-
   def _GenerateTrace(self, url, emulate_device, emulate_network, filename,
                      log_filename):
     """ Generates a trace.
@@ -201,9 +215,9 @@
     emulate_device = params.get('emulate_device')
     emulate_network = params.get('emulate_network')
 
-    failures_dir = self._base_path_in_bucket + 'failures/'
+    failures_dir = os.path.join(self._base_path_in_bucket, 'failures')
     # TODO(blundell): Fix this up.
-    logs_dir = self._base_path_in_bucket + 'analyze_logs/'
+    logs_dir = os.path.join(self._base_path_in_bucket, 'analyze_logs')
     log_filename = 'analyze.log'
     # Avoid special characters in storage object names
     pattern = re.compile(r"[#\?\[\]\*/]")
@@ -213,27 +227,27 @@
       local_filename = pattern.sub('_', url)
       for repeat in range(repeat_count):
         self._logger.debug('Generating trace for URL: %s' % url)
-        remote_filename = local_filename + '/' + str(repeat)
+        remote_filename = os.path.join(local_filename, str(repeat))
         trace_metadata = self._GenerateTrace(
             url, emulate_device, emulate_network, local_filename, log_filename)
         if trace_metadata['succeeded']:
           self._logger.debug('Uploading: %s' % remote_filename)
-          remote_trace_location = self._traces_dir + remote_filename
+          remote_trace_location = os.path.join(self._traces_dir,
+                                               remote_filename)
           self._google_storage_accessor.UploadFile(local_filename,
                                                    remote_trace_location)
-          full_cloud_storage_path = ('gs://' + self._bucket_name + '/' +
-              remote_trace_location)
-          self._trace_database.AddTrace(full_cloud_storage_path, trace_metadata)
+          full_cloud_storage_path = os.path.join('gs://' + self._bucket_name,
+                                                 remote_trace_location)
+          self._trace_database.SetTrace(full_cloud_storage_path, trace_metadata)
         else:
           self._logger.warning('Trace generation failed for URL: %s' % url)
-          # TODO: upload the failure
           if os.path.isfile(local_filename):
-            self._google_storage_accessor.UploadFile(local_filename,
-                                            failures_dir + remote_filename)
-            self._logger.debug('Uploading log')
-        self._google_storage_accessor.UploadFile(log_filename,
-                                                 logs_dir + remote_filename)
-
+            self._google_storage_accessor.UploadFile(
+                local_filename, os.path.join(failures_dir, remote_filename))
+        self._logger.debug('Uploading analyze log')
+        self._google_storage_accessor.UploadFile(
+            log_filename, os.path.join(logs_dir, remote_filename))
+    self._UploadTraceDatabase()
 
 if __name__ == '__main__':
   parser = argparse.ArgumentParser(
diff --git a/tools/android/loading/loading_trace_database.py b/tools/android/loading/loading_trace_database.py
index 2ef33b0..dad6153 100644
--- a/tools/android/loading/loading_trace_database.py
+++ b/tools/android/loading/loading_trace_database.py
@@ -14,9 +14,10 @@
        about those traces."""
     self._traces_dict = traces_dict
 
-  def AddTrace(self, filename, trace_dict):
-    """Adds a mapping from |filename| to |trace_dict| into the database."""
-    assert filename not in self._traces_dict
+  def SetTrace(self, filename, trace_dict):
+    """Sets a mapping from |filename| to |trace_dict| into the database.
+    If there is an existing mapping for filename, it is replaced.
+    """
     self._traces_dict[filename] = trace_dict
 
   def GetTraceFilesForURL(self, url):
diff --git a/tools/android/loading/loading_trace_database_unittest.py b/tools/android/loading/loading_trace_database_unittest.py
index 31dc9b3..e64fb8c 100644
--- a/tools/android/loading/loading_trace_database_unittest.py
+++ b/tools/android/loading/loading_trace_database_unittest.py
@@ -32,11 +32,11 @@
     self.assertEqual(
         self._JSON_DATABASE, self.database.ToJsonDict())
 
-  def testAddTrace(self):
+  def testSetTrace(self):
     dummy_url = "http://dummy.com"
     new_trace_file = "traces/new_trace.json"
     self.assertEqual(self.database.GetTraceFilesForURL(dummy_url), [])
-    self.database.AddTrace(new_trace_file, {"url" : dummy_url})
+    self.database.SetTrace(new_trace_file, {"url" : dummy_url})
     self.assertEqual(self.database.GetTraceFilesForURL(dummy_url),
                      [new_trace_file])
 
diff --git a/tools/android/loading/request_track.py b/tools/android/loading/request_track.py
index bf19fbbf..9f513d2e 100644
--- a/tools/android/loading/request_track.py
+++ b/tools/android/loading/request_track.py
@@ -25,7 +25,8 @@
     'requestTime': 'request_time', 'sendEnd': 'send_end',
     'sendStart': 'send_start', 'sslEnd': 'ssl_end', 'sslStart': 'ssl_start',
     'workerReady': 'worker_ready', 'workerStart': 'worker_start',
-    'loadingFinished': 'loading_finished'}
+    'loadingFinished': 'loading_finished', 'pushStart' : 'push_start',
+    'pushEnd' : 'push_end'}
 
 Timing = collections.namedtuple('Timing', _TIMING_NAMES_MAPPING.values())
 
diff --git a/tools/copyright_scanner/third_party_files_whitelist.txt b/tools/copyright_scanner/third_party_files_whitelist.txt
index 43fc331..91def808 100644
--- a/tools/copyright_scanner/third_party_files_whitelist.txt
+++ b/tools/copyright_scanner/third_party_files_whitelist.txt
@@ -174,9 +174,6 @@
 # third-party code is taken from Mozilla, the license for which we already pick
 # up from third_party/npapi/.
 net/proxy/proxy_resolver_script.h
-# Copyright The Chromium Authors and Netscape Communications Corporation; BSD
-# and (MPL, GPL v2 or LGPL v2) licenses. Not used on Android.
-net/socket/ssl_client_socket_nss.cc
 # Contains the word 'Copyright' in comments
 ppapi/generators/idl_c_proto.py
 ppapi/generators/idl_outfile.py
diff --git a/tools/gn/BUILD.gn b/tools/gn/BUILD.gn
index 2728c0d..bb36b1ff 100644
--- a/tools/gn/BUILD.gn
+++ b/tools/gn/BUILD.gn
@@ -277,7 +277,6 @@
     "function_write_file_unittest.cc",
     "functions_target_unittest.cc",
     "functions_unittest.cc",
-    "group_target_generator_unittest.cc",
     "header_checker_unittest.cc",
     "inherited_libraries_unittest.cc",
     "input_conversion_unittest.cc",
diff --git a/tools/gn/docs/cookbook.md b/tools/gn/docs/cookbook.md
index febc16c..92bfeb55 100644
--- a/tools/gn/docs/cookbook.md
+++ b/tools/gn/docs/cookbook.md
@@ -279,8 +279,6 @@
 | `use_gnome_keyring` (0/1)               | `is_desktop_linux` (true/false)                |                               |
 | `use_goma` (0/1)                        | `use_goma` (true/false)                        | `//build/toolchain/goma.gni`  |
 | `use_nss_certs` (0/1)                   | `use_nss_certs` (true/false)                   | `//build/config/crypto.gni` (Many of these conditions can be deleted, see the "SSL" notes on targets below.) |
-| `use_nss_verifier` (0/1)                | `use_nss_verifier` (true/false)                | `//build/config/crypto.gni` (Many of these conditions can be deleted, see the "SSL" notes on targets below.) |
-| `use_openssl` (0/1)                     | `use_openssl` (true/false)                     | `//build/config/crypto.gni` (Many of these conditions can be deleted, see the "SSL" notes on targets below.) |
 | `use_pango` (0/1)                       | `use_pango` (true/false)                       | `//build/config/ui.gni`       |
 | `use_ozone` (0/1)                       | `use_ozone` (true/false)                       | `//build/config/ui.gni`       |
 | `use_seccomp_bpf` (0/1)                 | `use_seccomp_bpf` (true/false)                 | `//build/config/features.gni` |
diff --git a/tools/gn/group_target_generator_unittest.cc b/tools/gn/group_target_generator_unittest.cc
deleted file mode 100644
index 3b0c824..0000000
--- a/tools/gn/group_target_generator_unittest.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/group_target_generator.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/test_with_scope.h"
-
-namespace {
-
-// Returns true on success, false if write_file signaled an error.
-bool ParseWriteRuntimeDeps(Scope* scope, const std::string& value) {
-  TestParseInput input(
-      "group(\"foo\") { write_runtime_deps = " + value + "}");
-  if (input.has_error())
-    return false;
-
-  Err err;
-  input.parsed()->Execute(scope, &err);
-  return !err.has_error();
-}
-
-}  // namespace
-
-
-// Tests that actions can't have output substitutions.
-TEST(GroupTargetGenerator, WriteRuntimeDeps) {
-  Scheduler scheduler;
-  TestWithScope setup;
-  Scope::ItemVector items_;
-  setup.scope()->set_item_collector(&items_);
-
-  // Should refuse to write files outside of the output dir.
-  EXPECT_FALSE(ParseWriteRuntimeDeps(setup.scope(), "\"//foo.txt\""));
-  EXPECT_EQ(0U, scheduler.GetWriteRuntimeDepsTargets().size());
-
-  // Should fail for garbage inputs.
-  EXPECT_FALSE(ParseWriteRuntimeDeps(setup.scope(), "0"));
-  EXPECT_EQ(0U, scheduler.GetWriteRuntimeDepsTargets().size());
-
-  // Should be able to write inside the out dir.
-  EXPECT_TRUE(ParseWriteRuntimeDeps(setup.scope(), "\"//out/Debug/foo.txt\""));
-  EXPECT_EQ(1U, scheduler.GetWriteRuntimeDepsTargets().size());
-}
-
diff --git a/tools/gn/runtime_deps_unittest.cc b/tools/gn/runtime_deps_unittest.cc
index 915fbc2..6c2013d 100644
--- a/tools/gn/runtime_deps_unittest.cc
+++ b/tools/gn/runtime_deps_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "tools/gn/runtime_deps.h"
+#include "tools/gn/scheduler.h"
 #include "tools/gn/target.h"
 #include "tools/gn/test_with_scope.h"
 
@@ -282,3 +283,31 @@
                         MakePair("../../action.output", &action)) !=
               result.end()) << GetVectorDescription(result);
 }
+
+// Tests that actions can't have output substitutions.
+TEST(RuntimeDeps, WriteRuntimeDepsVariable) {
+  Scheduler scheduler;
+  TestWithScope setup;
+  Err err;
+
+  // Should refuse to write files outside of the output dir.
+  EXPECT_FALSE(setup.ExecuteSnippet(
+      "group(\"foo\") { write_runtime_deps = \"//foo.txt\" }", &err));
+
+  // Should fail for garbage inputs.
+  err = Err();
+  EXPECT_FALSE(setup.ExecuteSnippet(
+      "group(\"foo\") { write_runtime_deps = 0 }", &err));
+
+  // Should be able to write inside the out dir, and shouldn't write the one
+  // in the else clause.
+  err = Err();
+  EXPECT_TRUE(setup.ExecuteSnippet(
+      "if (true) {\n"
+      "  group(\"foo\") { write_runtime_deps = \"//out/Debug/foo.txt\" }\n"
+      "} else {\n"
+      "  group(\"bar\") { write_runtime_deps = \"//out/Debug/bar.txt\" }\n"
+      "}", &err));
+  EXPECT_EQ(1U, setup.items().size());
+  EXPECT_EQ(1U, scheduler.GetWriteRuntimeDepsTargets().size());
+}
diff --git a/tools/gn/target.cc b/tools/gn/target.cc
index 18c353e..e88c82f 100644
--- a/tools/gn/target.cc
+++ b/tools/gn/target.cc
@@ -324,6 +324,9 @@
     CheckSourcesGenerated();
   }
 
+  if (!write_runtime_deps_output_.value().empty())
+    g_scheduler->AddWriteRuntimeDepsTarget(this);
+
   return true;
 }
 
diff --git a/tools/gn/target_generator.cc b/tools/gn/target_generator.cc
index 2132a5b..90642d4 100644
--- a/tools/gn/target_generator.cc
+++ b/tools/gn/target_generator.cc
@@ -403,6 +403,5 @@
   OutputFile output_file(GetBuildSettings(), source_file);
   target_->set_write_runtime_deps_output(output_file);
 
-  g_scheduler->AddWriteRuntimeDepsTarget(target_);
   return true;
 }
diff --git a/tools/gn/test_with_scope.cc b/tools/gn/test_with_scope.cc
index 32d5dd6..0ddd463 100644
--- a/tools/gn/test_with_scope.cc
+++ b/tools/gn/test_with_scope.cc
@@ -24,6 +24,7 @@
   settings_.set_default_toolchain_label(toolchain_.label());
 
   SetupToolchain(&toolchain_);
+  scope_.set_item_collector(&items_);
 }
 
 TestWithScope::~TestWithScope() {
@@ -37,6 +38,28 @@
   return result;
 }
 
+bool TestWithScope::ExecuteSnippet(const std::string& str, Err* err) {
+  TestParseInput input(str);
+  if (input.has_error()) {
+    *err = input.parse_err();
+    return false;
+  }
+
+  size_t first_item = items_.size();
+  input.parsed()->Execute(&scope_, err);
+  if (err->has_error())
+    return false;
+
+  for (size_t i = first_item; i < items_.size(); ++i) {
+    CHECK(items_[i]->AsTarget() != nullptr)
+        << "Only targets are supported in ExecuteSnippet()";
+    items_[i]->AsTarget()->SetToolchain(&toolchain_);
+    if (!items_[i]->OnResolved(err))
+      return false;
+  }
+  return true;
+}
+
 // static
 void TestWithScope::SetupToolchain(Toolchain* toolchain) {
   Err err;
diff --git a/tools/gn/test_with_scope.h b/tools/gn/test_with_scope.h
index fa6fb4b..8853243 100644
--- a/tools/gn/test_with_scope.h
+++ b/tools/gn/test_with_scope.h
@@ -34,6 +34,7 @@
   Toolchain* toolchain() { return &toolchain_; }
   const Toolchain* toolchain() const { return &toolchain_; }
   Scope* scope() { return &scope_; }
+  const Scope::ItemVector& items() { return items_; }
 
   // This buffer accumulates output from any print() commands executed in the
   // context of this test. Note that the implementation of this is not
@@ -44,6 +45,11 @@
   // assert if the label isn't valid (this is intended for hardcoded labels).
   Label ParseLabel(const std::string& str) const;
 
+  // Parses, evaluates, and resolves targets from the given snippet of code.
+  // All targets must be defined in dependency order (does not use a Builder,
+  // just blindly resolves all targets in order).
+  bool ExecuteSnippet(const std::string& str, Err* err);
+
   // Fills in the tools for the given toolchain with reasonable default values.
   // The toolchain in this object will be automatically set up with this
   // function, it is exposed to allow tests to get the same functionality for
@@ -62,6 +68,7 @@
   Settings settings_;
   Toolchain toolchain_;
   Scope scope_;
+  Scope::ItemVector items_;
 
   // Supplies the scope with built-in variables like root_out_dir.
   ScopePerFileProvider scope_progammatic_provider_;
diff --git a/tools/grit/grit_rule.gni b/tools/grit/grit_rule.gni
index 90c0b00..07d8f3a 100644
--- a/tools/grit/grit_rule.gni
+++ b/tools/grit/grit_rule.gni
@@ -159,13 +159,6 @@
   ]
 }
 
-if (use_nss_verifier) {
-  grit_defines += [
-    "-D",
-    "use_nss_verifier",
-  ]
-}
-
 if (use_ozone) {
   grit_defines += [
     "-D",
diff --git a/tools/idl_parser/OWNERS b/tools/idl_parser/OWNERS
new file mode 100644
index 0000000..c5e87c09
--- /dev/null
+++ b/tools/idl_parser/OWNERS
@@ -0,0 +1,3 @@
+bashi@chromium.org
+haraken@chromium.org
+yukishiino@chromium.org
diff --git a/tools/idl_parser/idl_parser.py b/tools/idl_parser/idl_parser.py
index 45f8d7c..ff787a46 100755
--- a/tools/idl_parser/idl_parser.py
+++ b/tools/idl_parser/idl_parser.py
@@ -554,14 +554,12 @@
 
   # [36]
   def p_StringifierRest(self, p):
-    """StringifierRest : AttributeRest
+    """StringifierRest : ReadOnly AttributeRest
                        | ReturnType OperationRest
                        | ';'"""
     if len(p) == 3:
       p[2].AddChildren(p[1])
       p[0] = p[2]
-    elif p[1] != ';':
-      p[0] = p[1]
 
   # [37]
   def p_StaticMember(self, p):
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 91cbf8a9..80ab100 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -5428,6 +5428,23 @@
   </summary>
 </histogram>
 
+<histogram name="Compositing.Browser.NumActiveLayers" units="layers">
+  <owner>paint-dev@chromium.org</owner>
+  <summary>
+    The number of layers in the active tree for each compositor frame. This is
+    logged once per frame, before the frame is drawn (in a browser process).
+  </summary>
+</histogram>
+
+<histogram name="Compositing.Browser.NumRenderSurfaces" units="surfaces">
+  <owner>paint-dev@chromium.org</owner>
+  <summary>
+    The number of render surfaces in the render surface layer list. Recorded
+    each time the render surface layer list is constructed (in a browser
+    process).
+  </summary>
+</histogram>
+
 <histogram name="Compositing.Browser.PictureMemoryUsageKb" units="KB">
   <owner>paint-dev@chromium.org</owner>
   <summary>
@@ -5540,6 +5557,10 @@
 </histogram>
 
 <histogram name="Compositing.NumActiveLayers">
+  <obsolete>
+    Deprecated 04/2016, replaced by similar metrics under Compositing.Renderer
+    and Compositing.Browser, depending on which process it occurs in.
+  </obsolete>
   <owner>dneto@chromium.org</owner>
   <summary>
     The number of layers in the active tree for each compositor frame. This is
@@ -5646,6 +5667,23 @@
   </summary>
 </histogram>
 
+<histogram name="Compositing.Renderer.NumActiveLayers" units="layers">
+  <owner>paint-dev@chromium.org</owner>
+  <summary>
+    The number of layers in the active tree for each compositor frame. This is
+    logged once per frame, before the frame is drawn (in a renderer process).
+  </summary>
+</histogram>
+
+<histogram name="Compositing.Renderer.NumRenderSurfaces" units="surfaces">
+  <owner>paint-dev@chromium.org</owner>
+  <summary>
+    The number of render surfaces in the render surface layer list. Recorded
+    each time the render surface layer list is constructed (in a renderer
+    process).
+  </summary>
+</histogram>
+
 <histogram name="Compositing.Renderer.PictureMemoryUsageKb" units="KB">
   <owner>paint-dev@chromium.org</owner>
   <summary>
@@ -75647,6 +75685,7 @@
   <int value="-384589459" label="disable-supervised-user-safesites"/>
   <int value="-378180863" label="disable-panels"/>
   <int value="-378033324" label="disable-win32k-renderer-lockdown"/>
+  <int value="-362022976" label="disable-quirks-client"/>
   <int value="-360038744" label="invert-viewport-scroll-order"/>
   <int value="-351552989" label="disable-hosted-apps-in-windows"/>
   <int value="-351127770" label="enable-offline-pages-as-bookmarks"/>
diff --git a/tools/perf/benchmarks/memory_infra.py b/tools/perf/benchmarks/memory_infra.py
index 801dd47..40f09ad 100644
--- a/tools/perf/benchmarks/memory_infra.py
+++ b/tools/perf/benchmarks/memory_infra.py
@@ -52,22 +52,13 @@
 # TODO(bashi): Workaround for http://crbug.com/532075
 # @benchmark.Enabled('android') shouldn't be needed.
 @benchmark.Enabled('android')
-class MemoryHealthPlan(_MemoryInfra):
-  """Timeline based benchmark for the Memory Health Plan."""
-
-  _PREFIX_WHITELIST = ('memory_allocator_', 'memory_android_memtrack_',
-                       'memory_mmaps_', 'process_count_')
-
+class MemoryHealthQuick(_MemoryInfra):
+  """Timeline based benchmark for the Memory Health Plan (1 iteration)."""
   page_set = page_sets.MemoryHealthStory
 
   @classmethod
   def Name(cls):
-    return 'memory.memory_health_plan'
-
-  @classmethod
-  def ValueCanBeAddedPredicate(cls, value, is_first_result):
-    return (value.tir_label in ['foreground', 'background']
-            and any(value.name.startswith(p) for p in cls._PREFIX_WHITELIST))
+    return 'memory.memory_health_quick'
 
   @classmethod
   def ShouldDisable(cls, possible_browser):
@@ -76,6 +67,17 @@
     return 'nexus' not in possible_browser.platform.GetDeviceTypeName().lower()
 
 
+# Benchmark is disabled by default because it takes too long to run.
+@benchmark.Disabled('all')
+class MemoryHealthPlan(MemoryHealthQuick):
+  """Timeline based benchmark for the Memory Health Plan (5 iterations)."""
+  options = {'pageset_repeat': 5}
+
+  @classmethod
+  def Name(cls):
+    return 'memory.memory_health_plan'
+
+
 # TODO(bashi): Workaround for http://crbug.com/532075
 # @benchmark.Enabled('android') shouldn't be needed.
 @benchmark.Enabled('android')
diff --git a/tools/perf/benchmarks/rasterize_and_record_micro.py b/tools/perf/benchmarks/rasterize_and_record_micro.py
index f2260d5..eaed3f4 100644
--- a/tools/perf/benchmarks/rasterize_and_record_micro.py
+++ b/tools/perf/benchmarks/rasterize_and_record_micro.py
@@ -46,7 +46,9 @@
 
 # RasterizeAndRecord disabled on mac because of crbug.com/350684.
 # RasterizeAndRecord disabled on windows because of crbug.com/338057.
-@benchmark.Disabled('mac', 'win')
+# RasterizeAndRecord disabled on linux because of crbug.com/600377.
+# RasterizeAndRecord disabled on android because of crbug.com/605120.
+@benchmark.Disabled('mac', 'win', 'linux', 'android')
 class RasterizeAndRecordMicroTop25(_RasterizeAndRecordMicro):
   """Measures rasterize and record performance on the top 25 web pages.
 
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index 4162a15..ae70a60 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -116,6 +116,7 @@
     deps += [
       "//ui/events:events_base",
       "//ui/events/devices",
+      "//ui/events/devices/x11",
       "//ui/events/platform/x11",
       "//ui/gfx/x",
     ]
diff --git a/ui/aura/aura.gyp b/ui/aura/aura.gyp
index 2e6ff1a..d39e82f 100644
--- a/ui/aura/aura.gyp
+++ b/ui/aura/aura.gyp
@@ -118,6 +118,7 @@
             '../../build/linux/system.gyp:xrandr',
             '../../build/linux/system.gyp:xi',
             '../events/devices/events_devices.gyp:events_devices',
+            '../events/devices/x11/events_devices_x11.gyp:events_devices_x11',
             '../events/platform/x11/x11_events_platform.gyp:x11_events_platform',
             '../gfx/x/gfx_x11.gyp:gfx_x11',
           ],
diff --git a/ui/aura/test/aura_test_helper.cc b/ui/aura/test/aura_test_helper.cc
index 2d679e5..10c45ca3 100644
--- a/ui/aura/test/aura_test_helper.cc
+++ b/ui/aura/test/aura_test_helper.cc
@@ -67,9 +67,12 @@
 
   ui::InitializeInputMethodForTesting();
 
-  gfx::Size host_size(800, 600);
+  gfx::Screen* screen = gfx::Screen::GetScreen();
+  gfx::Size host_size(screen ? screen->GetPrimaryDisplay().GetSizeInPixel()
+                             : gfx::Size(800, 600));
   test_screen_.reset(TestScreen::Create(host_size));
-  gfx::Screen::SetScreenInstance(test_screen_.get());
+  if (!screen)
+    gfx::Screen::SetScreenInstance(test_screen_.get());
   host_.reset(test_screen_->CreateHostForPrimaryDisplay());
 
   focus_client_.reset(new TestFocusClient);
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index 6390bd4e..a4f296f 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -412,6 +412,8 @@
       "dragdrop/drag_utils_aura.cc",
     ]
   }
+
+  # TODO(kylechar): remove ozone_platform_x11 from here.
   if (use_x11 || ozone_platform_x11) {
     sources += [
       "x/x11_foreign_window_manager.cc",
@@ -431,7 +433,10 @@
       ]
       configs += [ "//build/config/linux:xscrnsaver" ]
     }
-    deps += [ "//ui/gfx/x" ]
+    deps += [
+      "//ui/events/devices/x11",
+      "//ui/gfx/x",
+    ]
   }
 
   if (!use_aura || !is_linux) {
diff --git a/ui/base/ui_base.gyp b/ui/base/ui_base.gyp
index c8c369d..06a52ffe 100644
--- a/ui/base/ui_base.gyp
+++ b/ui/base/ui_base.gyp
@@ -607,6 +607,7 @@
             '../../build/linux/system.gyp:xfixes',
             '../../build/linux/system.gyp:xrender',  # For XRender* function calls in x11_util.cc.
             '../events/devices/events_devices.gyp:events_devices',
+            '../events/devices/x11/events_devices_x11.gyp:events_devices_x11',
             '../events/platform/x11/x11_events_platform.gyp:x11_events_platform',
             '../gfx/x/gfx_x11.gyp:gfx_x11',
           ],
diff --git a/ui/events/BUILD.gn b/ui/events/BUILD.gn
index a7fc9af..0787103 100644
--- a/ui/events/BUILD.gn
+++ b/ui/events/BUILD.gn
@@ -165,6 +165,7 @@
     ]
     deps += [
       "//ui/events/devices",
+      "//ui/events/devices/x11",
       "//ui/gfx/x",
     ]
   }
@@ -338,7 +339,7 @@
       "test/events_test_utils_x11.h",
     ]
     deps += [
-      "//ui/events/devices",
+      "//ui/events/devices/x11",
       "//ui/gfx/x",
     ]
   }
@@ -425,6 +426,7 @@
     ]
     configs += [ "//build/config/linux:x11" ]
     deps += [
+      "//ui/events/devices/x11",
       "//ui/events/x",
       "//ui/gfx/x",
     ]
diff --git a/ui/events/devices/BUILD.gn b/ui/events/devices/BUILD.gn
index f3dbfd5..c440545 100644
--- a/ui/events/devices/BUILD.gn
+++ b/ui/events/devices/BUILD.gn
@@ -2,9 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/ui.gni")
-import("//ui/ozone/ozone.gni")
-
 component("devices") {
   sources = [
     "device_data_manager.cc",
@@ -31,22 +28,4 @@
     "//ui/gfx",
     "//ui/gfx/geometry",
   ]
-
-  if (use_x11 || ozone_platform_x11) {
-    configs += [ "//build/config/linux:x11" ]
-
-    sources += [
-      "x11/device_data_manager_x11.cc",
-      "x11/device_data_manager_x11.h",
-      "x11/device_list_cache_x11.cc",
-      "x11/device_list_cache_x11.h",
-      "x11/touch_factory_x11.cc",
-      "x11/touch_factory_x11.h",
-    ]
-
-    deps += [
-      "//ui/events:events_base",
-      "//ui/gfx/x",
-    ]
-  }
 }
diff --git a/ui/events/devices/events_devices.gyp b/ui/events/devices/events_devices.gyp
index 1a20ee7..f0e1563 100644
--- a/ui/events/devices/events_devices.gyp
+++ b/ui/events/devices/events_devices.gyp
@@ -34,25 +34,10 @@
         'keyboard_device.h',
         'touchscreen_device.cc',
         'touchscreen_device.h',
-        'x11/device_data_manager_x11.cc',
-        'x11/device_data_manager_x11.h',
-        'x11/device_list_cache_x11.cc',
-        'x11/device_list_cache_x11.h',
-        'x11/touch_factory_x11.cc',
-        'x11/touch_factory_x11.h',
       ],
       'export_dependent_settings': [
         '../../../ui/gfx/gfx.gyp:gfx',
       ],
-      'conditions': [
-        ['use_x11==1', {
-          'dependencies': [
-            '../../../build/linux/system.gyp:x11',
-            '../../../ui/events/events.gyp:events_base',
-            '../../../ui/gfx/x/gfx_x11.gyp:gfx_x11',
-          ],
-        }],
-      ],
     },
   ],
 }
diff --git a/ui/events/devices/x11/BUILD.gn b/ui/events/devices/x11/BUILD.gn
new file mode 100644
index 0000000..1aa7ed70
--- /dev/null
+++ b/ui/events/devices/x11/BUILD.gn
@@ -0,0 +1,32 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+component("x11") {
+  output_name = "events_devices_x11"
+
+  sources = [
+    "device_data_manager_x11.cc",
+    "device_data_manager_x11.h",
+    "device_list_cache_x11.cc",
+    "device_list_cache_x11.h",
+    "events_devices_x11_export.h",
+    "touch_factory_x11.cc",
+    "touch_factory_x11.h",
+  ]
+
+  configs += [ "//build/config/linux:x11" ]
+
+  defines = [ "EVENTS_DEVICES_X11_IMPLEMENTATION" ]
+
+  deps = [
+    "//base",
+    "//base/third_party/dynamic_annotations",
+    "//skia",
+    "//ui/events:events_base",
+    "//ui/events/devices",
+    "//ui/gfx",
+    "//ui/gfx/geometry",
+    "//ui/gfx/x",
+  ]
+}
diff --git a/ui/events/devices/x11/device_data_manager_x11.h b/ui/events/devices/x11/device_data_manager_x11.h
index d09cf34..072378e 100644
--- a/ui/events/devices/x11/device_data_manager_x11.h
+++ b/ui/events/devices/x11/device_data_manager_x11.h
@@ -24,7 +24,7 @@
 #include "base/event_types.h"
 #include "base/macros.h"
 #include "ui/events/devices/device_data_manager.h"
-#include "ui/events/devices/events_devices_export.h"
+#include "ui/events/devices/x11/events_devices_x11_export.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/gfx/geometry/rect.h"
@@ -49,7 +49,8 @@
 
 // A class that extracts and tracks the input events data. It currently handles
 // mouse, touchpad and touchscreen devices.
-class EVENTS_DEVICES_EXPORT DeviceDataManagerX11 : public DeviceDataManager {
+class EVENTS_DEVICES_X11_EXPORT DeviceDataManagerX11
+    : public DeviceDataManager {
  public:
   // Enumerate additional data that one might be interested on an input event,
   // which are usually wrapped in X valuators. If you modify any of this,
diff --git a/ui/events/devices/x11/device_list_cache_x11.h b/ui/events/devices/x11/device_list_cache_x11.h
index 2ff3943a..1618fc14 100644
--- a/ui/events/devices/x11/device_list_cache_x11.h
+++ b/ui/events/devices/x11/device_list_cache_x11.h
@@ -12,7 +12,7 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "ui/events/devices/events_devices_export.h"
+#include "ui/events/devices/x11/events_devices_x11_export.h"
 #include "ui/gfx/x/x11_types.h"
 
 namespace base {
@@ -38,7 +38,7 @@
 // A class to cache the current XInput device list. This minimized the
 // round-trip time to the X server whenever such a device list is needed. The
 // update function will be called on each incoming XI_HierarchyChanged event.
-class EVENTS_DEVICES_EXPORT DeviceListCacheX11 {
+class EVENTS_DEVICES_X11_EXPORT DeviceListCacheX11 {
  public:
   static DeviceListCacheX11* GetInstance();
 
diff --git a/ui/events/devices/x11/events_devices_x11.gyp b/ui/events/devices/x11/events_devices_x11.gyp
new file mode 100644
index 0000000..1093f99c
--- /dev/null
+++ b/ui/events/devices/x11/events_devices_x11.gyp
@@ -0,0 +1,38 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'variables': {
+    'chromium_code': 1,
+  },
+  'targets': [
+    {
+      'target_name': 'events_devices_x11',
+      'type': '<(component)',
+      'dependencies': [
+        '../../../../base/base.gyp:base',
+        '../../../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+        '../../../../build/linux/system.gyp:x11',
+        '../../../../skia/skia.gyp:skia',
+        '../../../../ui/events/events.gyp:events_base',
+        '../../../../ui/events/devices/events_devices.gyp:events_devices',
+        '../../../../ui/gfx/gfx.gyp:gfx',
+        '../../../../ui/gfx/gfx.gyp:gfx_geometry',
+        '../../../../ui/gfx/x/gfx_x11.gyp:gfx_x11',
+      ],
+      'defines': [
+        'EVENTS_DEVICES_X11_IMPLEMENTATION',
+      ],
+      'sources': [
+        'device_data_manager_x11.cc',
+        'device_data_manager_x11.h',
+        'device_list_cache_x11.cc',
+        'device_list_cache_x11.h',
+        'events_devices_x11_export.h',
+        'touch_factory_x11.cc',
+        'touch_factory_x11.h',
+      ],
+    },
+  ],
+}
diff --git a/ui/events/devices/x11/events_devices_x11_export.h b/ui/events/devices/x11/events_devices_x11_export.h
new file mode 100644
index 0000000..cf5f77df
--- /dev/null
+++ b/ui/events/devices/x11/events_devices_x11_export.h
@@ -0,0 +1,29 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_DEVICES_X11_EVENTS_DEVICES_X11_EXPORT_H_
+#define UI_EVENTS_DEVICES_X11_EVENTS_DEVICES_X11_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(EVENTS_DEVICES_X11_IMPLEMENTATION)
+#define EVENTS_DEVICES_X11_EXPORT __declspec(dllexport)
+#else
+#define EVENTS_DEVICES_X11_EXPORT __declspec(dllimport)
+#endif  // defined(EVENTS_DEVICES_X11_IMPLEMENTATION)
+
+#else  // defined(WIN32)
+#if defined(EVENTS_DEVICES_X11_IMPLEMENTATION)
+#define EVENTS_DEVICES_X11_EXPORT __attribute__((visibility("default")))
+#else
+#define EVENTS_DEVICES_X11_EXPORT
+#endif
+#endif
+
+#else  // defined(COMPONENT_BUILD)
+#define EVENTS_DEVICES_X11_EXPORT
+#endif
+
+#endif  // UI_EVENTS_DEVICES_X11_EVENTS_DEVICES_X11_EXPORT_H_
diff --git a/ui/events/devices/x11/touch_factory_x11.h b/ui/events/devices/x11/touch_factory_x11.h
index 496dcb5..7588398 100644
--- a/ui/events/devices/x11/touch_factory_x11.h
+++ b/ui/events/devices/x11/touch_factory_x11.h
@@ -14,7 +14,7 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "ui/events/devices/events_devices_export.h"
+#include "ui/events/devices/x11/events_devices_x11_export.h"
 #include "ui/gfx/sequential_id_generator.h"
 
 namespace base {
@@ -30,7 +30,7 @@
 namespace ui {
 
 // Functions related to determining touch devices.
-class EVENTS_DEVICES_EXPORT TouchFactory {
+class EVENTS_DEVICES_X11_EXPORT TouchFactory {
  private:
   TouchFactory();
   ~TouchFactory();
diff --git a/ui/events/events.gyp b/ui/events/events.gyp
index c8d994f..cf1ed63 100644
--- a/ui/events/events.gyp
+++ b/ui/events/events.gyp
@@ -162,6 +162,7 @@
             '../../build/linux/system.gyp:x11',
             '../gfx/x/gfx_x11.gyp:gfx_x11',
             'devices/events_devices.gyp:events_devices',
+            'devices/x11/events_devices_x11.gyp:events_devices_x11',
             'x/events_x.gyp:events_x',
           ],
         }],
@@ -362,6 +363,11 @@
           # The cocoa files don't apply to iOS.
           'sources/': [['exclude', 'cocoa']],
         }],
+        ['use_x11==1', {
+          'dependencies': [
+            'devices/x11/events_devices_x11.gyp:events_devices_x11',
+          ],
+        }],
         ['use_x11==1 or use_ozone==1', {
           'sources' : [
               'test/device_data_manager_test_api_impl.cc',
diff --git a/ui/events/events_unittests.gyp b/ui/events/events_unittests.gyp
index f5a5d01c..f8e0ed9 100644
--- a/ui/events/events_unittests.gyp
+++ b/ui/events/events_unittests.gyp
@@ -72,7 +72,8 @@
           'dependencies': [
             '../../build/linux/system.gyp:x11',
             '../gfx/x/gfx_x11.gyp:gfx_x11',
-	    'x/events_x.gyp:events_x',
+            'devices/x11/events_devices_x11.gyp:events_devices_x11',
+            'x/events_x.gyp:events_x',
           ],
         }],
         ['use_ozone==1', {
diff --git a/ui/events/platform/x11/BUILD.gn b/ui/events/platform/x11/BUILD.gn
index 929613c7f..a4801af 100644
--- a/ui/events/platform/x11/BUILD.gn
+++ b/ui/events/platform/x11/BUILD.gn
@@ -25,6 +25,7 @@
     "//ui/events",
     "//ui/events:events_base",
     "//ui/events/devices",
+    "//ui/events/devices/x11",
     "//ui/events/platform",
     "//ui/events/x",
     "//ui/gfx/x",
diff --git a/ui/events/platform/x11/x11_events_platform.gyp b/ui/events/platform/x11/x11_events_platform.gyp
index a624722..de6a9b9 100644
--- a/ui/events/platform/x11/x11_events_platform.gyp
+++ b/ui/events/platform/x11/x11_events_platform.gyp
@@ -18,6 +18,7 @@
       '../../../../build/linux/system.gyp:x11',
       '../../../gfx/x/gfx_x11.gyp:gfx_x11',
       '../../devices/events_devices.gyp:events_devices',
+      '../../devices/x11/events_devices_x11.gyp:events_devices_x11',
       '../../events.gyp:events',
       '../../events.gyp:events_base',
       '../../x/events_x.gyp:events_x',
diff --git a/ui/events/x/BUILD.gn b/ui/events/x/BUILD.gn
index 991ce6e..bff8a29 100644
--- a/ui/events/x/BUILD.gn
+++ b/ui/events/x/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 component("x") {
+  output_name = "events_x"
   sources = [
     "events_x_export.h",
     "events_x_utils.cc",
@@ -14,6 +15,7 @@
     "//skia",
     "//ui/events:events_base",
     "//ui/events/devices",
+    "//ui/events/devices/x11",
     "//ui/gfx/x",
   ]
   configs += [ "//build/config/linux:x11" ]
diff --git a/ui/events/x/events_x.gyp b/ui/events/x/events_x.gyp
index 0432178..9b3f802 100644
--- a/ui/events/x/events_x.gyp
+++ b/ui/events/x/events_x.gyp
@@ -15,6 +15,7 @@
         '<(DEPTH)/base/base.gyp:base',
         '<(DEPTH)/skia/skia.gyp:skia',
         '../../events/devices/events_devices.gyp:events_devices',
+        '../../events/devices/x11/events_devices_x11.gyp:events_devices_x11',
         '../../events/events.gyp:events_base',
         '../../gfx/x/gfx_x11.gyp:gfx_x11',
       ],
diff --git a/ui/login/account_picker/screen_account_picker.js b/ui/login/account_picker/screen_account_picker.js
index fa287e2a..cccf723 100644
--- a/ui/login/account_picker/screen_account_picker.js
+++ b/ui/login/account_picker/screen_account_picker.js
@@ -203,6 +203,9 @@
     loadUsers: function(users, showGuest) {
       $('pod-row').loadPods(users);
       $('login-header-bar').showGuestButton = showGuest;
+      // On Desktop, #login-header-bar has a shadow if there are 8+ profiles.
+      if (Oobe.getInstance().displayType == DISPLAY_TYPE.DESKTOP_USER_MANAGER)
+        $('login-header-bar').classList.toggle('shadow', users.length > 8);
     },
 
     /**
diff --git a/ui/login/account_picker/user_pod_row.css b/ui/login/account_picker/user_pod_row.css
index 88f117b..32a1f93c 100644
--- a/ui/login/account_picker/user_pod_row.css
+++ b/ui/login/account_picker/user_pod_row.css
@@ -433,6 +433,16 @@
   background-image: url(chrome://theme/IDR_OOBE_ACTION_BOX_BUTTON_PRESSED);
 }
 
+.action-box-area .action-box-icon {
+  /* overriden in chrome/browser/resources/md_user_manager/user_manager.css */
+  display: none;
+}
+
+.user-image-gradient-area {
+  /* overriden in chrome/browser/resources/md_user_manager/user_manager.css */
+  display: none;
+}
+
 .user-type-icon-area {
   left: 0;
   z-index: 5;
@@ -571,9 +581,18 @@
 }
 
 .action-box-remove-user-warning .remove-warning-button {
+  background: rgb(197, 57, 41);
+  border-radius: 2px;
+  color: white;
+  line-height: 32px;
+  padding: 0 16px;
   width: 100%;
 }
 
+.action-box-remove-user-warning .remove-warning-button.keyboard-focus {
+  font-weight: normal;
+}
+
 /* Hide dialog elements not in a correct category. Only combinations currently
    in use are included here. */
 .pod.legacy-supervised .non-sync,
diff --git a/ui/login/account_picker/user_pod_row.js b/ui/login/account_picker/user_pod_row.js
index 8bc93b9..5beacb4 100644
--- a/ui/login/account_picker/user_pod_row.js
+++ b/ui/login/account_picker/user_pod_row.js
@@ -28,7 +28,7 @@
    * @type {Array<number>}
    * @const
    */
-  var DESKTOP_MARGIN_BY_COLUMNS = [undefined, 15, 15, 15, 15, 15, 15];
+  var DESKTOP_MARGIN_BY_COLUMNS = [undefined, 32, 32, 32, 32, 32, 32];
 
   /**
    * Maximal number of columns currently supported by pod-row.
@@ -48,13 +48,16 @@
    * Variables used for pod placement processing. Width and height should be
    * synced with computed CSS sizes of pods.
    */
-  var POD_WIDTH = 180;
+  var CROS_POD_WIDTH = 180;
+  var DESKTOP_POD_WIDTH = 180;
+  var MD_DESKTOP_POD_WIDTH = 160;
   var PUBLIC_EXPANDED_BASIC_WIDTH = 500;
   var PUBLIC_EXPANDED_ADVANCED_WIDTH = 610;
   var CROS_POD_HEIGHT = 213;
   var DESKTOP_POD_HEIGHT = 226;
+  var MD_DESKTOP_POD_HEIGHT = 200;
   var POD_ROW_PADDING = 10;
-  var DESKTOP_ROW_PADDING = 15;
+  var DESKTOP_ROW_PADDING = 32;
   var CUSTOM_ICON_CONTAINER_SIZE = 40;
 
   /**
@@ -1548,19 +1551,26 @@
       if (profilePath !== this.user.profilePath)
         return;
       // Add localized messages where $1 will be replaced with
-      // <span class="total-count"></span>.
+      // <span class="total-count"></span> and $2 will be replaced with
+      // <span class="email"></span>.
       var element = this.querySelector('.action-box-remove-user-warning-text');
       element.textContent = '';
 
-      messageParts = message.split('$1');
+      messageParts = message.split(/(\$[12])/);
       var numParts = messageParts.length;
       for (var j = 0; j < numParts; j++) {
-        element.appendChild(document.createTextNode(messageParts[j]));
-        if (j < numParts - 1) {
+        if (messageParts[j] === '$1') {
           var elementToAdd = document.createElement('span');
           elementToAdd.classList.add('total-count');
           elementToAdd.textContent = count;
           element.appendChild(elementToAdd);
+        } else if (messageParts[j] === '$2') {
+          var elementToAdd = document.createElement('span');
+          elementToAdd.classList.add('email');
+          elementToAdd.textContent = this.user.emailAddress;
+          element.appendChild(elementToAdd);
+        } else {
+          element.appendChild(document.createTextNode(messageParts[j]));
         }
       }
       this.moveActionMenuUpIfNeeded_();
@@ -2312,10 +2322,15 @@
 
       var isDesktopUserManager = Oobe.getInstance().displayType ==
           DISPLAY_TYPE.DESKTOP_USER_MANAGER;
-      this.userPodHeight_ = isDesktopUserManager ? DESKTOP_POD_HEIGHT :
-                                                   CROS_POD_HEIGHT;
-      // Same for Chrome OS and desktop.
-      this.userPodWidth_ = POD_WIDTH;
+      var isNewDesktopUserManager = Oobe.getInstance().newDesktopUserManager;
+      this.userPodHeight_ = isDesktopUserManager ?
+          isNewDesktopUserManager ? MD_DESKTOP_POD_HEIGHT :
+                                    DESKTOP_POD_HEIGHT :
+          CROS_POD_HEIGHT;
+      this.userPodWidth_ = isDesktopUserManager ?
+          isNewDesktopUserManager ? MD_DESKTOP_POD_WIDTH :
+                                    DESKTOP_POD_WIDTH :
+          CROS_POD_WIDTH;
     },
 
     /**
@@ -2793,9 +2808,11 @@
           $('signin-banner'), null).getPropertyValue('display') != 'none') {
         rows = Math.min(rows, MAX_NUMBER_OF_ROWS_UNDER_SIGNIN_BANNER);
       }
-      var maxHeigth = Oobe.getInstance().clientAreaSize.height;
-      while (maxHeigth < this.rowsToHeight_(rows) && rows > 1)
-        --rows;
+      if (!Oobe.getInstance().newDesktopUserManager) {
+        var maxHeigth = Oobe.getInstance().clientAreaSize.height;
+        while (maxHeigth < this.rowsToHeight_(rows) && rows > 1)
+         --rows;
+      }
       // One more iteration if it's not enough cells to place all pods.
       while (maxWidth >= this.columnsToWidth_(columns + 1) &&
              columns * rows < this.pods.length &&
diff --git a/ui/login/account_picker/user_pod_template.html b/ui/login/account_picker/user_pod_template.html
index cf302ba4..008b28c8 100644
--- a/ui/login/account_picker/user_pod_template.html
+++ b/ui/login/account_picker/user_pod_template.html
@@ -52,6 +52,9 @@
   </div>
   <div class="action-box-area">
     <div class="custom-appearance action-box-button"></div>
+    <iron-icon icon="more-vert" class="action-box-icon"></iron-icon>
+  </div>
+  <div class="user-image-gradient-area">
   </div>
   <div class="user-type-icon-area" hidden>
     <div class="custom-appearance user-type-icon-image"></div>
@@ -97,9 +100,8 @@
       </table>
       <div class="action-box-remove-legacy-supervised-user-warning-text"
           i18n-content="removeLegacySupervisedUserWarningText"></div>
-      <button class="remove-warning-button
-                     custom-appearance button-fancy button-red"
-          i18n-content="removeUserWarningButtonTitle"></button>
+      <paper-button class="remove-warning-button"
+          i18n-content="removeUserWarningButtonTitle"></paper-button>
     </div>
   </div>
   <div class="user-type-bubble">
diff --git a/ui/login/account_picker/user_pod_template.js b/ui/login/account_picker/user_pod_template.js
index 0a5ee8a..7853c5e 100644
--- a/ui/login/account_picker/user_pod_template.js
+++ b/ui/login/account_picker/user_pod_template.js
@@ -16,6 +16,8 @@
     }
 
     lazyLoadUrl('chrome://resources/polymer/v1_0/iron-icons/iron-icons.html');
+    lazyLoadUrl(
+        'chrome://resources/polymer/v1_0/paper-button/paper-button.html');
   }
 
   window.addEventListener('load', function() {
diff --git a/ui/platform_window/x11/BUILD.gn b/ui/platform_window/x11/BUILD.gn
index bac1aaa..d3edc9a 100644
--- a/ui/platform_window/x11/BUILD.gn
+++ b/ui/platform_window/x11/BUILD.gn
@@ -15,6 +15,7 @@
     "//skia",
     "//ui/events",
     "//ui/events/devices",
+    "//ui/events/devices/x11",
     "//ui/events/platform",
     "//ui/events/platform/x11",
     "//ui/gfx/x",
diff --git a/ui/platform_window/x11/x11_window.gyp b/ui/platform_window/x11/x11_window.gyp
index f4b948a..b81fbd2 100644
--- a/ui/platform_window/x11/x11_window.gyp
+++ b/ui/platform_window/x11/x11_window.gyp
@@ -17,6 +17,7 @@
       '../../../skia/skia.gyp:skia',
       '../../events/devices/events_devices.gyp:events_devices',
       '../../events/events.gyp:events',
+      '../../events/devices/x11/events_devices_x11.gyp:events_devices_x11',
       '../../events/platform/events_platform.gyp:events_platform',
       '../../events/platform/x11/x11_events_platform.gyp:x11_events_platform',
       '../../gfx/x/gfx_x11.gyp:gfx_x11',
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 576c2b72..b7b01f37 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -105,6 +105,7 @@
     ]
     deps += [
       "//ui/events/devices",
+      "//ui/events/devices/x11",
       "//ui/events/platform/x11",
       "//ui/gfx/x",
     ]
diff --git a/ui/views/mus/BUILD.gn b/ui/views/mus/BUILD.gn
index 3e058c6..b166f85 100644
--- a/ui/views/mus/BUILD.gn
+++ b/ui/views/mus/BUILD.gn
@@ -152,6 +152,7 @@
     "native_widget_mus_unittest.cc",
     "platform_test_helper_mus.cc",
     "run_all_unittests_mus.cc",
+    "screen_mus_unittest.cc",
   ]
 
   deps = [
diff --git a/ui/views/mus/screen_mus.cc b/ui/views/mus/screen_mus.cc
index d22499c..faa31ad 100644
--- a/ui/views/mus/screen_mus.cc
+++ b/ui/views/mus/screen_mus.cc
@@ -17,9 +17,19 @@
 template <>
 struct TypeConverter<gfx::Display, mus::mojom::DisplayPtr> {
   static gfx::Display Convert(const mus::mojom::DisplayPtr& input) {
-    gfx::Display result(input->id, input->bounds.To<gfx::Rect>());
-    result.set_work_area(input->work_area.To<gfx::Rect>());
+    gfx::Display result(input->id);
+    gfx::Rect pixel_bounds = input->bounds.To<gfx::Rect>();
+    gfx::Rect pixel_work_area = input->work_area.To<gfx::Rect>();
+    float pixel_ratio = input->device_pixel_ratio;
+
+    gfx::Rect dip_bounds =
+        gfx::ScaleToEnclosingRect(pixel_bounds, 1.f / pixel_ratio);
+    gfx::Rect dip_work_area =
+        gfx::ScaleToEnclosingRect(pixel_work_area, 1.f / pixel_ratio);
+    result.set_bounds(dip_bounds);
+    result.set_work_area(dip_work_area);
     result.set_device_scale_factor(input->device_pixel_ratio);
+
     switch (input->rotation) {
       case mus::mojom::Rotation::VALUE_0:
         result.set_rotation(gfx::Display::ROTATE_0);
diff --git a/ui/views/mus/screen_mus_unittest.cc b/ui/views/mus/screen_mus_unittest.cc
new file mode 100644
index 0000000..fe80a72b
--- /dev/null
+++ b/ui/views/mus/screen_mus_unittest.cc
@@ -0,0 +1,32 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/mus/screen_mus.h"
+
+#include "base/command_line.h"
+#include "ui/gfx/screen.h"
+#include "ui/gfx/switches.h"
+#include "ui/views/mus/window_manager_connection.h"
+#include "ui/views/test/scoped_views_test_helper.h"
+#include "ui/views/test/views_test_base.h"
+
+namespace views {
+namespace {
+
+TEST(ScreenMusTest, ConsistentDisplayInHighDPI) {
+  base::MessageLoop message_loop(base::MessageLoop::TYPE_UI);
+  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kForceDeviceScaleFactor, "2");
+  ScopedViewsTestHelper test_helper;
+  gfx::Screen* screen = gfx::Screen::GetScreen();
+  std::vector<gfx::Display> displays = screen->GetAllDisplays();
+  ASSERT_FALSE(displays.empty());
+  for (const gfx::Display& display : displays) {
+    EXPECT_EQ(2.f, display.device_scale_factor());
+    EXPECT_EQ(display.work_area(), display.bounds());
+  }
+}
+
+}  // namespace
+}  // namespace views
diff --git a/ui/views/views.gyp b/ui/views/views.gyp
index dc89d3c..92476a2 100644
--- a/ui/views/views.gyp
+++ b/ui/views/views.gyp
@@ -763,6 +763,7 @@
             '../../build/linux/system.gyp:x11',
             '../../build/linux/system.gyp:xrandr',
             '../events/devices/events_devices.gyp:events_devices',
+            '../events/devices/x11/events_devices_x11.gyp:events_devices_x11',
             '../events/platform/x11/x11_events_platform.gyp:x11_events_platform',
             '../gfx/x/gfx_x11.gyp:gfx_x11',
           ],
diff --git a/ui/wm/BUILD.gn b/ui/wm/BUILD.gn
index 3be6e2d8..1881478 100644
--- a/ui/wm/BUILD.gn
+++ b/ui/wm/BUILD.gn
@@ -85,6 +85,7 @@
 
   if (use_x11) {
     configs += [ "//build/config/linux:x11" ]
+    deps += [ "//ui/events/devices/x11" ]
   }
 }
 
diff --git a/ui/wm/core/compound_event_filter.cc b/ui/wm/core/compound_event_filter.cc
index 70f76c6..74ecae27 100644
--- a/ui/wm/core/compound_event_filter.cc
+++ b/ui/wm/core/compound_event_filter.cc
@@ -18,7 +18,7 @@
 #include "ui/wm/public/drag_drop_client.h"
 
 #if defined(OS_CHROMEOS) && defined(USE_X11)
-#include "ui/events/devices/x11/touch_factory_x11.h"
+#include "ui/events/devices/x11/touch_factory_x11.h"  // nogncheck
 #endif
 
 namespace wm {
diff --git a/ui/wm/wm.gyp b/ui/wm/wm.gyp
index 685c9769..aa7ef5ac 100644
--- a/ui/wm/wm.gyp
+++ b/ui/wm/wm.gyp
@@ -91,6 +91,7 @@
         ['use_x11==1', {
           'dependencies': [
             '../../build/linux/system.gyp:x11',
+            '../events/devices/x11/events_devices_x11.gyp:events_devices_x11',
           ],
         }],
       ],