diff --git a/BUILD.gn b/BUILD.gn
index 9378182..82a71f8a0 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -456,7 +456,10 @@
     }
 
     if (enable_extensions) {
-      deps += [ "//extensions/shell:app_shell" ]
+      deps += [
+        "//extensions/shell:app_shell",
+        "//extensions/shell/installer",
+      ]
     }
 
     if (enable_nacl) {
diff --git a/DEPS b/DEPS
index a8aa20c..1e7b884 100644
--- a/DEPS
+++ b/DEPS
@@ -40,11 +40,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': 'bc2cdd154bf5a031ca9d3a530123d9f7a4c0925d',
+  'skia_revision': '6a0feba05bd57e84103cebc695d4a217ec9e472e',
   # 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': 'ad03fc48a4772d109cd6705ecb2bbe00f19d5819',
+  'v8_revision': 'fa1127207863b148988f8e6a4c9517379889aafe',
   # 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.
@@ -60,7 +60,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': 'f41f0332bfb9dfbf09253bbf10f3b46e820a4f8e',
+  'swiftshader_revision': '399a298b449e9f9fff72170caf06ab2214172683',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -72,7 +72,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
-  'boringssl_revision': 'd91e1efd835f84b2b59467ae78ace3b516730344',
+  'boringssl_revision': 'f6584e7a5232463dab271529f65f50131ae2202a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '93941b45f0e4d47db31547f735f27375bf6b7da4',
+  'catapult_revision': '1ffc3ed0526747eded946b2970a50046603b9272',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/WATCHLISTS b/WATCHLISTS
index 73ee4f41..769ae730 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1611,6 +1611,7 @@
     'accelerator_table': ['derat+watch@chromium.org',
                           'yusukes+watch@chromium.org'],
     'accessibility': ['aboxhall+watch@chromium.org',
+                      'aleventhal+watch@chromium.org',
                       'dmazzoni+watch@chromium.org',
                       'dougt+watch@chromium.org',
                       'dtseng+watch@chromium.org',
diff --git a/base/task_scheduler/scheduler_worker.cc b/base/task_scheduler/scheduler_worker.cc
index 174446f..07353443 100644
--- a/base/task_scheduler/scheduler_worker.cc
+++ b/base/task_scheduler/scheduler_worker.cc
@@ -203,9 +203,11 @@
     ThreadPriority priority_hint,
     std::unique_ptr<Delegate> delegate,
     TaskTracker* task_tracker,
+    const SchedulerLock* predecessor_lock,
     SchedulerBackwardCompatibility backward_compatibility,
     InitialState initial_state)
-    : priority_hint_(priority_hint),
+    : thread_lock_(predecessor_lock),
+      priority_hint_(priority_hint),
       delegate_(std::move(delegate)),
       task_tracker_(task_tracker),
 #if defined(OS_WIN)
diff --git a/base/task_scheduler/scheduler_worker.h b/base/task_scheduler/scheduler_worker.h
index d6330a5..62462c6 100644
--- a/base/task_scheduler/scheduler_worker.h
+++ b/base/task_scheduler/scheduler_worker.h
@@ -102,13 +102,16 @@
   // before Start() is called. |priority_hint| is the preferred thread priority;
   // the actual thread priority depends on shutdown state and platform
   // capabilities. |task_tracker| is used to handle shutdown behavior of Tasks.
-  // |backward_compatibility| indicates whether backward compatibility is
-  // enabled. |initial_state| determines whether the thread is created in
-  // Start() or in the first WakeUp() after Start(). Either JoinForTesting() or
-  // Cleanup() must be called before releasing the last external reference.
+  // |predecessor_lock| is a lock that is allowed to be held when calling
+  // methods on this SchedulerWorker. |backward_compatibility| indicates
+  // whether backward compatibility is enabled. |initial_state| determines
+  // whether the thread is created in Start() or in the first WakeUp() after
+  // Start(). Either JoinForTesting() or Cleanup() must be called before
+  // releasing the last external reference.
   SchedulerWorker(ThreadPriority priority_hint,
                   std::unique_ptr<Delegate> delegate,
                   TaskTracker* task_tracker,
+                  const SchedulerLock* predecessor_lock = nullptr,
                   SchedulerBackwardCompatibility backward_compatibility =
                       SchedulerBackwardCompatibility::DISABLED,
                   InitialState initial_state = InitialState::ALIVE);
diff --git a/base/task_scheduler/scheduler_worker_pool_impl.cc b/base/task_scheduler/scheduler_worker_pool_impl.cc
index 2ac4d28..8fe2a9ba 100644
--- a/base/task_scheduler/scheduler_worker_pool_impl.cc
+++ b/base/task_scheduler/scheduler_worker_pool_impl.cc
@@ -258,7 +258,8 @@
     for (int index = params.max_threads() - 1; index >= 0; --index) {
       workers_[index] = make_scoped_refptr(new SchedulerWorker(
           priority_hint_, MakeUnique<SchedulerWorkerDelegateImpl>(this, index),
-          task_tracker_, params.backward_compatibility(),
+          task_tracker_, &idle_workers_stack_lock_,
+          params.backward_compatibility(),
           index < num_alive_workers ? SchedulerWorker::InitialState::ALIVE
                                     : SchedulerWorker::InitialState::DETACHED));
 
@@ -271,14 +272,20 @@
 #if DCHECK_IS_ON()
     workers_created_.Set();
 #endif
+
+    // Start all workers. CHECK that the first worker can be started (assume
+    // that failure means that threads can't be created on this machine). Note
+    // that the workers must be started before the idle_workers_stack_lock_ is
+    // released, otherwise WakeUpOneWorker() could WakeUp() a worker before it's
+    // started (after the lock's released, but before it's started).
+    for (size_t index = 0; index < workers_.size(); ++index) {
+      const bool start_success = workers_[index]->Start();
+      CHECK(start_success || index > 0);
+    }
   }
 
-  // Start all workers. CHECK that the first worker can be started (assume that
-  // failure means that threads can't be created on this machine). Wake up one
-  // worker for each wake up that occurred before Start().
+  // Wake up one worker for each wake up that occurred before Start().
   for (size_t index = 0; index < workers_.size(); ++index) {
-    const bool start_success = workers_[index]->Start();
-    CHECK(start_success || index > 0);
     if (static_cast<int>(index) < num_wake_ups_before_start_)
       workers_[index]->WakeUp();
   }
diff --git a/base/task_scheduler/scheduler_worker_unittest.cc b/base/task_scheduler/scheduler_worker_unittest.cc
index 5d218a7..ab5982fb2 100644
--- a/base/task_scheduler/scheduler_worker_unittest.cc
+++ b/base/task_scheduler/scheduler_worker_unittest.cc
@@ -764,7 +764,7 @@
   scoped_refptr<ControllableDetachDelegate::Controls> controls =
       delegate->controls();
   auto worker = make_scoped_refptr(new SchedulerWorker(
-      ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker,
+      ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, nullptr,
       SchedulerBackwardCompatibility::DISABLED,
       SchedulerWorker::InitialState::DETACHED));
   worker->Start();
@@ -864,7 +864,7 @@
 
   // Create a DETACHED thread.
   auto worker = make_scoped_refptr(new SchedulerWorker(
-      ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker,
+      ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker, nullptr,
       SchedulerBackwardCompatibility::DISABLED,
       SchedulerWorker::InitialState::DETACHED));
   worker->Start();
@@ -923,7 +923,7 @@
   // Create a worker with backward compatibility ENABLED. Wake it up and wait
   // until GetWork() returns.
   auto worker = make_scoped_refptr(new SchedulerWorker(
-      ThreadPriority::NORMAL, std::move(delegate), &task_tracker,
+      ThreadPriority::NORMAL, std::move(delegate), &task_tracker, nullptr,
       SchedulerBackwardCompatibility::INIT_COM_STA));
   worker->Start();
   worker->WakeUp();
@@ -944,7 +944,7 @@
   // Create a worker with backward compatibility DISABLED. Wake it up and wait
   // until GetWork() returns.
   auto worker = make_scoped_refptr(new SchedulerWorker(
-      ThreadPriority::NORMAL, std::move(delegate), &task_tracker,
+      ThreadPriority::NORMAL, std::move(delegate), &task_tracker, nullptr,
       SchedulerBackwardCompatibility::DISABLED));
   worker->Start();
   worker->WakeUp();
diff --git a/base/trace_event/memory_infra_background_whitelist.cc b/base/trace_event/memory_infra_background_whitelist.cc
index 69a4e50..a6685f92 100644
--- a/base/trace_event/memory_infra_background_whitelist.cc
+++ b/base/trace_event/memory_infra_background_whitelist.cc
@@ -28,6 +28,7 @@
     "LeveldbValueStore",
     "Malloc",
     "MemoryCache",
+    "MojoHandleTable",
     "PartitionAlloc",
     "ProcessMemoryMetrics",
     "Skia",
@@ -68,6 +69,14 @@
     "malloc",
     "malloc/allocated_objects",
     "malloc/metadata_fragmentation_caches",
+    "mojo",
+    "mojo/data_pipe_consumer",
+    "mojo/data_pipe_producer",
+    "mojo/message_pipe",
+    "mojo/platform_handle",
+    "mojo/shared_buffer",
+    "mojo/unknown",
+    "mojo/watcher",
     "net/http_network_session_0x?",
     "net/http_network_session_0x?/quic_stream_factory",
     "net/http_network_session_0x?/socket_pool",
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 0e5badd..0ebbb7b 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -290,8 +290,10 @@
   if (scrollable_ == scrollable)
     return;
   scrollable_ = scrollable;
-  if (scrollable)
-    layer_tree_impl()->RegisterScrollLayer(this);
+  if (scrollable && layer_tree_impl()->settings().scrollbar_animator ==
+                        LayerTreeSettings::AURA_OVERLAY) {
+    set_needs_show_scrollbars(true);
+  }
 }
 
 std::unique_ptr<LayerImpl> LayerImpl::CreateLayerImpl(
diff --git a/cc/layers/surface_layer_impl.cc b/cc/layers/surface_layer_impl.cc
index 35e8996..8b23db0 100644
--- a/cc/layers/surface_layer_impl.cc
+++ b/cc/layers/surface_layer_impl.cc
@@ -61,28 +61,30 @@
 void SurfaceLayerImpl::AppendQuads(RenderPass* render_pass,
                                    AppendQuadsData* append_quads_data) {
   AppendRainbowDebugBorder(render_pass);
+  if (!primary_surface_info_.is_valid())
+    return;
+
   SharedQuadState* common_shared_quad_state = nullptr;
   auto* primary =
       CreateSurfaceDrawQuad(render_pass, SurfaceDrawQuadType::PRIMARY,
                             primary_surface_info_, &common_shared_quad_state);
   // Emitting a fallback SurfaceDrawQuad is unnecessary if the primary and
   // fallback surface Ids match.
-  bool needs_fallback =
-      fallback_surface_info_.is_valid() &&
-      (fallback_surface_info_.id() != primary_surface_info_.id());
-  if (primary && needs_fallback) {
+  if (primary && fallback_surface_info_.id() != primary_surface_info_.id()) {
     // Add the primary surface ID as a dependency.
     append_quads_data->activation_dependencies.push_back(
         primary_surface_info_.id());
-    // We can use the same SharedQuadState as the primary SurfaceDrawQuad if
-    // we don't need a different transform on the fallback.
-    bool use_common_shared_quad_state =
-        !stretch_content_to_fill_bounds_ &&
-        primary_surface_info_.device_scale_factor() ==
-            fallback_surface_info_.device_scale_factor();
-    primary->fallback_quad = CreateSurfaceDrawQuad(
-        render_pass, SurfaceDrawQuadType::FALLBACK, fallback_surface_info_,
-        use_common_shared_quad_state ? &common_shared_quad_state : nullptr);
+    if (fallback_surface_info_.is_valid()) {
+      // We can use the same SharedQuadState as the primary SurfaceDrawQuad if
+      // we don't need a different transform on the fallback.
+      bool use_common_shared_quad_state =
+          !stretch_content_to_fill_bounds_ &&
+          primary_surface_info_.device_scale_factor() ==
+              fallback_surface_info_.device_scale_factor();
+      primary->fallback_quad = CreateSurfaceDrawQuad(
+          render_pass, SurfaceDrawQuadType::FALLBACK, fallback_surface_info_,
+          use_common_shared_quad_state ? &common_shared_quad_state : nullptr);
+    }
   }
 }
 
@@ -91,8 +93,7 @@
     SurfaceDrawQuadType surface_draw_quad_type,
     const SurfaceInfo& surface_info,
     SharedQuadState** common_shared_quad_state) {
-  if (!surface_info.is_valid())
-    return nullptr;
+  DCHECK(surface_info.is_valid());
 
   gfx::Rect quad_rect(surface_info.size_in_pixels());
   gfx::Rect visible_quad_rect =
diff --git a/cc/layers/surface_layer_impl_unittest.cc b/cc/layers/surface_layer_impl_unittest.cc
index 8aa8f8f..f39326d 100644
--- a/cc/layers/surface_layer_impl_unittest.cc
+++ b/cc/layers/surface_layer_impl_unittest.cc
@@ -253,6 +253,18 @@
                 UnorderedElementsAre(surface_id1));
   }
 
+  // Update the fallback to an invalid SurfaceInfo. The
+  // |activation_dependencies| should still contain the primary SurfaceInfo.
+  {
+    AppendQuadsData data;
+    surface_layer_impl->SetFallbackSurfaceInfo(SurfaceInfo());
+    surface_layer_impl->AppendQuads(render_pass.get(), &data);
+    // The primary SurfaceInfo should not be added to
+    // activation_dependencies.
+    EXPECT_THAT(data.activation_dependencies,
+                UnorderedElementsAre(surface_id1));
+  }
+
   // Update the fallback SurfaceInfo and re-emit DrawQuads.
   {
     AppendQuadsData data;
@@ -263,7 +275,7 @@
                 UnorderedElementsAre(surface_id1));
   }
 
-  ASSERT_EQ(4u, render_pass->quad_list.size());
+  ASSERT_EQ(5u, render_pass->quad_list.size());
   const SurfaceDrawQuad* surface_draw_quad1 =
       SurfaceDrawQuad::MaterialCast(render_pass->quad_list.ElementAt(0));
   ASSERT_TRUE(surface_draw_quad1);
@@ -276,6 +288,9 @@
   const SurfaceDrawQuad* surface_draw_quad4 =
       SurfaceDrawQuad::MaterialCast(render_pass->quad_list.ElementAt(3));
   ASSERT_TRUE(surface_draw_quad4);
+  const SurfaceDrawQuad* surface_draw_quad5 =
+      SurfaceDrawQuad::MaterialCast(render_pass->quad_list.ElementAt(4));
+  ASSERT_TRUE(surface_draw_quad5);
 
   EXPECT_EQ(SurfaceDrawQuadType::PRIMARY,
             surface_draw_quad1->surface_draw_quad_type);
@@ -292,14 +307,19 @@
   EXPECT_EQ(SurfaceDrawQuadType::PRIMARY,
             surface_draw_quad3->surface_draw_quad_type);
   EXPECT_EQ(surface_id1, surface_draw_quad3->surface_id);
-  EXPECT_EQ(surface_draw_quad4, surface_draw_quad3->fallback_quad);
-  EXPECT_EQ(SurfaceDrawQuadType::FALLBACK,
+  EXPECT_EQ(nullptr, surface_draw_quad3->fallback_quad);
+
+  EXPECT_EQ(SurfaceDrawQuadType::PRIMARY,
             surface_draw_quad4->surface_draw_quad_type);
-  EXPECT_EQ(surface_id2, surface_draw_quad4->surface_id);
+  EXPECT_EQ(surface_id1, surface_draw_quad4->surface_id);
+  EXPECT_EQ(surface_draw_quad5, surface_draw_quad4->fallback_quad);
+  EXPECT_EQ(SurfaceDrawQuadType::FALLBACK,
+            surface_draw_quad5->surface_draw_quad_type);
+  EXPECT_EQ(surface_id2, surface_draw_quad5->surface_id);
   // If the device scale factor of the primary and fallback are the same then
   // they share a SharedQuadState.
-  EXPECT_EQ(surface_draw_quad3->shared_quad_state,
-            surface_draw_quad4->shared_quad_state);
+  EXPECT_EQ(surface_draw_quad4->shared_quad_state,
+            surface_draw_quad5->shared_quad_state);
 }
 
 // This test verifies that one SurfaceDrawQuad is emitted if a
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 73520be..435cc8d 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2191,6 +2191,17 @@
   if (visible_) {
     // TODO(crbug.com/469175): Replace with RequiresHighResToDraw.
     SetRequiresHighResToDraw();
+    // Prior CompositorFrame may have been discarded and thus we need to ensure
+    // that we submit a new one, even if there are no tiles. Therefore, force a
+    // full viewport redraw. However, this is unnecessary when we become visible
+    // for the first time (before the first commit) as there is no prior
+    // CompositorFrame to replace. We can safely use |!active_tree_->
+    // LayerListIsEmpty()| as a proxy for this, because we wouldn't be able to
+    // draw anything even if this is not the first time we become visible.
+    if (!active_tree_->LayerListIsEmpty()) {
+      SetFullViewportDamage();
+      SetNeedsRedraw();
+    }
   } else {
     EvictAllUIResources();
     // Call PrepareTiles to evict tiles when we become invisible.
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index ed85c60c..22661bbd 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -8785,12 +8785,36 @@
   }
 }
 
-TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
+namespace {
+void ExpectFullDamageAndDraw(LayerTreeHostImpl* host_impl) {
+  gfx::Rect full_frame_damage(host_impl->DeviceViewport().size());
+  TestFrameData frame;
+  EXPECT_EQ(DRAW_SUCCESS, host_impl->PrepareToDraw(&frame));
+  ASSERT_EQ(1u, frame.render_passes.size());
+  const RenderPass* root_render_pass = frame.render_passes.back().get();
+  EXPECT_EQ(full_frame_damage, root_render_pass->damage_rect);
+  EXPECT_TRUE(host_impl->DrawLayers(&frame));
+  host_impl->DidDrawAllLayers(frame);
+}
+}  // namespace
+
+TEST_F(LayerTreeHostImplTestDrawAndTestDamage,
+       RequireHighResAndRedrawWhenVisible) {
   ASSERT_TRUE(host_impl_->active_tree());
 
+  std::unique_ptr<SolidColorLayerImpl> root =
+      SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
+  root->SetBackgroundColor(SK_ColorRED);
+  SetupRootLayerImpl(std::move(root));
+
+  host_impl_->active_tree()->BuildPropertyTreesForTesting();
+
   // RequiresHighResToDraw is set when new output surface is used.
   EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
 
+  // Expect full frame damage for first frame.
+  EXPECT_SCOPED(ExpectFullDamageAndDraw(host_impl_.get()));
+
   host_impl_->ResetRequiresHighResToDraw();
 
   host_impl_->SetVisible(false);
@@ -8803,8 +8827,12 @@
   host_impl_->ResetRequiresHighResToDraw();
 
   EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
+  did_request_redraw_ = false;
   host_impl_->SetVisible(true);
   EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
+  // Expect redraw and full frame damage when becoming visible.
+  EXPECT_TRUE(did_request_redraw_);
+  EXPECT_SCOPED(ExpectFullDamageAndDraw(host_impl_.get()));
 }
 
 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 2a980f8..565285d 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -1747,14 +1747,6 @@
   return scrollbars;
 }
 
-// TODO(pdr): This function no longer registers the scroll layer. Remove this by
-// inlining it into the only callsite.
-void LayerTreeImpl::RegisterScrollLayer(LayerImpl* layer) {
-  DCHECK(layer->scrollable());
-  if (settings().scrollbar_animator == LayerTreeSettings::AURA_OVERLAY)
-    layer->set_needs_show_scrollbars(true);
-}
-
 static bool PointHitsRect(
     const gfx::PointF& screen_space_point,
     const gfx::Transform& local_space_to_screen_space_transform,
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index 5209cbf..dc40268 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -461,8 +461,6 @@
   void UnregisterScrollbar(ScrollbarLayerImplBase* scrollbar_layer);
   ScrollbarSet ScrollbarsFor(ElementId scroll_element_id) const;
 
-  void RegisterScrollLayer(LayerImpl* layer);
-
   LayerImpl* FindFirstScrollingLayerOrDrawnScrollbarThatIsHitByPoint(
       const gfx::PointF& screen_space_point);
 
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index 993571c..7d3936d8 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -135,6 +135,11 @@
       } else {
         deps = []
       }
+      if (defined(invoker.data)) {
+        data = invoker.data
+      } else {
+        data = []
+      }
 
       if (!is_win || is_clang) {
         # Normally, we need to pass specific flags to the linker to
@@ -157,9 +162,7 @@
         "//printing/features",
       ]
 
-      data = [
-        "$root_out_dir/resources.pak",
-      ]
+      data += [ "$root_out_dir/resources.pak" ]
       if (is_linux || is_win) {
         data += [
           "$root_out_dir/chrome_100_percent.pak",
@@ -336,6 +339,9 @@
       deps = [
         "//chrome/app/mash:chrome_test_catalog",
       ]
+      data = [
+        "$root_out_dir/chrome_200_percent.pak",
+      ]
       if (!is_win && use_aura) {
         sources += [ "app/chrome_test_exe_main_aura.cc" ]
       }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentApp.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentApp.java
index ad5ba250..6b769b43 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentApp.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentApp.java
@@ -129,8 +129,13 @@
 
     @Override
     public boolean supportsMethodsAndData(Map<String, PaymentMethodData> methodDataMap) {
-        assert methodDataMap != null;
+        return merchantSupportsAutofillPaymentInstruments(methodDataMap);
+    }
 
+    /** @return True if the merchant methodDataMap supports autofill payment instruments. */
+    public static boolean merchantSupportsAutofillPaymentInstruments(
+            Map<String, PaymentMethodData> methodDataMap) {
+        assert methodDataMap != null;
         PaymentMethodData basicCardData = methodDataMap.get(BASIC_CARD_METHOD_NAME);
         if (basicCardData != null) {
             Set<String> basicCardNetworks = convertBasicCardToNetworks(basicCardData);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
index 0fa12b3..c8e90d9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -471,6 +471,9 @@
         }
         mId = details.id;
 
+        // Checks whether the merchant supports autofill payment instrument before show is called.
+        mMerchantSupportsAutofillPaymentInstruments =
+                AutofillPaymentApp.merchantSupportsAutofillPaymentInstruments(mMethodData);
         PaymentAppFactory.getInstance().create(mWebContents,
                 Collections.unmodifiableSet(mMethodData.keySet()), this /* callback */);
 
@@ -700,7 +703,6 @@
                 mPendingApps.remove(app);
             } else {
                 mArePaymentMethodsSupported = true;
-                mMerchantSupportsAutofillPaymentInstruments |= app instanceof AutofillPaymentApp;
                 queryApps.put(app, appMethods);
             }
         }
@@ -714,9 +716,6 @@
 
         if (disconnectIfNoPaymentMethodsSupported()) return;
 
-        // Query instruments after mMerchantSupportsAutofillPaymentInstruments has been initialized,
-        // so a fast response from a non-autofill payment app at the front of the app list does not
-        // cause NOT_SUPPORTED payment rejection.
         for (Map.Entry<PaymentApp, Map<String, PaymentMethodData>> q : queryApps.entrySet()) {
             q.getKey().getInstruments(q.getValue(), mTopLevelOrigin, mPaymentRequestOrigin,
                     mCertificateChain, mRawTotal, this);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java
index 55c6f70..8570bc39 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java
@@ -375,14 +375,6 @@
     }
 
     @Override
-    public void updateButtonVisibility() {
-        super.updateButtonVisibility();
-        if (!mUseToolbarHandle) {
-            mExpandButton.setVisibility(urlHasFocus() ? INVISIBLE : VISIBLE);
-        }
-    }
-
-    @Override
     protected boolean isChildLeft(View child) {
         return (child == mNewTabButton || child == mExpandButton) ^ LocalizationUtils.isLayoutRtl();
     }
diff --git a/chrome/app/OWNERS b/chrome/app/OWNERS
index 8b8ad1a..0589fa2 100644
--- a/chrome/app/OWNERS
+++ b/chrome/app/OWNERS
@@ -25,4 +25,6 @@
 per-file chrome_crash_reporter_client*=ananta@chromium.org
 per-file chrome_crash_reporter_client*=scottmg@chromium.org
 
+per-file *.plist=file://chrome/browser/ui/cocoa/OWNERS
+
 # COMPONENT: Internals>PlatformIntegration
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 3e72025c..8ce2826 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3008,6 +3008,11 @@
      flag_descriptions::kOmniboxUIVerticalLayoutDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(omnibox::kUIExperimentVerticalLayout)},
 
+    {"omnibox-ui-narrow-dropdown",
+     flag_descriptions::kOmniboxUINarrowDropdownName,
+     flag_descriptions::kOmniboxUINarrowDropdownDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(omnibox::kUIExperimentNarrowDropdown)},
+
     {"omnibox-ui-vertical-margin",
      flag_descriptions::kOmniboxUIVerticalMarginName,
      flag_descriptions::kOmniboxUIVerticalMarginDescription, kOsDesktop,
@@ -3065,6 +3070,9 @@
      flag_descriptions::kEnablePictureInPictureDescription, kOsDesktop,
      SINGLE_VALUE_TYPE(switches::kEnablePictureInPicture)},
 #endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
+    {"browser-side-navigation", flag_descriptions::kBrowserSideNavigationName,
+     flag_descriptions::kBrowserSideNavigationDescription, kOsAll,
+     FEATURE_VALUE_TYPE(features::kBrowserSideNavigation)},
 
     // NOTE: Adding new command-line switches requires adding corresponding
     // entries to enum "LoginCustomFlags" in histograms/enums.xml. See note in
diff --git a/chrome/browser/download/download_resource_throttle.cc b/chrome/browser/download/download_resource_throttle.cc
index 5b294249..37e9f97 100644
--- a/chrome/browser/download/download_resource_throttle.cc
+++ b/chrome/browser/download/download_resource_throttle.cc
@@ -51,9 +51,11 @@
     std::unique_ptr<DownloadResourceThrottle::DownloadRequestInfo> info) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 #if defined(OS_ANDROID)
+  const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter =
+      info->web_contents_getter;
   DownloadControllerBase::Get()->AcquireFileAccessPermission(
-      info->web_contents_getter, base::Bind(&OnAcquireFileAccessPermissionDone,
-                                            base::Passed(std::move(info))));
+      web_contents_getter, base::Bind(&OnAcquireFileAccessPermissionDone,
+                                      base::Passed(std::move(info))));
 #else
   CanDownload(std::move(info));
 #endif
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index 1764a87..1c21a59c 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -935,6 +935,8 @@
       "api/enterprise_platform_keys/enterprise_platform_keys_api.h",
       "api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc",
       "api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h",
+      "api/file_system/consent_provider.cc",
+      "api/file_system/consent_provider.h",
       "api/file_system/request_file_system_notification.cc",
       "api/file_system/request_file_system_notification.h",
       "api/input_ime/input_ime_api.cc",
diff --git a/chrome/browser/extensions/api/file_system/consent_provider.cc b/chrome/browser/extensions/api/file_system/consent_provider.cc
new file mode 100644
index 0000000..3f7dece
--- /dev/null
+++ b/chrome/browser/extensions/api/file_system/consent_provider.cc
@@ -0,0 +1,222 @@
+// Copyright 2017 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 "chrome/browser/extensions/api/file_system/consent_provider.h"
+
+#include <memory>
+#include <string>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
+#include "chrome/browser/chromeos/file_manager/app_id.h"
+#include "chrome/browser/chromeos/file_manager/volume_manager.h"
+#include "chrome/browser/extensions/api/file_system/request_file_system_notification.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/views/extensions/request_file_system_dialog_view.h"
+#include "chrome/common/extensions/api/file_system.h"
+#include "components/user_manager/user_manager.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "extensions/browser/app_window/app_window.h"
+#include "extensions/browser/app_window/app_window_registry.h"
+#include "extensions/common/manifest_handlers/kiosk_mode_info.h"
+
+namespace extensions {
+
+namespace {
+
+// List of whitelisted component apps and extensions by their ids for
+// chrome.fileSystem.requestFileSystem.
+const char* const kRequestFileSystemComponentWhitelist[] = {
+    file_manager::kFileManagerAppId,
+    file_manager::kVideoPlayerAppId,
+    file_manager::kGalleryAppId,
+    file_manager::kAudioPlayerAppId,
+    file_manager::kImageLoaderExtensionId,
+    // TODO(mtomasz): Remove this extension id, and add it only for tests.
+    "pkplfbidichfdicaijlchgnapepdginl"  // Testing extensions.
+};
+
+ui::DialogButton g_auto_dialog_button_for_test = ui::DIALOG_BUTTON_NONE;
+
+// Gets a WebContents instance handle for a current window of a platform app
+// with |app_id|. If not found, then returns NULL.
+content::WebContents* GetWebContentsForAppId(Profile* profile,
+                                             const std::string& app_id) {
+  AppWindowRegistry* const registry = AppWindowRegistry::Get(profile);
+  DCHECK(registry);
+  AppWindow* const app_window = registry->GetCurrentAppWindowForApp(app_id);
+  return app_window ? app_window->web_contents() : nullptr;
+}
+
+// Converts the clicked button to a consent result and passes it via the
+// |callback|.
+void DialogResultToConsent(
+    const file_system_api::ConsentProvider::ConsentCallback& callback,
+    ui::DialogButton button) {
+  switch (button) {
+    case ui::DIALOG_BUTTON_NONE:
+      callback.Run(file_system_api::ConsentProvider::CONSENT_IMPOSSIBLE);
+      break;
+    case ui::DIALOG_BUTTON_OK:
+      callback.Run(file_system_api::ConsentProvider::CONSENT_GRANTED);
+      break;
+    case ui::DIALOG_BUTTON_CANCEL:
+      callback.Run(file_system_api::ConsentProvider::CONSENT_REJECTED);
+      break;
+  }
+}
+
+}  // namespace
+
+namespace file_system_api {
+
+ConsentProvider::ConsentProvider(DelegateInterface* delegate)
+    : delegate_(delegate) {
+  DCHECK(delegate_);
+}
+
+ConsentProvider::~ConsentProvider() {
+}
+
+void ConsentProvider::RequestConsent(
+    const Extension& extension,
+    const base::WeakPtr<file_manager::Volume>& volume,
+    bool writable,
+    const ConsentCallback& callback) {
+  DCHECK(IsGrantable(extension));
+
+  // If a whitelisted component, then no need to ask or inform the user.
+  if (extension.location() == Manifest::COMPONENT &&
+      delegate_->IsWhitelistedComponent(extension)) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::Bind(callback, CONSENT_GRANTED));
+    return;
+  }
+
+  // If auto-launched kiosk app, then no need to ask user either, but show the
+  // notification.
+  if (delegate_->IsAutoLaunched(extension)) {
+    delegate_->ShowNotification(extension, volume, writable);
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::Bind(callback, CONSENT_GRANTED));
+    return;
+  }
+
+  // If it's a kiosk app running in manual-launch kiosk session, then show
+  // the confirmation dialog.
+  if (KioskModeInfo::IsKioskOnly(&extension) &&
+      user_manager::UserManager::Get()->IsLoggedInAsKioskApp()) {
+    delegate_->ShowDialog(extension, volume, writable,
+                          base::Bind(&DialogResultToConsent, callback));
+    return;
+  }
+
+  NOTREACHED() << "Cannot request consent for non-grantable extensions.";
+}
+
+bool ConsentProvider::IsGrantable(const Extension& extension) {
+  const bool is_whitelisted_component =
+      delegate_->IsWhitelistedComponent(extension);
+
+  const bool is_running_in_kiosk_session =
+      KioskModeInfo::IsKioskOnly(&extension) &&
+      user_manager::UserManager::Get()->IsLoggedInAsKioskApp();
+
+  return is_whitelisted_component || is_running_in_kiosk_session;
+}
+
+ConsentProviderDelegate::ConsentProviderDelegate(Profile* profile,
+                                                 content::RenderFrameHost* host)
+    : profile_(profile), host_(host) {
+  DCHECK(profile_);
+}
+
+ConsentProviderDelegate::~ConsentProviderDelegate() {
+}
+
+// static
+void ConsentProviderDelegate::SetAutoDialogButtonForTest(
+    ui::DialogButton button) {
+  g_auto_dialog_button_for_test = button;
+}
+
+void ConsentProviderDelegate::ShowDialog(
+    const Extension& extension,
+    const base::WeakPtr<file_manager::Volume>& volume,
+    bool writable,
+    const file_system_api::ConsentProvider::ShowDialogCallback& callback) {
+  DCHECK(host_);
+  content::WebContents* web_contents = nullptr;
+
+  // Find an app window to host the dialog.
+  content::WebContents* const foreground_contents =
+      content::WebContents::FromRenderFrameHost(host_);
+  if (AppWindowRegistry::Get(profile_)->GetAppWindowForWebContents(
+          foreground_contents)) {
+    web_contents = foreground_contents;
+  }
+
+  // If there is no web contents handle, then the method is most probably
+  // executed from a background page.
+  if (!web_contents)
+    web_contents = GetWebContentsForAppId(profile_, extension.id());
+
+  if (!web_contents) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::Bind(callback, ui::DIALOG_BUTTON_NONE));
+    return;
+  }
+
+  // Short circuit the user consent dialog for tests. This is far from a pretty
+  // code design.
+  if (g_auto_dialog_button_for_test != ui::DIALOG_BUTTON_NONE) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::Bind(callback, g_auto_dialog_button_for_test /* result */));
+    return;
+  }
+
+  // If the volume is gone, then cancel the dialog.
+  if (!volume.get()) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::Bind(callback, ui::DIALOG_BUTTON_CANCEL));
+    return;
+  }
+
+  RequestFileSystemDialogView::ShowDialog(
+      web_contents, extension.name(),
+      (volume->volume_label().empty() ? volume->volume_id()
+                                      : volume->volume_label()),
+      writable, callback);
+}
+
+void ConsentProviderDelegate::ShowNotification(
+    const Extension& extension,
+    const base::WeakPtr<file_manager::Volume>& volume,
+    bool writable) {
+  RequestFileSystemNotification::ShowAutoGrantedNotification(
+      profile_, extension, volume, writable);
+}
+
+bool ConsentProviderDelegate::IsAutoLaunched(const Extension& extension) {
+  chromeos::KioskAppManager::App app_info;
+  return chromeos::KioskAppManager::Get()->GetApp(extension.id(), &app_info) &&
+         app_info.was_auto_launched_with_zero_delay;
+}
+
+bool ConsentProviderDelegate::IsWhitelistedComponent(
+    const Extension& extension) {
+  for (auto* whitelisted_id : kRequestFileSystemComponentWhitelist) {
+    if (extension.id().compare(whitelisted_id) == 0)
+      return true;
+  }
+  return false;
+}
+
+}  // namespace file_system_api
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/file_system/consent_provider.h b/chrome/browser/extensions/api/file_system/consent_provider.h
new file mode 100644
index 0000000..3a517b6f
--- /dev/null
+++ b/chrome/browser/extensions/api/file_system/consent_provider.h
@@ -0,0 +1,117 @@
+// Copyright 2017 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_BROWSER_EXTENSIONS_API_FILE_SYSTEM_CONSENT_PROVIDER_H_
+#define CHROME_BROWSER_EXTENSIONS_API_FILE_SYSTEM_CONSENT_PROVIDER_H_
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "build/build_config.h"
+#include "ui/base/ui_base_types.h"
+
+class Profile;
+
+namespace content {
+class RenderFrameHost;
+}  // content
+
+namespace file_manager {
+class Volume;
+}  // namespace file_manager
+
+namespace extensions {
+class Extension;
+class ScopedSkipRequestFileSystemDialog;
+
+namespace file_system_api {
+
+// Requests consent for the chrome.fileSystem.requestFileSystem() method.
+// Interaction with UI and environmental checks (kiosk mode, whitelist) are
+// provided by a delegate: ConsentProviderDelegate. For testing, it is
+// TestingConsentProviderDelegate.
+class ConsentProvider {
+ public:
+  enum Consent { CONSENT_GRANTED, CONSENT_REJECTED, CONSENT_IMPOSSIBLE };
+  typedef base::Callback<void(Consent)> ConsentCallback;
+  typedef base::Callback<void(ui::DialogButton)> ShowDialogCallback;
+
+  // Interface for delegating user interaction for granting permissions.
+  class DelegateInterface {
+   public:
+    // Shows a dialog for granting permissions.
+    virtual void ShowDialog(const Extension& extension,
+                            const base::WeakPtr<file_manager::Volume>& volume,
+                            bool writable,
+                            const ShowDialogCallback& callback) = 0;
+
+    // Shows a notification about permissions automatically granted access.
+    virtual void ShowNotification(
+        const Extension& extension,
+        const base::WeakPtr<file_manager::Volume>& volume,
+        bool writable) = 0;
+
+    // Checks if the extension was launched in auto-launch kiosk mode.
+    virtual bool IsAutoLaunched(const Extension& extension) = 0;
+
+    // Checks if the extension is a whitelisted component extension or app.
+    virtual bool IsWhitelistedComponent(const Extension& extension) = 0;
+  };
+
+  explicit ConsentProvider(DelegateInterface* delegate);
+  ~ConsentProvider();
+
+  // Requests consent for granting |writable| permissions to the |volume|
+  // volume by the |extension|. Must be called only if the extension is
+  // grantable, which can be checked with IsGrantable().
+  void RequestConsent(const Extension& extension,
+                      const base::WeakPtr<file_manager::Volume>& volume,
+                      bool writable,
+                      const ConsentCallback& callback);
+
+  // Checks whether the |extension| can be granted access.
+  bool IsGrantable(const Extension& extension);
+
+ private:
+  DelegateInterface* const delegate_;
+
+  DISALLOW_COPY_AND_ASSIGN(ConsentProvider);
+};
+
+// Handles interaction with user as well as environment checks (whitelists,
+// context of running extensions) for ConsentProvider.
+class ConsentProviderDelegate : public ConsentProvider::DelegateInterface {
+ public:
+  ConsentProviderDelegate(Profile* profile, content::RenderFrameHost* host);
+  ~ConsentProviderDelegate();
+
+ private:
+  friend ScopedSkipRequestFileSystemDialog;
+
+  // Sets a fake result for the user consent dialog. If ui::DIALOG_BUTTON_NONE
+  // then disabled.
+  static void SetAutoDialogButtonForTest(ui::DialogButton button);
+
+  // ConsentProvider::DelegateInterface overrides:
+  void ShowDialog(const Extension& extension,
+                  const base::WeakPtr<file_manager::Volume>& volume,
+                  bool writable,
+                  const file_system_api::ConsentProvider::ShowDialogCallback&
+                      callback) override;
+  void ShowNotification(const Extension& extension,
+                        const base::WeakPtr<file_manager::Volume>& volume,
+                        bool writable) override;
+  bool IsAutoLaunched(const Extension& extension) override;
+  bool IsWhitelistedComponent(const Extension& extension) override;
+
+  Profile* const profile_;
+  content::RenderFrameHost* const host_;
+
+  DISALLOW_COPY_AND_ASSIGN(ConsentProviderDelegate);
+};
+
+}  // namespace file_system_api
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_API_FILE_SYSTEM_CONSENT_PROVIDER_H_
diff --git a/chrome/browser/extensions/api/file_system/consent_provider_unittest.cc b/chrome/browser/extensions/api/file_system/consent_provider_unittest.cc
new file mode 100644
index 0000000..15769153
--- /dev/null
+++ b/chrome/browser/extensions/api/file_system/consent_provider_unittest.cc
@@ -0,0 +1,259 @@
+// Copyright 2017 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 "chrome/browser/extensions/api/file_system/consent_provider.h"
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/run_loop.h"
+#include "chrome/browser/chromeos/file_manager/volume_manager.h"
+#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
+#include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/user_manager/user.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/extension_builder.h"
+#include "extensions/common/manifest.h"
+#include "extensions/common/test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using extensions::file_system_api::ConsentProvider;
+using file_manager::Volume;
+
+namespace extensions {
+namespace {
+
+class TestingConsentProviderDelegate
+    : public ConsentProvider::DelegateInterface {
+ public:
+  TestingConsentProviderDelegate()
+      : show_dialog_counter_(0),
+        show_notification_counter_(0),
+        dialog_button_(ui::DIALOG_BUTTON_NONE),
+        is_auto_launched_(false) {}
+
+  ~TestingConsentProviderDelegate() {}
+
+  // Sets a fake dialog response.
+  void SetDialogButton(ui::DialogButton button) { dialog_button_ = button; }
+
+  // Sets a fake result of detection the auto launch kiosk mode.
+  void SetIsAutoLaunched(bool is_auto_launched) {
+    is_auto_launched_ = is_auto_launched;
+  }
+
+  // Sets a whitelisted components list with a single id.
+  void SetComponentWhitelist(const std::string& extension_id) {
+    whitelisted_component_id_ = extension_id;
+  }
+
+  int show_dialog_counter() const { return show_dialog_counter_; }
+  int show_notification_counter() const { return show_notification_counter_; }
+
+ private:
+  // ConsentProvider::DelegateInterface overrides:
+  void ShowDialog(
+      const extensions::Extension& extension,
+      const base::WeakPtr<Volume>& volume,
+      bool writable,
+      const ConsentProvider::ShowDialogCallback& callback) override {
+    ++show_dialog_counter_;
+    callback.Run(dialog_button_);
+  }
+
+  void ShowNotification(const extensions::Extension& extension,
+                        const base::WeakPtr<Volume>& volume,
+                        bool writable) override {
+    ++show_notification_counter_;
+  }
+
+  bool IsAutoLaunched(const extensions::Extension& extension) override {
+    return is_auto_launched_;
+  }
+
+  bool IsWhitelistedComponent(const extensions::Extension& extension) override {
+    return whitelisted_component_id_.compare(extension.id()) == 0;
+  }
+
+  int show_dialog_counter_;
+  int show_notification_counter_;
+  ui::DialogButton dialog_button_;
+  bool is_auto_launched_;
+  std::string whitelisted_component_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestingConsentProviderDelegate);
+};
+
+// Rewrites result of a consent request from |result| to |log|.
+void OnConsentReceived(ConsentProvider::Consent* log,
+                       const ConsentProvider::Consent result) {
+  *log = result;
+}
+
+}  // namespace
+
+class FileSystemApiConsentProviderTest : public testing::Test {
+ public:
+  FileSystemApiConsentProviderTest() {}
+
+  void SetUp() override {
+    testing_pref_service_.reset(new TestingPrefServiceSimple);
+    TestingBrowserProcess::GetGlobal()->SetLocalState(
+        testing_pref_service_.get());
+    user_manager_ = new chromeos::FakeChromeUserManager;
+    scoped_user_manager_enabler_.reset(
+        new chromeos::ScopedUserManagerEnabler(user_manager_));
+  }
+
+  void TearDown() override {
+    scoped_user_manager_enabler_.reset();
+    user_manager_ = nullptr;
+    testing_pref_service_.reset();
+    TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr);
+  }
+
+ protected:
+  base::WeakPtr<Volume> volume_;
+  std::unique_ptr<TestingPrefServiceSimple> testing_pref_service_;
+  chromeos::FakeChromeUserManager*
+      user_manager_;  // Owned by the scope enabler.
+  std::unique_ptr<chromeos::ScopedUserManagerEnabler>
+      scoped_user_manager_enabler_;
+  content::TestBrowserThreadBundle thread_bundle_;
+};
+
+TEST_F(FileSystemApiConsentProviderTest, ForNonKioskApps) {
+  // Component apps are not granted unless they are whitelisted.
+  {
+    scoped_refptr<Extension> component_extension(
+        test_util::BuildApp(
+            std::move(ExtensionBuilder().SetLocation(Manifest::COMPONENT)))
+            .Build());
+    TestingConsentProviderDelegate delegate;
+    ConsentProvider provider(&delegate);
+    EXPECT_FALSE(provider.IsGrantable(*component_extension));
+  }
+
+  // Whitelitsed component apps are instantly granted access without asking
+  // user.
+  {
+    scoped_refptr<Extension> whitelisted_component_extension(
+        test_util::BuildApp(
+            std::move(ExtensionBuilder().SetLocation(Manifest::COMPONENT)))
+            .Build());
+    TestingConsentProviderDelegate delegate;
+    delegate.SetComponentWhitelist(whitelisted_component_extension->id());
+    ConsentProvider provider(&delegate);
+    EXPECT_TRUE(provider.IsGrantable(*whitelisted_component_extension));
+
+    ConsentProvider::Consent result = ConsentProvider::CONSENT_IMPOSSIBLE;
+    provider.RequestConsent(*whitelisted_component_extension.get(), volume_,
+                            true /* writable */,
+                            base::Bind(&OnConsentReceived, &result));
+    base::RunLoop().RunUntilIdle();
+
+    EXPECT_EQ(0, delegate.show_dialog_counter());
+    EXPECT_EQ(0, delegate.show_notification_counter());
+    EXPECT_EQ(ConsentProvider::CONSENT_GRANTED, result);
+  }
+
+  // Non-component apps in non-kiosk mode will be rejected instantly, without
+  // asking for user consent.
+  {
+    scoped_refptr<Extension> non_component_extension(
+        test_util::CreateEmptyExtension());
+    TestingConsentProviderDelegate delegate;
+    ConsentProvider provider(&delegate);
+    EXPECT_FALSE(provider.IsGrantable(*non_component_extension));
+  }
+}
+
+TEST_F(FileSystemApiConsentProviderTest, ForKioskApps) {
+  // Non-component apps in auto-launch kiosk mode will be granted access
+  // instantly without asking for user consent, but with a notification.
+  {
+    scoped_refptr<Extension> auto_launch_kiosk_app(
+        test_util::BuildApp(ExtensionBuilder())
+            .MergeManifest(DictionaryBuilder()
+                               .SetBoolean("kiosk_enabled", true)
+                               .SetBoolean("kiosk_only", true)
+                               .Build())
+            .Build());
+    user_manager_->AddKioskAppUser(
+        AccountId::FromUserEmail(auto_launch_kiosk_app->id()));
+    user_manager_->LoginUser(
+        AccountId::FromUserEmail(auto_launch_kiosk_app->id()));
+
+    TestingConsentProviderDelegate delegate;
+    delegate.SetIsAutoLaunched(true);
+    ConsentProvider provider(&delegate);
+    EXPECT_TRUE(provider.IsGrantable(*auto_launch_kiosk_app));
+
+    ConsentProvider::Consent result = ConsentProvider::CONSENT_IMPOSSIBLE;
+    provider.RequestConsent(*auto_launch_kiosk_app.get(), volume_,
+                            true /* writable */,
+                            base::Bind(&OnConsentReceived, &result));
+    base::RunLoop().RunUntilIdle();
+
+    EXPECT_EQ(0, delegate.show_dialog_counter());
+    EXPECT_EQ(1, delegate.show_notification_counter());
+    EXPECT_EQ(ConsentProvider::CONSENT_GRANTED, result);
+  }
+
+  // Non-component apps in manual-launch kiosk mode will be granted access after
+  // receiving approval from the user.
+  scoped_refptr<Extension> manual_launch_kiosk_app(
+      test_util::BuildApp(ExtensionBuilder())
+          .MergeManifest(DictionaryBuilder()
+                             .SetBoolean("kiosk_enabled", true)
+                             .SetBoolean("kiosk_only", true)
+                             .Build())
+          .Build());
+  user_manager::User* const manual_kiosk_app_user =
+      user_manager_->AddKioskAppUser(
+          AccountId::FromUserEmail(manual_launch_kiosk_app->id()));
+  user_manager_->KioskAppLoggedIn(manual_kiosk_app_user);
+  {
+    TestingConsentProviderDelegate delegate;
+    delegate.SetDialogButton(ui::DIALOG_BUTTON_OK);
+    ConsentProvider provider(&delegate);
+    EXPECT_TRUE(provider.IsGrantable(*manual_launch_kiosk_app));
+
+    ConsentProvider::Consent result = ConsentProvider::CONSENT_IMPOSSIBLE;
+    provider.RequestConsent(*manual_launch_kiosk_app.get(), volume_,
+                            true /* writable */,
+                            base::Bind(&OnConsentReceived, &result));
+    base::RunLoop().RunUntilIdle();
+
+    EXPECT_EQ(1, delegate.show_dialog_counter());
+    EXPECT_EQ(0, delegate.show_notification_counter());
+    EXPECT_EQ(ConsentProvider::CONSENT_GRANTED, result);
+  }
+
+  // Non-component apps in manual-launch kiosk mode will be rejected access
+  // after rejecting by a user.
+  {
+    TestingConsentProviderDelegate delegate;
+    ConsentProvider provider(&delegate);
+    delegate.SetDialogButton(ui::DIALOG_BUTTON_CANCEL);
+    EXPECT_TRUE(provider.IsGrantable(*manual_launch_kiosk_app));
+
+    ConsentProvider::Consent result = ConsentProvider::CONSENT_IMPOSSIBLE;
+    provider.RequestConsent(*manual_launch_kiosk_app.get(), volume_,
+                            true /* writable */,
+                            base::Bind(&OnConsentReceived, &result));
+    base::RunLoop().RunUntilIdle();
+
+    EXPECT_EQ(1, delegate.show_dialog_counter());
+    EXPECT_EQ(0, delegate.show_notification_counter());
+    EXPECT_EQ(ConsentProvider::CONSENT_REJECTED, result);
+  }
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/file_system/file_system_api.cc b/chrome/browser/extensions/api/file_system/file_system_api.cc
index 3b0631b..cbd34827 100644
--- a/chrome/browser/extensions/api/file_system/file_system_api.cc
+++ b/chrome/browser/extensions/api/file_system/file_system_api.cc
@@ -15,7 +15,6 @@
 #include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
-#include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/path_service.h"
@@ -68,19 +67,11 @@
 
 #if defined(OS_CHROMEOS)
 #include "base/strings/string16.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
-#include "chrome/browser/chromeos/file_manager/app_id.h"
 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
-#include "chrome/browser/extensions/api/file_system/request_file_system_notification.h"
-#include "chrome/browser/ui/simple_message_box.h"
-#include "chrome/browser/ui/views/extensions/request_file_system_dialog_view.h"
-#include "components/user_manager/user_manager.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/constants.h"
-#include "extensions/common/manifest_handlers/kiosk_mode_info.h"
 #include "url/url_constants.h"
 #endif
 
@@ -110,18 +101,6 @@
 const char kSecurityError[] = "Security error.";
 const char kConsentImpossible[] =
     "Impossible to ask for user consent as there is no app window visible.";
-
-// List of whitelisted component apps and extensions by their ids for
-// chrome.fileSystem.requestFileSystem.
-const char* const kRequestFileSystemComponentWhitelist[] = {
-    file_manager::kFileManagerAppId,
-    file_manager::kVideoPlayerAppId,
-    file_manager::kGalleryAppId,
-    file_manager::kAudioPlayerAppId,
-    file_manager::kImageLoaderExtensionId,
-    // TODO(mtomasz): Remove this extension id, and add it only for tests.
-    "pkplfbidichfdicaijlchgnapepdginl"  // Testing extensions.
-};
 #endif
 
 namespace extensions {
@@ -138,10 +117,6 @@
 bool g_skip_directory_confirmation_for_test = false;
 bool g_allow_directory_access_for_test = false;
 
-#if defined(OS_CHROMEOS)
-ui::DialogButton g_auto_dialog_button_for_test = ui::DIALOG_BUTTON_NONE;
-#endif
-
 // Expand the mime-types and extensions provided in an AcceptOption, returning
 // them within the passed extension vector. Returns false if no valid types
 // were found.
@@ -247,16 +222,6 @@
 }
 
 #if defined(OS_CHROMEOS)
-// Gets a WebContents instance handle for a current window of a platform app
-// with |app_id|. If not found, then returns NULL.
-content::WebContents* GetWebContentsForAppId(Profile* profile,
-                                             const std::string& app_id) {
-  AppWindowRegistry* const registry = AppWindowRegistry::Get(profile);
-  DCHECK(registry);
-  AppWindow* const app_window = registry->GetCurrentAppWindowForApp(app_id);
-  return app_window ? app_window->web_contents() : nullptr;
-}
-
 // Fills a list of volumes mounted in the system.
 void FillVolumeList(Profile* profile,
                     std::vector<api::file_system::Volume>* result) {
@@ -273,24 +238,6 @@
     result->push_back(std::move(result_volume));
   }
 }
-
-// Converts the clicked button to a consent result and passes it via the
-// |callback|.
-void DialogResultToConsent(
-    const file_system_api::ConsentProvider::ConsentCallback& callback,
-    ui::DialogButton button) {
-  switch (button) {
-    case ui::DIALOG_BUTTON_NONE:
-      callback.Run(file_system_api::ConsentProvider::CONSENT_IMPOSSIBLE);
-      break;
-    case ui::DIALOG_BUTTON_OK:
-      callback.Run(file_system_api::ConsentProvider::CONSENT_GRANTED);
-      break;
-    case ui::DIALOG_BUTTON_CANCEL:
-      callback.Run(file_system_api::ConsentProvider::CONSENT_REJECTED);
-      break;
-  }
-}
 #endif
 
 }  // namespace
@@ -342,142 +289,6 @@
             api::file_system::OnVolumeListChanged::Create(event_args)));
   }
 }
-
-ConsentProvider::ConsentProvider(DelegateInterface* delegate)
-    : delegate_(delegate) {
-  DCHECK(delegate_);
-}
-
-ConsentProvider::~ConsentProvider() {
-}
-
-void ConsentProvider::RequestConsent(
-    const Extension& extension,
-    const base::WeakPtr<file_manager::Volume>& volume,
-    bool writable,
-    const ConsentCallback& callback) {
-  DCHECK(IsGrantable(extension));
-
-  // If a whitelisted component, then no need to ask or inform the user.
-  if (extension.location() == Manifest::COMPONENT &&
-      delegate_->IsWhitelistedComponent(extension)) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(callback, CONSENT_GRANTED));
-    return;
-  }
-
-  // If auto-launched kiosk app, then no need to ask user either, but show the
-  // notification.
-  if (delegate_->IsAutoLaunched(extension)) {
-    delegate_->ShowNotification(extension, volume, writable);
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(callback, CONSENT_GRANTED));
-    return;
-  }
-
-  // If it's a kiosk app running in manual-launch kiosk session, then show
-  // the confirmation dialog.
-  if (KioskModeInfo::IsKioskOnly(&extension) &&
-      user_manager::UserManager::Get()->IsLoggedInAsKioskApp()) {
-    delegate_->ShowDialog(extension, volume, writable,
-                          base::Bind(&DialogResultToConsent, callback));
-    return;
-  }
-
-  NOTREACHED() << "Cannot request consent for non-grantable extensions.";
-}
-
-bool ConsentProvider::IsGrantable(const Extension& extension) {
-  const bool is_whitelisted_component =
-      delegate_->IsWhitelistedComponent(extension);
-
-  const bool is_running_in_kiosk_session =
-      KioskModeInfo::IsKioskOnly(&extension) &&
-      user_manager::UserManager::Get()->IsLoggedInAsKioskApp();
-
-  return is_whitelisted_component || is_running_in_kiosk_session;
-}
-
-ConsentProviderDelegate::ConsentProviderDelegate(Profile* profile,
-                                                 content::RenderFrameHost* host)
-    : profile_(profile), host_(host) {
-  DCHECK(profile_);
-}
-
-ConsentProviderDelegate::~ConsentProviderDelegate() {
-}
-
-// static
-void ConsentProviderDelegate::SetAutoDialogButtonForTest(
-    ui::DialogButton button) {
-  g_auto_dialog_button_for_test = button;
-}
-
-void ConsentProviderDelegate::ShowDialog(
-    const Extension& extension,
-    const base::WeakPtr<file_manager::Volume>& volume,
-    bool writable,
-    const file_system_api::ConsentProvider::ShowDialogCallback& callback) {
-  DCHECK(host_);
-  content::WebContents* const foreground_contents =
-      GetWebContentsForRenderFrameHost(profile_, host_);
-  // If there is no web contents handle, then the method is most probably
-  // executed from a background page. Find an app window to host the dialog.
-  content::WebContents* const web_contents =
-      foreground_contents ? foreground_contents
-                          : GetWebContentsForAppId(profile_, extension.id());
-  if (!web_contents) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(callback, ui::DIALOG_BUTTON_NONE));
-    return;
-  }
-
-  // Short circuit the user consent dialog for tests. This is far from a pretty
-  // code design.
-  if (g_auto_dialog_button_for_test != ui::DIALOG_BUTTON_NONE) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::Bind(callback, g_auto_dialog_button_for_test /* result */));
-    return;
-  }
-
-  // If the volume is gone, then cancel the dialog.
-  if (!volume.get()) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(callback, ui::DIALOG_BUTTON_CANCEL));
-    return;
-  }
-
-  RequestFileSystemDialogView::ShowDialog(
-      web_contents, extension.name(),
-      (volume->volume_label().empty() ? volume->volume_id()
-                                      : volume->volume_label()),
-      writable, callback);
-}
-
-void ConsentProviderDelegate::ShowNotification(
-    const Extension& extension,
-    const base::WeakPtr<file_manager::Volume>& volume,
-    bool writable) {
-  RequestFileSystemNotification::ShowAutoGrantedNotification(
-      profile_, extension, volume, writable);
-}
-
-bool ConsentProviderDelegate::IsAutoLaunched(const Extension& extension) {
-  chromeos::KioskAppManager::App app_info;
-  return chromeos::KioskAppManager::Get()->GetApp(extension.id(), &app_info) &&
-         app_info.was_auto_launched_with_zero_delay;
-}
-
-bool ConsentProviderDelegate::IsWhitelistedComponent(
-    const Extension& extension) {
-  for (auto* whitelisted_id : kRequestFileSystemComponentWhitelist) {
-    if (extension.id().compare(whitelisted_id) == 0)
-      return true;
-  }
-  return false;
-}
-
 #endif
 
 }  // namespace file_system_api
diff --git a/chrome/browser/extensions/api/file_system/file_system_api.h b/chrome/browser/extensions/api/file_system/file_system_api.h
index 9825c23..f65f418 100644
--- a/chrome/browser/extensions/api/file_system/file_system_api.h
+++ b/chrome/browser/extensions/api/file_system/file_system_api.h
@@ -19,18 +19,14 @@
 #include "chrome/browser/extensions/chrome_extension_function_details.h"
 #include "chrome/common/extensions/api/file_system.h"
 #include "extensions/browser/extension_function.h"
-#include "ui/base/ui_base_types.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
 
 #if defined(OS_CHROMEOS)
-namespace file_manager {
-class Volume;
-}  // namespace file_manager
+#include "chrome/browser/extensions/api/file_system/consent_provider.h"
 #endif
 
 namespace extensions {
 class ExtensionPrefs;
-class ScopedSkipRequestFileSystemDialog;
 
 namespace file_system_api {
 
@@ -50,90 +46,6 @@
 // Dispatches an event about a mounted on unmounted volume in the system to
 // each extension which can request it.
 void DispatchVolumeListChangeEvent(Profile* profile);
-
-// Requests consent for the chrome.fileSystem.requestFileSystem() method.
-// Interaction with UI and environmental checks (kiosk mode, whitelist) are
-// provided by a delegate: ConsentProviderDelegate. For testing, it is
-// TestingConsentProviderDelegate.
-class ConsentProvider {
- public:
-  enum Consent { CONSENT_GRANTED, CONSENT_REJECTED, CONSENT_IMPOSSIBLE };
-  typedef base::Callback<void(Consent)> ConsentCallback;
-  typedef base::Callback<void(ui::DialogButton)> ShowDialogCallback;
-
-  // Interface for delegating user interaction for granting permissions.
-  class DelegateInterface {
-   public:
-    // Shows a dialog for granting permissions.
-    virtual void ShowDialog(const Extension& extension,
-                            const base::WeakPtr<file_manager::Volume>& volume,
-                            bool writable,
-                            const ShowDialogCallback& callback) = 0;
-
-    // Shows a notification about permissions automatically granted access.
-    virtual void ShowNotification(
-        const Extension& extension,
-        const base::WeakPtr<file_manager::Volume>& volume,
-        bool writable) = 0;
-
-    // Checks if the extension was launched in auto-launch kiosk mode.
-    virtual bool IsAutoLaunched(const Extension& extension) = 0;
-
-    // Checks if the extension is a whitelisted component extension or app.
-    virtual bool IsWhitelistedComponent(const Extension& extension) = 0;
-  };
-
-  explicit ConsentProvider(DelegateInterface* delegate);
-  ~ConsentProvider();
-
-  // Requests consent for granting |writable| permissions to the |volume|
-  // volume by the |extension|. Must be called only if the extension is
-  // grantable, which can be checked with IsGrantable().
-  void RequestConsent(const Extension& extension,
-                      const base::WeakPtr<file_manager::Volume>& volume,
-                      bool writable,
-                      const ConsentCallback& callback);
-
-  // Checks whether the |extension| can be granted access.
-  bool IsGrantable(const Extension& extension);
-
- private:
-  DelegateInterface* const delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(ConsentProvider);
-};
-
-// Handles interaction with user as well as environment checks (whitelists,
-// context of running extensions) for ConsentProvider.
-class ConsentProviderDelegate : public ConsentProvider::DelegateInterface {
- public:
-  ConsentProviderDelegate(Profile* profile, content::RenderFrameHost* host);
-  ~ConsentProviderDelegate();
-
- private:
-  friend ScopedSkipRequestFileSystemDialog;
-
-  // Sets a fake result for the user consent dialog. If ui::DIALOG_BUTTON_NONE
-  // then disabled.
-  static void SetAutoDialogButtonForTest(ui::DialogButton button);
-
-  // ConsentProvider::DelegateInterface overrides:
-  void ShowDialog(const Extension& extension,
-                  const base::WeakPtr<file_manager::Volume>& volume,
-                  bool writable,
-                  const file_system_api::ConsentProvider::ShowDialogCallback&
-                      callback) override;
-  void ShowNotification(const Extension& extension,
-                        const base::WeakPtr<file_manager::Volume>& volume,
-                        bool writable) override;
-  bool IsAutoLaunched(const Extension& extension) override;
-  bool IsWhitelistedComponent(const Extension& extension) override;
-
-  Profile* const profile_;
-  content::RenderFrameHost* const host_;
-
-  DISALLOW_COPY_AND_ASSIGN(ConsentProviderDelegate);
-};
 #endif
 
 }  // namespace file_system_api
diff --git a/chrome/browser/extensions/api/file_system/file_system_api_unittest.cc b/chrome/browser/extensions/api/file_system/file_system_api_unittest.cc
index f3ce3def..1b8de48 100644
--- a/chrome/browser/extensions/api/file_system/file_system_api_unittest.cc
+++ b/chrome/browser/extensions/api/file_system/file_system_api_unittest.cc
@@ -9,8 +9,6 @@
 #include <vector>
 
 #include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -18,31 +16,9 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
 
-#if defined(OS_CHROMEOS)
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/chromeos/file_manager/volume_manager.h"
-#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
-#include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
-#include "chrome/test/base/testing_browser_process.h"
-#include "components/prefs/testing_pref_service.h"
-#include "components/user_manager/user.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "extensions/common/extension.h"
-#include "extensions/common/extension_builder.h"
-#include "extensions/common/manifest.h"
-#include "extensions/common/test_util.h"
-#include "extensions/common/value_builder.h"
-#endif
-
 using extensions::FileSystemChooseEntryFunction;
 using extensions::api::file_system::AcceptOption;
 
-#if defined(OS_CHROMEOS)
-using extensions::file_system_api::ConsentProvider;
-using file_manager::Volume;
-#endif
-
 namespace extensions {
 namespace {
 
@@ -84,109 +60,8 @@
 #define ToStringType
 #endif
 
-#if defined(OS_CHROMEOS)
-class TestingConsentProviderDelegate
-    : public ConsentProvider::DelegateInterface {
- public:
-  TestingConsentProviderDelegate()
-      : show_dialog_counter_(0),
-        show_notification_counter_(0),
-        dialog_button_(ui::DIALOG_BUTTON_NONE),
-        is_auto_launched_(false) {}
-
-  ~TestingConsentProviderDelegate() {}
-
-  // Sets a fake dialog response.
-  void SetDialogButton(ui::DialogButton button) { dialog_button_ = button; }
-
-  // Sets a fake result of detection the auto launch kiosk mode.
-  void SetIsAutoLaunched(bool is_auto_launched) {
-    is_auto_launched_ = is_auto_launched;
-  }
-
-  // Sets a whitelisted components list with a single id.
-  void SetComponentWhitelist(const std::string& extension_id) {
-    whitelisted_component_id_ = extension_id;
-  }
-
-  int show_dialog_counter() const { return show_dialog_counter_; }
-  int show_notification_counter() const { return show_notification_counter_; }
-
- private:
-  // ConsentProvider::DelegateInterface overrides:
-  void ShowDialog(
-      const extensions::Extension& extension,
-      const base::WeakPtr<Volume>& volume,
-      bool writable,
-      const ConsentProvider::ShowDialogCallback& callback) override {
-    ++show_dialog_counter_;
-    callback.Run(dialog_button_);
-  }
-
-  void ShowNotification(const extensions::Extension& extension,
-                        const base::WeakPtr<Volume>& volume,
-                        bool writable) override {
-    ++show_notification_counter_;
-  }
-
-  bool IsAutoLaunched(const extensions::Extension& extension) override {
-    return is_auto_launched_;
-  }
-
-  bool IsWhitelistedComponent(const extensions::Extension& extension) override {
-    return whitelisted_component_id_.compare(extension.id()) == 0;
-  }
-
-  int show_dialog_counter_;
-  int show_notification_counter_;
-  ui::DialogButton dialog_button_;
-  bool is_auto_launched_;
-  std::string whitelisted_component_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestingConsentProviderDelegate);
-};
-
-// Rewrites result of a consent request from |result| to |log|.
-void OnConsentReceived(ConsentProvider::Consent* log,
-                       const ConsentProvider::Consent result) {
-  *log = result;
-}
-#endif
-
 }  // namespace
 
-#if defined(OS_CHROMEOS)
-class FileSystemApiConsentProviderTest : public testing::Test {
- public:
-  FileSystemApiConsentProviderTest() {}
-
-  void SetUp() override {
-    testing_pref_service_.reset(new TestingPrefServiceSimple);
-    TestingBrowserProcess::GetGlobal()->SetLocalState(
-        testing_pref_service_.get());
-    user_manager_ = new chromeos::FakeChromeUserManager;
-    scoped_user_manager_enabler_.reset(
-        new chromeos::ScopedUserManagerEnabler(user_manager_));
-  }
-
-  void TearDown() override {
-    scoped_user_manager_enabler_.reset();
-    user_manager_ = nullptr;
-    testing_pref_service_.reset();
-    TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr);
-  }
-
- protected:
-  base::WeakPtr<Volume> volume_;
-  std::unique_ptr<TestingPrefServiceSimple> testing_pref_service_;
-  chromeos::FakeChromeUserManager*
-      user_manager_;  // Owned by the scope enabler.
-  std::unique_ptr<chromeos::ScopedUserManagerEnabler>
-      scoped_user_manager_enabler_;
-  content::TestBrowserThreadBundle thread_bundle_;
-};
-#endif
-
 TEST(FileSystemApiUnitTest, FileSystemChooseEntryFunctionFileTypeInfoTest) {
   // AcceptsAllTypes is ignored when no other extensions are available.
   ui::SelectFileDialog::FileTypeInfo file_type_info;
@@ -312,134 +187,4 @@
 #endif
 }
 
-#if defined(OS_CHROMEOS)
-TEST_F(FileSystemApiConsentProviderTest, ForNonKioskApps) {
-  // Component apps are not granted unless they are whitelisted.
-  {
-    scoped_refptr<Extension> component_extension(
-        test_util::BuildApp(
-            std::move(ExtensionBuilder().SetLocation(Manifest::COMPONENT)))
-            .Build());
-    TestingConsentProviderDelegate delegate;
-    ConsentProvider provider(&delegate);
-    EXPECT_FALSE(provider.IsGrantable(*component_extension));
-  }
-
-  // Whitelitsed component apps are instantly granted access without asking
-  // user.
-  {
-    scoped_refptr<Extension> whitelisted_component_extension(
-        test_util::BuildApp(
-            std::move(ExtensionBuilder().SetLocation(Manifest::COMPONENT)))
-            .Build());
-    TestingConsentProviderDelegate delegate;
-    delegate.SetComponentWhitelist(whitelisted_component_extension->id());
-    ConsentProvider provider(&delegate);
-    EXPECT_TRUE(provider.IsGrantable(*whitelisted_component_extension));
-
-    ConsentProvider::Consent result = ConsentProvider::CONSENT_IMPOSSIBLE;
-    provider.RequestConsent(*whitelisted_component_extension.get(), volume_,
-                            true /* writable */,
-                            base::Bind(&OnConsentReceived, &result));
-    base::RunLoop().RunUntilIdle();
-
-    EXPECT_EQ(0, delegate.show_dialog_counter());
-    EXPECT_EQ(0, delegate.show_notification_counter());
-    EXPECT_EQ(ConsentProvider::CONSENT_GRANTED, result);
-  }
-
-  // Non-component apps in non-kiosk mode will be rejected instantly, without
-  // asking for user consent.
-  {
-    scoped_refptr<Extension> non_component_extension(
-        test_util::CreateEmptyExtension());
-    TestingConsentProviderDelegate delegate;
-    ConsentProvider provider(&delegate);
-    EXPECT_FALSE(provider.IsGrantable(*non_component_extension));
-  }
-}
-
-TEST_F(FileSystemApiConsentProviderTest, ForKioskApps) {
-  // Non-component apps in auto-launch kiosk mode will be granted access
-  // instantly without asking for user consent, but with a notification.
-  {
-    scoped_refptr<Extension> auto_launch_kiosk_app(
-        test_util::BuildApp(ExtensionBuilder())
-            .MergeManifest(DictionaryBuilder()
-                               .SetBoolean("kiosk_enabled", true)
-                               .SetBoolean("kiosk_only", true)
-                               .Build())
-            .Build());
-    user_manager_->AddKioskAppUser(
-        AccountId::FromUserEmail(auto_launch_kiosk_app->id()));
-    user_manager_->LoginUser(
-        AccountId::FromUserEmail(auto_launch_kiosk_app->id()));
-
-    TestingConsentProviderDelegate delegate;
-    delegate.SetIsAutoLaunched(true);
-    ConsentProvider provider(&delegate);
-    EXPECT_TRUE(provider.IsGrantable(*auto_launch_kiosk_app));
-
-    ConsentProvider::Consent result = ConsentProvider::CONSENT_IMPOSSIBLE;
-    provider.RequestConsent(*auto_launch_kiosk_app.get(), volume_,
-                            true /* writable */,
-                            base::Bind(&OnConsentReceived, &result));
-    base::RunLoop().RunUntilIdle();
-
-    EXPECT_EQ(0, delegate.show_dialog_counter());
-    EXPECT_EQ(1, delegate.show_notification_counter());
-    EXPECT_EQ(ConsentProvider::CONSENT_GRANTED, result);
-  }
-
-  // Non-component apps in manual-launch kiosk mode will be granted access after
-  // receiving approval from the user.
-  scoped_refptr<Extension> manual_launch_kiosk_app(
-      test_util::BuildApp(ExtensionBuilder())
-          .MergeManifest(DictionaryBuilder()
-                             .SetBoolean("kiosk_enabled", true)
-                             .SetBoolean("kiosk_only", true)
-                             .Build())
-          .Build());
-  user_manager::User* const manual_kiosk_app_user =
-      user_manager_->AddKioskAppUser(
-          AccountId::FromUserEmail(manual_launch_kiosk_app->id()));
-  user_manager_->KioskAppLoggedIn(manual_kiosk_app_user);
-  {
-    TestingConsentProviderDelegate delegate;
-    delegate.SetDialogButton(ui::DIALOG_BUTTON_OK);
-    ConsentProvider provider(&delegate);
-    EXPECT_TRUE(provider.IsGrantable(*manual_launch_kiosk_app));
-
-    ConsentProvider::Consent result = ConsentProvider::CONSENT_IMPOSSIBLE;
-    provider.RequestConsent(*manual_launch_kiosk_app.get(), volume_,
-                            true /* writable */,
-                            base::Bind(&OnConsentReceived, &result));
-    base::RunLoop().RunUntilIdle();
-
-    EXPECT_EQ(1, delegate.show_dialog_counter());
-    EXPECT_EQ(0, delegate.show_notification_counter());
-    EXPECT_EQ(ConsentProvider::CONSENT_GRANTED, result);
-  }
-
-  // Non-component apps in manual-launch kiosk mode will be rejected access
-  // after rejecting by a user.
-  {
-    TestingConsentProviderDelegate delegate;
-    ConsentProvider provider(&delegate);
-    delegate.SetDialogButton(ui::DIALOG_BUTTON_CANCEL);
-    EXPECT_TRUE(provider.IsGrantable(*manual_launch_kiosk_app));
-
-    ConsentProvider::Consent result = ConsentProvider::CONSENT_IMPOSSIBLE;
-    provider.RequestConsent(*manual_launch_kiosk_app.get(), volume_,
-                            true /* writable */,
-                            base::Bind(&OnConsentReceived, &result));
-    base::RunLoop().RunUntilIdle();
-
-    EXPECT_EQ(1, delegate.show_dialog_counter());
-    EXPECT_EQ(0, delegate.show_notification_counter());
-    EXPECT_EQ(ConsentProvider::CONSENT_REJECTED, result);
-  }
-}
-#endif
-
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc b/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc
index 180ed24..9e1a42db 100644
--- a/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc
+++ b/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/extensions/api/file_system/consent_provider.h"
 #include "chrome/browser/extensions/component_loader.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/extensions/api/file_system.h"
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index b396780d..848906f 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -6,6 +6,11 @@
 
 namespace flag_descriptions {
 
+const char kBrowserSideNavigationName[] = "Enable browser side navigation";
+
+const char kBrowserSideNavigationDescription[] =
+    "Enable browser side navigation (aka PlzNaviate).";
+
 //  Material Design version of chrome://bookmarks
 
 const char kEnableMaterialDesignBookmarksName[] =
@@ -3100,6 +3105,11 @@
     "Changes the maximum number of autocomplete matches displayed in the "
     "Omnibox UI.";
 
+const char kOmniboxUINarrowDropdownName[] = "Omnibox UI Narrow Dropdown";
+
+const char kOmniboxUINarrowDropdownDescription[] =
+    "Makes the suggestions dropdown width match the omnibox width.";
+
 const char kOmniboxUIVerticalLayoutName[] = "Omnibox UI Vertical Layout";
 
 const char kOmniboxUIVerticalLayoutDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 87430a03..42e9f39 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -60,6 +60,9 @@
 extern const char kBleAdvertisingInExtensionsName[];
 extern const char kBleAdvertisingInExtensionsDescription[];
 
+extern const char kBrowserSideNavigationName[];
+extern const char kBrowserSideNavigationDescription[];
+
 extern const char kBrowserTaskSchedulerName[];
 extern const char kBrowserTaskSchedulerDescription[];
 
@@ -498,6 +501,9 @@
 extern const char kOmniboxUIMaxAutocompleteMatchesName[];
 extern const char kOmniboxUIMaxAutocompleteMatchesDescription[];
 
+extern const char kOmniboxUINarrowDropdownName[];
+extern const char kOmniboxUINarrowDropdownDescription[];
+
 extern const char kOmniboxUIVerticalLayoutName[];
 extern const char kOmniboxUIVerticalLayoutDescription[];
 
diff --git a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
index ff1f2b5..ca5920bc 100644
--- a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
+++ b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
@@ -16,6 +16,9 @@
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/favicon/large_icon_service_factory.h"
+#include "chrome/browser/gcm/gcm_profile_service_factory.h"
+#include "chrome/browser/gcm/instance_id/instance_id_profile_service.h"
+#include "chrome/browser/gcm/instance_id/instance_id_profile_service_factory.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/suggestions/image_decoder_impl.h"
@@ -394,6 +397,10 @@
   DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance());
   DependsOn(ProfileSyncServiceFactory::GetInstance());
   DependsOn(SigninManagerFactory::GetInstance());
+#if defined(OS_ANDROID)
+  DependsOn(gcm::GCMProfileServiceFactory::GetInstance());
+  DependsOn(instance_id::InstanceIDProfileServiceFactory::GetInstance());
+#endif  // defined(OS_ANDROID)
 }
 
 ContentSuggestionsServiceFactory::~ContentSuggestionsServiceFactory() = default;
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index e4196af..ceb4642 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -79,6 +79,7 @@
 #include "components/gcm_driver/gcm_channel_status_syncer.h"
 #include "components/metrics/metrics_service.h"
 #include "components/network_time/network_time_tracker.h"
+#include "components/ntp_snippets/breaking_news/content_suggestions_gcm_app_handler.h"
 #include "components/ntp_snippets/breaking_news/subscription_manager.h"
 #include "components/ntp_snippets/content_suggestions_service.h"
 #include "components/ntp_snippets/remote/remote_suggestions_provider_impl.h"
@@ -497,6 +498,7 @@
   MediaStreamDevicesController::RegisterProfilePrefs(registry);
   NetHttpSessionParamsObserver::RegisterProfilePrefs(registry);
   NotifierStateTracker::RegisterProfilePrefs(registry);
+  ntp_snippets::ContentSuggestionsGCMAppHandler::RegisterProfilePrefs(registry);
   ntp_snippets::ContentSuggestionsService::RegisterProfilePrefs(registry);
   ntp_snippets::ForeignSessionsSuggestionsProvider::RegisterProfilePrefs(
       registry);
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index 41baac05..236d02a 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -1313,11 +1313,6 @@
   net::HttpNetworkSession::Context session_context;
   net::URLRequestContextBuilder::SetHttpNetworkSessionComponents(
       context, &session_context);
-  if (!IsOffTheRecord()) {
-    session_context.socket_performance_watcher_factory =
-        io_thread->globals()
-            ->network_quality_estimator->GetSocketPerformanceWatcherFactory();
-  }
   if (data_reduction_proxy_io_data_.get()) {
     session_context.proxy_delegate =
         data_reduction_proxy_io_data_->proxy_delegate();
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.html b/chrome/browser/resources/settings/basic_page/basic_page.html
index 86c5b4b..d08c0df4 100644
--- a/chrome/browser/resources/settings/basic_page/basic_page.html
+++ b/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -121,7 +121,7 @@
         </template>
 </if>
 <if expr="is_win">
-        <template is="dom-if" if="[[chromeCleanupVisible_]]" restamp>
+        <template is="dom-if" if="[[showChromeCleanup]]" restamp>
           <settings-section section="chromeCleanup">
             <settings-chrome-cleanup-page></settings-chrome-cleanup-page>
           </settings-section>
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.js b/chrome/browser/resources/settings/basic_page/basic_page.js
index 01ee11b6..9063c8b 100644
--- a/chrome/browser/resources/settings/basic_page/basic_page.js
+++ b/chrome/browser/resources/settings/basic_page/basic_page.js
@@ -20,16 +20,13 @@
 
     showAndroidApps: Boolean,
 
-    // <if expr="is_win">
-    /**
-     * Whether there is cleanup information to present to the user.
-     * @private {boolean}
-     */
-    chromeCleanupVisible_: {
+    showChromeCleanup: {
       type: Boolean,
-      value: false,
+      value: function() {
+        return loadTimeData.valueExists('chromeCleanupEnabled') &&
+            loadTimeData.getBoolean('chromeCleanupEnabled');
+      },
     },
-    // </if>
 
     /**
      * Dictionary defining page visibility.
@@ -93,20 +90,9 @@
   attached: function() {
     this.currentRoute_ = settings.getCurrentRoute();
 
-    // <if expr="is_win">
-    this.addWebUIListener(
-        'basic-page-set-chrome-cleanup-visibility',
-        function(visibility) {
-          this.chromeCleanupVisible_ = visibility;
-        }.bind(this));
-
-    var cleanupBrowserProxy =
-        settings.ChromeCleanupProxyImpl.getInstance();
-    cleanupBrowserProxy.getChromeCleanupVisibility().then(
-      function(visibility) {
-        this.chromeCleanupVisible_ = visibility;
-      }.bind(this));
-    // </if>
+    this.addEventListener('chrome-cleanup-dismissed', function(e) {
+      this.showChromeCleanup = false;
+    }.bind(this));
   },
 
   /**
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
index a7def7e..3d43ba4 100644
--- a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
+++ b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
@@ -14,30 +14,16 @@
 <dom-module id="settings-chrome-cleanup-page">
   <template>
     <style include="settings-shared">
-      #details-container {
-        display: block;
-        padding-bottom: 10px;
-        padding-top: 10px;
-      }
-
       #files-to-remove-list {
         -webkit-user-select: text;
       }
 
-      .powered-by {
-        padding-top: 10px;
-      }
-
       #show-files-button {
         color: var(--google-blue-700);
         --paper-button-ink-color: white;
         text-transform: inherit;
       }
 
-      .show-files-container {
-        padding-top: 10px;
-      }
-
       #status-icon {
         height: 24px;
         width: 24px;
@@ -79,8 +65,10 @@
       </template>
     </div>
     <div id="details-container"
-         class="settings-box" hidden="[[!showDetails_]]">
+         class="settings-box two-line" hidden="[[!showDetails_]]">
       <div>[[detailsDescription]]</div>
+    </div>
+    <div class="settings-box continuation" hidden="[[!showDetails_]]">
       <div class="show-files-container start" hidden="[[showFilesToRemove_]]">
         <paper-button id="show-files-button" on-tap="showFiles_">
           $i18n{chromeCleanupLinkShowFiles}
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js
index 615d447..77d18fd1 100644
--- a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js
+++ b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js
@@ -5,15 +5,16 @@
 /**
  * The reason why the controller is in state kIdle.
  * Must be kept in sync with ChromeCleanerController::IdleReason.
- * @enum {number}
+ * @enum {string}
  */
 settings.ChromeCleanupIdleReason = {
-  INITIAL: 0,
-  SCANNING_FOUND_NOTHING: 1,
-  SCANNING_FAILED: 2,
-  CONNECTION_LOST: 3,
-  CLEANING_FAILED: 4,
-  CLEANING_SUCCEEDED: 5,
+  INITIAL: 'initial',
+  SCANNING_FOUND_NOTHING: 'scanning_found_nothing',
+  SCANNING_FAILED: 'scanning_failed',
+  CONNECTION_LOST: 'connection_lost',
+  USER_DECLINED_CLEANUP: 'user_declined_cleanup',
+  CLEANING_FAILED: 'cleaning_failed',
+  CLEANING_SUCCEEDED: 'cleaning_succeeded',
 };
 
 /**
@@ -111,17 +112,19 @@
   attached: function() {
     this.browserProxy_ = settings.ChromeCleanupProxyImpl.getInstance();
 
-    this.addWebUIListener('chrome-cleanup-on-idle', this.OnIdle_.bind(this));
+    this.addWebUIListener('chrome-cleanup-on-idle', this.onIdle_.bind(this));
     this.addWebUIListener(
-        'chrome-cleanup-on-scanning', this.OnScanning_.bind(this));
+        'chrome-cleanup-on-scanning', this.onScanning_.bind(this));
     this.addWebUIListener(
-        'chrome-cleanup-on-infected', this.OnInfected_.bind(this));
+        'chrome-cleanup-on-infected', this.onInfected_.bind(this));
     this.addWebUIListener(
-        'chrome-cleanup-on-cleaning', this.OnCleaning_.bind(this));
+        'chrome-cleanup-on-cleaning', this.onCleaning_.bind(this));
     this.addWebUIListener(
-        'chrome-cleanup-on-reboot-required', this.OnRebootRequired_.bind(this));
+        'chrome-cleanup-on-reboot-required', this.onRebootRequired_.bind(this));
+    this.addWebUIListener(
+        'chrome-cleanup-on-dismiss', this.onDismiss_.bind(this));
 
-    this.browserProxy_.registerChromeCleanupObserver();
+    this.browserProxy_.registerChromeCleanerObserver();
   },
 
   /**
@@ -146,16 +149,13 @@
    * @param {number} idleReason
    * @private
    */
-  OnIdle_: function(idleReason) {
-    if (this.waitingForCleanupResults_ &&
-        idleReason == settings.ChromeCleanupIdleReason.CLEANING_SUCCEEDED) {
+  onIdle_: function(idleReason) {
+    if (idleReason == settings.ChromeCleanupIdleReason.CLEANING_SUCCEEDED) {
       this.title_ = this.i18n('chromeCleanupTitleRemoved');
       this.enableActionButton_(
           this.i18n('chromeCleanupDoneButtonLabel'), this.dismiss_.bind(this));
       this.setIconDone_();
-    } else if (
-        this.waitingForCleanupResults_ &&
-        idleReason == settings.ChromeCleanupIdleReason.CLEANING_FAILED) {
+    } else if (idleReason == settings.ChromeCleanupIdleReason.CLEANING_FAILED) {
       this.title_ = this.i18n('chromeCleanupTitleErrorCantRemove');
       this.enableActionButton_(
           this.i18n('chromeCleanupDoneButtonLabel'), this.dismiss_.bind(this));
@@ -177,7 +177,7 @@
    * the card and cleanup this element's fields.
    * @private
    */
-  OnScanning_: function() {
+  onScanning_: function() {
     this.title_ = '';
     this.isRemoving_ = false;
     this.disableActionButton_();
@@ -190,7 +190,7 @@
    * @param {!Array<!string>} files The list of files to present to the user.
    * @private
    */
-  OnInfected_: function(files) {
+  onInfected_: function(files) {
     this.title_ = this.i18n('chromeCleanupTitleRemove');
     this.isRemoving_ = false;
     this.setIconRemove_();
@@ -207,7 +207,7 @@
    * @param {!Array<!string>} files The list of files to present to the user.
    * @private
    */
-  OnCleaning_: function(files) {
+  onCleaning_: function(files) {
     this.waitingForCleanupResults_ = true;
     this.title_ = this.i18n('chromeCleanupTitleRemoving');
     this.isRemoving_ = true;
@@ -222,7 +222,7 @@
    * the card and cleanup this element's fields.
    * @private
    */
-  OnRebootRequired_: function() {
+  onRebootRequired_: function() {
     this.title_ = this.i18n('chromeCleanupTitleRestart');
     this.isRemoving_ = false;
     this.setIconWarning_();
@@ -233,12 +233,20 @@
   },
 
   /**
-   * Dismiss the card and unregister it from the controller.
+   * Listener of event 'chrome-cleanup-dismiss'.
+   * Hides the Cleanup card.
+   * @private
+   */
+   onDismiss_: function() {
+     this.fire('chrome-cleanup-dismissed');
+   },
+
+  /**
+   * Dismiss the card.
    * @private
    */
   dismiss_: function() {
     this.browserProxy_.dismissCleanupPage();
-    // TODO(proberge): unregister from the controller.
   },
 
   /**
@@ -324,6 +332,7 @@
 
   /**
    * Sets the card's icon as a completed indication.
+   * @private
    */
   setIconDone_: function() {
     this.statusIcon_ = 'settings:check-circle';
@@ -332,6 +341,7 @@
 
   /**
    * Resets the card's icon.
+   * @private
    */
   resetIcon_: function() {
     this.statusIcon_ = '';
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_proxy.js b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_proxy.js
index c269d8d..7edbab00 100644
--- a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_proxy.js
+++ b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_proxy.js
@@ -9,9 +9,9 @@
   ChromeCleanupProxy.prototype = {
     /**
      * Registers the current ChromeCleanupHandler as an observer of
-     * ChromeCleanupController events.
+     * ChromeCleanerController events.
      */
-    registerChromeCleanupObserver: assertNotReached,
+    registerChromeCleanerObserver: assertNotReached,
 
     /**
      * Starts a cleanup on the user's computer.
@@ -27,12 +27,6 @@
      * Hides the Cleanup page from the settings menu.
      */
     dismissCleanupPage: assertNotReached,
-
-    /**
-     * Retrieves if there is cleanup information to present to the user.
-     * @return {!Promise<boolean>}
-     */
-    getChromeCleanupVisibility: assertNotReached,
   };
 
   /**
@@ -45,33 +39,23 @@
 
   ChromeCleanupProxyImpl.prototype = {
     /** @override */
-    registerChromeCleanupObserver: function() {
-      // TODO(proberge): Uncomment once this is implemented.
-      // chrome.send('registerChromeCleanupObserver');
+    registerChromeCleanerObserver: function() {
+      chrome.send('registerChromeCleanerObserver');
     },
 
     /** @override */
     startCleanup: function() {
-      // TODO(proberge): Uncomment once this is implemented.
-      // chrome.send('startCleanup');
+      chrome.send('startCleanup');
     },
 
     /** @override */
     restartComputer: function() {
-      // TODO(proberge): Uncomment once this is implemented.
-      // chrome.send('restartComputer');
+      chrome.send('restartComputer');
     },
 
     /** @override */
     dismissCleanupPage: function() {
-      // TODO(proberge): Uncomment once this is implemented.
-    },
-
-    /** @override */
-    getChromeCleanupVisibility: function() {
-      // TODO(proberge): Uncomment once this is implemented.
-      // return cr.sendWithPromise('getChromeCleanupVisibility');
-      return Promise.resolve(false);
+      chrome.send('dismissCleanupPage');
     },
   };
 
diff --git a/chrome/browser/resources/settings/people_page/change_picture.html b/chrome/browser/resources/settings/people_page/change_picture.html
index 963de294..377f9cc 100644
--- a/chrome/browser/resources/settings/people_page/change_picture.html
+++ b/chrome/browser/resources/settings/people_page/change_picture.html
@@ -99,23 +99,23 @@
       </iron-a11y-keys>
       <div id="availableIcons" class="start">
         <iron-selector id="selector" on-iron-activate="onImageActivate_"
-            selected-item="{{selectedItem_}}">
-          <iron-icon id="cameraImage"
+            selected-item="{{selectedItem_}}" role="radiogroup">
+          <iron-icon id="cameraImage" role="radio"
               data-type$="[[selectionTypesEnum_.CAMERA]]"
               icon="settings:camera-alt" title="$i18n{takePhoto}"
               hidden="[[!cameraPresent_]]">
           </iron-icon>
-          <iron-icon data-type$="[[selectionTypesEnum_.FILE]]"
+          <iron-icon data-type$="[[selectionTypesEnum_.FILE]]" role="radio"
               icon="cr:folder" title="$i18n{chooseFile}">
           </iron-icon>
-          <img id="profileImage"
+          <img id="profileImage" role="radio"
               data-type$="[[selectionTypesEnum_.PROFILE]]"
               src="[[profileImageUrl_]]" title="$i18n{profilePhotoLoading}">
           <img id="oldImage" data-type$="[[selectionTypesEnum_.OLD]]"
-              src="[[oldImageUrl_]]" hidden="[[!oldImageUrl_]]"
+              role="radio" src="[[oldImageUrl_]]" hidden="[[!oldImageUrl_]]"
               title="$i18n{oldPhoto}">
           <template is="dom-repeat" items="[[defaultImages_]]">
-            <img data-type$="[[selectionTypesEnum_.DEFAULT]]"
+            <img data-type$="[[selectionTypesEnum_.DEFAULT]]" role="radio"
                 data-default-image-index$="[[index]]" src="[[item.url]]"
                 title="[[item.title]]">
           </template>
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.cc
index 7424302..3f84823d 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.cc
@@ -35,6 +35,9 @@
 using ::chrome_cleaner::mojom::PromptAcceptance;
 using ::content::BrowserThread;
 
+// Keeps track of whether GetInstance() has been called.
+bool g_instance_exists = false;
+
 // TODO(alito): Move these shared exit codes to the chrome_cleaner component.
 // https://crbug.com/727956
 constexpr int kRebootRequiredExitCode = 15;
@@ -113,9 +116,17 @@
 // static
 ChromeCleanerController* ChromeCleanerController::GetInstance() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  g_instance_exists = true;
   return base::Singleton<ChromeCleanerController>::get();
 }
 
+// static
+bool ChromeCleanerController::ShouldShowCleanupInSettingsUI() {
+  // Short-circuit if the instance doesn't exist to avoid creating it during
+  // navigation to chrome://settings.
+  return g_instance_exists && GetInstance()->state() == State::kInfected;
+}
+
 void ChromeCleanerController::SetDelegateForTesting(
     ChromeCleanerControllerDelegate* delegate) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h
index 0b75a2c3..40424ad 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h
@@ -112,6 +112,10 @@
   // Returns the singleton controller object.
   static ChromeCleanerController* GetInstance();
 
+  // Returns whether the Cleanup card in settings should be displayed.
+  // Static to prevent instantiation of the singleton.
+  static bool ShouldShowCleanupInSettingsUI();
+
   State state() const { return state_; }
 
   // |AddObserver()| immediately notifies |observer| of the controller's state
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 8892be7c..3e4a0ec 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3125,6 +3125,8 @@
       "webui/conflicts_handler.h",
       "webui/conflicts_ui.cc",
       "webui/conflicts_ui.h",
+      "webui/settings/chrome_cleanup_handler.cc",
+      "webui/settings/chrome_cleanup_handler.h",
       "webui/welcome_win10_handler.cc",
       "webui/welcome_win10_handler.h",
       "webui/welcome_win10_ui.cc",
diff --git a/chrome/browser/ui/android/usb_chooser_dialog_android.cc b/chrome/browser/ui/android/usb_chooser_dialog_android.cc
index 0fc1f66..39d3a6e 100644
--- a/chrome/browser/ui/android/usb_chooser_dialog_android.cc
+++ b/chrome/browser/ui/android/usb_chooser_dialog_android.cc
@@ -29,10 +29,15 @@
 #include "device/usb/usb_device.h"
 #include "device/usb/usb_device_filter.h"
 #include "device/usb/webusb_descriptors.h"
+#include "device/vr/features/features.h"
 #include "jni/UsbChooserDialog_jni.h"
 #include "ui/android/window_android.h"
 #include "url/gurl.h"
 
+#if BUILDFLAG(ENABLE_VR)
+#include "chrome/browser/android/vr_shell/vr_tab_helper.h"
+#endif  // BUILDFLAG(ENABLE_VR)
+
 using device::UsbDevice;
 using device::UsbDeviceFilter;
 
@@ -59,6 +64,16 @@
       usb_service_observer_(this),
       filters_(filters),
       weak_factory_(this) {
+  content::WebContents* web_contents =
+      content::WebContents::FromRenderFrameHost(render_frame_host_);
+#if BUILDFLAG(ENABLE_VR)
+  if (vr_shell::VrTabHelper::IsInVr(web_contents)) {
+    DCHECK(!callback_.is_null());
+    callback_.Run(nullptr);
+    callback_.Reset();  // Reset |callback_| so that it is only run once.
+    return;
+  }
+#endif
   device::UsbService* usb_service =
       device::DeviceClient::Get()->GetUsbService();
   if (!usb_service)
@@ -68,8 +83,6 @@
     usb_service_observer_.Add(usb_service);
 
   // Create (and show) the UsbChooser dialog.
-  content::WebContents* web_contents =
-      content::WebContents::FromRenderFrameHost(render_frame_host_);
   base::android::ScopedJavaLocalRef<jobject> window_android =
       content::ContentViewCore::FromWebContents(web_contents)
           ->GetWindowAndroid()
diff --git a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h
index 3972b5e..3c98045 100644
--- a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h
+++ b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h
@@ -65,6 +65,7 @@
   IBOutlet NSButton* manageButton_;
   IBOutlet NSButton* doneButton_;
   IBOutlet NSButton* loadButton_;
+  IBOutlet NSButton* infoButton_;
 
   std::unique_ptr<ContentSettingBubbleModel> contentSettingBubbleModel_;
 
diff --git a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm
index acc447f..0b1b1a3 100644
--- a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm
+++ b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm
@@ -110,6 +110,7 @@
   [label setStringValue:text];
   [label setSelectable:NO];
   [label setBezeled:NO];
+  [label setAlignment:NSNaturalTextAlignment];
   return [label autorelease];
 }
 
@@ -390,6 +391,7 @@
   NSRect titleFrame = [titleLabel_ frame];
   titleFrame.origin.y -= deltaY;
   [titleLabel_ setFrame:titleFrame];
+  [titleLabel_ setAlignment:NSNaturalTextAlignment];
 }
 
 - (void)initializeMessage {
@@ -408,6 +410,7 @@
   NSRect messageFrame = [messageLabel_ frame];
   messageFrame.origin.y -= deltaY;
   [messageLabel_ setFrame:messageFrame];
+  [messageLabel_ setAlignment:NSNaturalTextAlignment];
 }
 
 - (void)initializeRadioGroup {
@@ -450,6 +453,19 @@
   NSRect windowFrame = [[self window] frame];
   windowFrame.size.height += radioDeltaY;
   [[self window] setFrame:windowFrame display:NO];
+
+  // NSMatrix-based radio buttons don't get automatically flipped for
+  // RTL. Setting the user interface layout direction explicitly
+  // doesn't affect rendering, so set image position and text alignment
+  // manually.
+  if (cocoa_l10n_util::ShouldDoExperimentalRTLLayout())
+    for (NSButtonCell* cell in [allowBlockRadioGroup_ cells]) {
+      [cell setAlignment:NSNaturalTextAlignment];
+      [cell setImagePosition:cocoa_l10n_util::LeadingCellImagePosition()];
+      // Why not?
+      [cell setUserInterfaceLayoutDirection:
+                NSUserInterfaceLayoutDirectionRightToLeft];
+    }
 }
 
 - (NSButton*)hyperlinkButtonWithFrame:(NSRect)frame
@@ -982,6 +998,20 @@
 
   if (contentSettingBubbleModel_->AsMediaStreamBubbleModel())
     [self initializeMediaMenus];
+
+  // RTL-ize NIBS:
+  if (cocoa_l10n_util::ShouldDoExperimentalRTLLayout()) {
+    cocoa_l10n_util::FlipAllSubviewsIfNecessary([self bubble]);
+
+    // Some NIBs have the manage/done buttons outside of the bubble.
+    cocoa_l10n_util::FlipAllSubviewsIfNecessary([[self bubble] superview]);
+    cocoa_l10n_util::FlipAllSubviewsIfNecessary(contentsContainer_);
+
+    // These buttons are inside |GTMWidthBasedTweaker|s, so fix margins.
+    cocoa_l10n_util::FlipAllSubviewsIfNecessary([infoButton_ superview]);
+    cocoa_l10n_util::FlipAllSubviewsIfNecessary([doneButton_ superview]);
+    cocoa_l10n_util::FlipAllSubviewsIfNecessary([manageButton_ superview]);
+  }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc
index e5486c5..c148a66 100644
--- a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc
+++ b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc
@@ -302,10 +302,6 @@
   return DialogDelegateView::GetDialogButtonLabel(button);
 }
 
-bool CardUnmaskPromptViews::ShouldDefaultButtonBeBlue() const {
-  return true;
-}
-
 bool CardUnmaskPromptViews::IsDialogButtonEnabled(
     ui::DialogButton button) const {
   if (button == ui::DIALOG_BUTTON_CANCEL)
diff --git a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.h b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.h
index 1288bf1..51544ce 100644
--- a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.h
+++ b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.h
@@ -65,7 +65,6 @@
   base::string16 GetWindowTitle() const override;
   void DeleteDelegate() override;
   base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
-  bool ShouldDefaultButtonBeBlue() const override;
   bool IsDialogButtonEnabled(ui::DialogButton button) const override;
   View* GetInitiallyFocusedView() override;
   bool Cancel() override;
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
index 4a3a16c..6ca27d4 100644
--- a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
+++ b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
@@ -139,10 +139,6 @@
                                        : IDS_NO_THANKS);
 }
 
-bool SaveCardBubbleViews::ShouldDefaultButtonBeBlue() const {
-  return true;
-}
-
 gfx::Size SaveCardBubbleViews::CalculatePreferredSize() const {
   return gfx::Size(kBubbleWidth, GetHeightForWidth(kBubbleWidth));
 }
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views.h b/chrome/browser/ui/views/autofill/save_card_bubble_views.h
index 005d72e..797d05d 100644
--- a/chrome/browser/ui/views/autofill/save_card_bubble_views.h
+++ b/chrome/browser/ui/views/autofill/save_card_bubble_views.h
@@ -53,7 +53,6 @@
   bool Close() override;
   base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
   bool IsDialogButtonEnabled(ui::DialogButton button) const override;
-  bool ShouldDefaultButtonBeBlue() const override;
 
   // views::View
   gfx::Size CalculatePreferredSize() const override;
diff --git a/chrome/browser/ui/views/chrome_cleaner_dialog_win.cc b/chrome/browser/ui/views/chrome_cleaner_dialog_win.cc
index 46764b9..967e4ff 100644
--- a/chrome/browser/ui/views/chrome_cleaner_dialog_win.cc
+++ b/chrome/browser/ui/views/chrome_cleaner_dialog_win.cc
@@ -72,12 +72,6 @@
   controller_->DialogShown();
 }
 
-// DialogModel overrides.
-
-bool ChromeCleanerDialog::ShouldDefaultButtonBeBlue() const {
-  return true;
-}
-
 // WidgetDelegate overrides.
 
 ui::ModalType ChromeCleanerDialog::GetModalType() const {
diff --git a/chrome/browser/ui/views/chrome_cleaner_dialog_win.h b/chrome/browser/ui/views/chrome_cleaner_dialog_win.h
index 944c4a2..8d3b1449 100644
--- a/chrome/browser/ui/views/chrome_cleaner_dialog_win.h
+++ b/chrome/browser/ui/views/chrome_cleaner_dialog_win.h
@@ -38,9 +38,6 @@
 
   void Show(Browser* browser);
 
-  // ui::DialogModel overrides.
-  bool ShouldDefaultButtonBeBlue() const override;
-
   // views::WidgetDelegate overrides.
   ui::ModalType GetModalType() const override;
   base::string16 GetWindowTitle() const override;
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
index fe21821..b7c9ae2 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
@@ -298,10 +298,6 @@
                                        : IDS_CANCEL);
 }
 
-bool DesktopMediaPickerDialogView::ShouldDefaultButtonBeBlue() const {
-  return true;
-}
-
 views::View* DesktopMediaPickerDialogView::CreateExtraView() {
   return audio_share_checkbox_;
 }
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h
index fa8a581..854a3e0 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h
@@ -53,7 +53,6 @@
   base::string16 GetWindowTitle() const override;
   bool IsDialogButtonEnabled(ui::DialogButton button) const override;
   views::View* GetInitiallyFocusedView() override;
-  bool ShouldDefaultButtonBeBlue() const override;
   base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
   View* CreateExtraView() override;
   bool Accept() override;
diff --git a/chrome/browser/ui/views/global_error_bubble_view.cc b/chrome/browser/ui/views/global_error_bubble_view.cc
index 46f7934..6b63fad 100644
--- a/chrome/browser/ui/views/global_error_bubble_view.cc
+++ b/chrome/browser/ui/views/global_error_bubble_view.cc
@@ -157,10 +157,6 @@
   return error_ && error_->ShouldShowCloseButton();
 }
 
-bool GlobalErrorBubbleView::ShouldDefaultButtonBeBlue() const {
-  return true;
-}
-
 base::string16 GlobalErrorBubbleView::GetDialogButtonLabel(
     ui::DialogButton button) const {
   if (!error_)
diff --git a/chrome/browser/ui/views/global_error_bubble_view.h b/chrome/browser/ui/views/global_error_bubble_view.h
index db08a6d..4071e909 100644
--- a/chrome/browser/ui/views/global_error_bubble_view.h
+++ b/chrome/browser/ui/views/global_error_bubble_view.h
@@ -36,7 +36,6 @@
   void Init() override;
   bool ShouldShowCloseButton() const override;
   void UpdateButton(views::LabelButton* button, ui::DialogButton type) override;
-  bool ShouldDefaultButtonBeBlue() const override;
   base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
   int GetDialogButtons() const override;
   bool Cancel() override;
diff --git a/chrome/browser/ui/views/ime/ime_warning_bubble_view.cc b/chrome/browser/ui/views/ime/ime_warning_bubble_view.cc
index 1435be2..01aad4c 100644
--- a/chrome/browser/ui/views/ime/ime_warning_bubble_view.cc
+++ b/chrome/browser/ui/views/ime/ime_warning_bubble_view.cc
@@ -67,10 +67,6 @@
   return true;
 }
 
-bool ImeWarningBubbleView::ShouldDefaultButtonBeBlue() const {
-  return true;
-}
-
 void ImeWarningBubbleView::OnToolbarActionsBarAnimationEnded() {
   if (!bubble_has_shown_) {
     views::BubbleDialogDelegateView::CreateBubble(this)->Show();
diff --git a/chrome/browser/ui/views/ime/ime_warning_bubble_view.h b/chrome/browser/ui/views/ime/ime_warning_bubble_view.h
index 04ca7a0c..5272c2f 100644
--- a/chrome/browser/ui/views/ime/ime_warning_bubble_view.h
+++ b/chrome/browser/ui/views/ime/ime_warning_bubble_view.h
@@ -41,7 +41,6 @@
   // views::DialogDelegate:
   bool Accept() override;
   bool Cancel() override;
-  bool ShouldDefaultButtonBeBlue() const override;
 
   // ToolbarActionsBarObserver:
   void OnToolbarActionsBarAnimationEnded() override;
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index f23d8467..a962a9e 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <map>
 
+#include "base/feature_list.h"
 #include "base/i18n/rtl.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -51,6 +52,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/bookmarks/common/bookmark_pref_names.h"
 #include "components/favicon/content/content_favicon_driver.h"
+#include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/omnibox/browser/omnibox_popup_model.h"
 #include "components/omnibox/browser/omnibox_popup_view.h"
 #include "components/prefs/pref_service.h"
@@ -370,12 +372,25 @@
     int* left_margin,
     int* right_margin,
     int top_edge_overlap) {
-  *top_left_screen_coord = gfx::Point(0, parent()->height() - top_edge_overlap);
+  // The popup contents are always sized matching the location bar size.
+  const int popup_contents_left = x();
+  const int popup_contents_right = bounds().right();
+
+  // The popup itself may either be the same width as the contents, or as wide
+  // as the toolbar.
+  bool narrow_popup =
+      base::FeatureList::IsEnabled(omnibox::kUIExperimentNarrowDropdown);
+  const int popup_left = narrow_popup ? popup_contents_left : 0;
+  const int popup_right =
+      narrow_popup ? popup_contents_right : parent()->width();
+
+  *top_left_screen_coord =
+      gfx::Point(popup_left, parent()->height() - top_edge_overlap);
   views::View::ConvertPointToScreen(parent(), top_left_screen_coord);
 
-  *popup_width = parent()->width();
-  *left_margin = x();
-  *right_margin = *popup_width - bounds().right();
+  *popup_width = popup_right - popup_left;
+  *left_margin = popup_contents_left - popup_left;
+  *right_margin = popup_right - popup_contents_right;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index 5c4cdc2..6d29e0a 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -380,6 +380,8 @@
       const int kAnswerIconToTextPadding = 2;
       x += answer_icon_size + kAnswerIconToTextPadding;
     }
+    DrawRenderText(match, description, DESCRIPTION, canvas, x, y,
+                   description_max_width);
     return;
   }
 
diff --git a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
index b6a7a62..879d72f 100644
--- a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
+++ b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
@@ -164,10 +164,6 @@
   return ui::DIALOG_BUTTON_CANCEL;
 }
 
-bool AccountChooserDialogView::ShouldDefaultButtonBeBlue() const {
-  return show_signin_button_;
-}
-
 base::string16 AccountChooserDialogView::GetDialogButtonLabel(
     ui::DialogButton button) const {
   int message_id = 0;
diff --git a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.h b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.h
index ae50ed2..0241a6b 100644
--- a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.h
+++ b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.h
@@ -41,7 +41,6 @@
   // DialogDelegate:
   bool Accept() override;
   int GetDialogButtons() const override;
-  bool ShouldDefaultButtonBeBlue() const override;
   base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
 
   // views::View
diff --git a/chrome/browser/ui/views/settings_reset_prompt_dialog.cc b/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
index 7d26ccc3..b394fb4 100644
--- a/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
+++ b/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
@@ -88,12 +88,6 @@
   return controller_->GetWindowTitle();
 }
 
-// DialogModel overrides.
-
-bool SettingsResetPromptDialog::ShouldDefaultButtonBeBlue() const {
-  return true;
-}
-
 // DialogDelegate overrides.
 
 base::string16 SettingsResetPromptDialog::GetDialogButtonLabel(
diff --git a/chrome/browser/ui/views/settings_reset_prompt_dialog.h b/chrome/browser/ui/views/settings_reset_prompt_dialog.h
index c668bcfe..033555c6f 100644
--- a/chrome/browser/ui/views/settings_reset_prompt_dialog.h
+++ b/chrome/browser/ui/views/settings_reset_prompt_dialog.h
@@ -39,9 +39,6 @@
   bool ShouldShowWindowIcon() const override;
   base::string16 GetWindowTitle() const override;
 
-  // ui::DialogModel overrides.
-  bool ShouldDefaultButtonBeBlue() const override;
-
   // views::DialogDelegate overrides.
   base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
   bool Accept() override;
diff --git a/chrome/browser/ui/webui/settings/chrome_cleanup_handler.cc b/chrome/browser/ui/webui/settings/chrome_cleanup_handler.cc
new file mode 100644
index 0000000..023ae0c
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/chrome_cleanup_handler.cc
@@ -0,0 +1,152 @@
+// Copyright (c) 2017 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 "chrome/browser/ui/webui/settings/chrome_cleanup_handler.h"
+
+#include "base/command_line.h"
+#include "base/feature_list.h"
+#include "base/synchronization/lock.h"
+#include "base/values.h"
+#include "chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h"
+#include "chrome/grit/generated_resources.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using safe_browsing::ChromeCleanerController;
+
+namespace settings {
+
+namespace {
+
+// Returns a ListValue containing a copy of the file paths stored in |files|.
+base::ListValue GetFilesAsListStorage(const std::set<base::FilePath>& files) {
+  base::ListValue value;
+  for (const base::FilePath& path : files)
+    value.AppendString(path.value());
+
+  return value;
+}
+
+std::string IdleReasonToString(
+    ChromeCleanerController::IdleReason idle_reason) {
+  switch (idle_reason) {
+    case ChromeCleanerController::IdleReason::kInitial:
+      return "initial";
+    case ChromeCleanerController::IdleReason::kScanningFoundNothing:
+      return "scanning_found_nothing";
+    case ChromeCleanerController::IdleReason::kScanningFailed:
+      return "scanning_failed";
+    case ChromeCleanerController::IdleReason::kConnectionLost:
+      return "connection_lost";
+    case ChromeCleanerController::IdleReason::kUserDeclinedCleanup:
+      return "user_declined_cleanup";
+    case ChromeCleanerController::IdleReason::kCleaningFailed:
+      return "cleaning_failed";
+    case ChromeCleanerController::IdleReason::kCleaningSucceeded:
+      return "cleaning_succeeded";
+  }
+  NOTREACHED();
+  return "";
+}
+
+}  // namespace
+
+ChromeCleanupHandler::ChromeCleanupHandler()
+    : controller_(ChromeCleanerController::GetInstance()) {}
+
+ChromeCleanupHandler::~ChromeCleanupHandler() {
+  controller_->RemoveObserver(this);
+}
+
+void ChromeCleanupHandler::RegisterMessages() {
+  web_ui()->RegisterMessageCallback(
+      "dismissCleanupPage",
+      base::Bind(&ChromeCleanupHandler::HandleDismiss, base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "registerChromeCleanerObserver",
+      base::Bind(&ChromeCleanupHandler::HandleRegisterChromeCleanerObserver,
+                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "restartComputer",
+      base::Bind(&ChromeCleanupHandler::HandleRestartComputer,
+                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "startCleanup", base::Bind(&ChromeCleanupHandler::HandleStartCleanup,
+                                 base::Unretained(this)));
+}
+
+void ChromeCleanupHandler::OnJavascriptAllowed() {
+  controller_->AddObserver(this);
+}
+
+void ChromeCleanupHandler::OnJavascriptDisallowed() {
+  controller_->RemoveObserver(this);
+}
+
+void ChromeCleanupHandler::OnIdle(
+    ChromeCleanerController::IdleReason idle_reason) {
+  CallJavascriptFunction("cr.webUIListenerCallback",
+                         base::Value("chrome-cleanup-on-idle"),
+                         base::Value(IdleReasonToString(idle_reason)));
+}
+
+void ChromeCleanupHandler::OnScanning() {
+  CallJavascriptFunction("cr.webUIListenerCallback",
+                         base::Value("chrome-cleanup-on-scanning"));
+}
+
+void ChromeCleanupHandler::OnInfected(const std::set<base::FilePath>& files) {
+  CallJavascriptFunction("cr.webUIListenerCallback",
+                         base::Value("chrome-cleanup-on-infected"),
+                         GetFilesAsListStorage(files));
+}
+
+void ChromeCleanupHandler::OnCleaning(const std::set<base::FilePath>& files) {
+  CallJavascriptFunction("cr.webUIListenerCallback",
+                         base::Value("chrome-cleanup-on-cleaning"),
+                         GetFilesAsListStorage(files));
+}
+
+void ChromeCleanupHandler::OnRebootRequired() {
+  CallJavascriptFunction("cr.webUIListenerCallback",
+                         base::Value("chrome-cleanup-on-reboot-required"));
+}
+
+void ChromeCleanupHandler::HandleDismiss(const base::ListValue* args) {
+  DCHECK_EQ(0U, args->GetSize());
+
+  controller_->RemoveObserver(this);
+
+  CallJavascriptFunction("cr.webUIListenerCallback",
+                         base::Value("chrome-cleanup-dismiss"));
+}
+
+void ChromeCleanupHandler::HandleRegisterChromeCleanerObserver(
+    const base::ListValue* args) {
+  DCHECK_EQ(0U, args->GetSize());
+  // The Polymer element should never be attached if the feature is
+  // disabled.
+  DCHECK(
+      base::FeatureList::IsEnabled(safe_browsing::kInBrowserCleanerUIFeature));
+
+  AllowJavascript();
+}
+
+void ChromeCleanupHandler::HandleRestartComputer(const base::ListValue* args) {
+  DCHECK_EQ(0U, args->GetSize());
+
+  CallJavascriptFunction("cr.webUIListenerCallback",
+                         base::Value("chrome-cleanup-on-dismiss"));
+  // TODO(proberge): Show a prompt to reboot the system.
+}
+
+void ChromeCleanupHandler::HandleStartCleanup(const base::ListValue* args) {
+  DCHECK_EQ(0U, args->GetSize());
+
+  controller_->ReplyWithUserResponse(
+      ChromeCleanerController::UserResponse::kAccepted);
+}
+
+}  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/chrome_cleanup_handler.h b/chrome/browser/ui/webui/settings/chrome_cleanup_handler.h
new file mode 100644
index 0000000..86df512
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/chrome_cleanup_handler.h
@@ -0,0 +1,64 @@
+// Copyright 2017 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_BROWSER_UI_WEBUI_SETTINGS_CHROME_CLEANUP_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROME_CLEANUP_HANDLER_H_
+
+#include <set>
+
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h"
+#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
+
+namespace settings {
+
+// Chrome Cleanup settings page UI handler.
+class ChromeCleanupHandler
+    : public SettingsPageUIHandler,
+      public safe_browsing::ChromeCleanerController::Observer {
+ public:
+  ChromeCleanupHandler();
+  ~ChromeCleanupHandler() override;
+
+  // SettingsPageUIHandler implementation.
+  void RegisterMessages() override;
+  void OnJavascriptAllowed() override;
+  void OnJavascriptDisallowed() override;
+
+  // ChromeCleanerController::Observer implementation.
+  void OnIdle(
+      safe_browsing::ChromeCleanerController::IdleReason idle_reason) override;
+  void OnScanning() override;
+  void OnInfected(const std::set<base::FilePath>& files) override;
+  void OnCleaning(const std::set<base::FilePath>& files) override;
+  void OnRebootRequired() override;
+
+ private:
+  // Callback for the "dismissCleanupPage" message to hide the Cleanup page
+  // from the settings.
+  void HandleDismiss(const base::ListValue* args);
+
+  // Callback for the "registerChromeCleanerObserver" message. This registers
+  // this object as an observer of the Chrome Cleanup global state and
+  // and retrieves the current cleanup state.
+  void HandleRegisterChromeCleanerObserver(const base::ListValue* args);
+
+  // Callback for the "restartComputer" message to finalize the cleanup with a
+  // system restart.
+  void HandleRestartComputer(const base::ListValue* args);
+
+  // Callback for the "startCleanup" message to start removing unwanted
+  // software from the user's computer.
+  void HandleStartCleanup(const base::ListValue* args);
+
+  // Raw pointer to a singleton. Must outlive this object.
+  safe_browsing::ChromeCleanerController* controller_;
+
+  DISALLOW_COPY_AND_ASSIGN(ChromeCleanupHandler);
+};
+
+}  // namespace settings
+
+#endif  // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROME_CLEANUP_HANDLER_H_
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc
index 270df59..6d4d5df 100644
--- a/chrome/browser/ui/webui/settings/md_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -44,6 +44,12 @@
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
 
+#if defined(OS_WIN)
+#include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h"
+#include "chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h"
+#include "chrome/browser/ui/webui/settings/chrome_cleanup_handler.h"
+#endif  // defined(OS_WIN)
+
 #if defined(OS_WIN) || defined(OS_CHROMEOS)
 #include "chrome/browser/ui/webui/settings/languages_handler.h"
 #endif  // defined(OS_WIN) || defined(OS_CHROMEOS)
@@ -173,6 +179,14 @@
       content::WebUIDataSource::Create(url.host());
   html_source->AddString("hostname", url.host());
 
+#if defined(OS_WIN)
+  if (base::FeatureList::IsEnabled(safe_browsing::kInBrowserCleanerUIFeature) &&
+      safe_browsing::ChromeCleanerController::ShouldShowCleanupInSettingsUI()) {
+    AddSettingsPageUIHandler(base::MakeUnique<ChromeCleanupHandler>());
+    html_source->AddBoolean("chromeCleanupEnabled", true);
+  }
+#endif  // defined(OS_WIN)
+
 #if defined(OS_CHROMEOS)
   chromeos::settings::EasyUnlockSettingsHandler* easy_unlock_handler =
       chromeos::settings::EasyUnlockSettingsHandler::Create(html_source,
diff --git a/chrome/installer/setup/setup_util.cc b/chrome/installer/setup/setup_util.cc
index 9d3bf54e..e8eeb71 100644
--- a/chrome/installer/setup/setup_util.cc
+++ b/chrome/installer/setup/setup_util.cc
@@ -848,45 +848,4 @@
   return base::Time::FromFileTime(filetime);
 }
 
-ScopedTokenPrivilege::ScopedTokenPrivilege(const wchar_t* privilege_name)
-    : is_enabled_(false) {
-  HANDLE temp_handle;
-  if (!::OpenProcessToken(::GetCurrentProcess(),
-                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
-                          &temp_handle)) {
-    return;
-  }
-  token_.Set(temp_handle);
-
-  LUID privilege_luid;
-  if (!::LookupPrivilegeValue(NULL, privilege_name, &privilege_luid)) {
-    token_.Close();
-    return;
-  }
-
-  // Adjust the token's privileges to enable |privilege_name|. If this privilege
-  // was already enabled, |previous_privileges_|.PrivilegeCount will be set to 0
-  // and we then know not to disable this privilege upon destruction.
-  TOKEN_PRIVILEGES tp;
-  tp.PrivilegeCount = 1;
-  tp.Privileges[0].Luid = privilege_luid;
-  tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
-  DWORD return_length;
-  if (!::AdjustTokenPrivileges(token_.Get(), FALSE, &tp,
-                               sizeof(TOKEN_PRIVILEGES),
-                               &previous_privileges_, &return_length)) {
-    token_.Close();
-    return;
-  }
-
-  is_enabled_ = true;
-}
-
-ScopedTokenPrivilege::~ScopedTokenPrivilege() {
-  if (is_enabled_ && previous_privileges_.PrivilegeCount != 0) {
-    ::AdjustTokenPrivileges(token_.Get(), FALSE, &previous_privileges_,
-                            sizeof(TOKEN_PRIVILEGES), NULL, NULL);
-  }
-}
-
 }  // namespace installer
diff --git a/chrome/installer/setup/setup_util.h b/chrome/installer/setup/setup_util.h
index 007c75f..5fbc3a1 100644
--- a/chrome/installer/setup/setup_util.h
+++ b/chrome/installer/setup/setup_util.h
@@ -9,16 +9,13 @@
 #ifndef CHROME_INSTALLER_SETUP_SETUP_UTIL_H_
 #define CHROME_INSTALLER_SETUP_SETUP_UTIL_H_
 
-#include <windows.h>
 #include <stdint.h>
 
 #include <memory>
 #include <vector>
 
-#include "base/macros.h"
 #include "base/strings/string16.h"
 #include "base/time/time.h"
-#include "base/win/scoped_handle.h"
 #include "chrome/installer/util/browser_distribution.h"
 #include "chrome/installer/util/lzma_util.h"
 #include "chrome/installer/util/util_constants.h"
@@ -154,35 +151,6 @@
 // a null time in case of error.
 base::Time GetConsoleSessionStartTime();
 
-// This class will enable the privilege defined by |privilege_name| on the
-// current process' token. The privilege will be disabled upon the
-// ScopedTokenPrivilege's destruction (unless it was already enabled when the
-// ScopedTokenPrivilege object was constructed).
-// Some privileges might require admin rights to be enabled (check is_enabled()
-// to know whether |privilege_name| was successfully enabled).
-class ScopedTokenPrivilege {
- public:
-  explicit ScopedTokenPrivilege(const wchar_t* privilege_name);
-  ~ScopedTokenPrivilege();
-
-  // Always returns true unless the privilege could not be enabled.
-  bool is_enabled() const { return is_enabled_; }
-
- private:
-  // Always true unless the privilege could not be enabled.
-  bool is_enabled_;
-
-  // A scoped handle to the current process' token. This will be closed
-  // preemptively should enabling the privilege fail in the constructor.
-  base::win::ScopedHandle token_;
-
-  // The previous state of the privilege this object is responsible for. As set
-  // by AdjustTokenPrivileges() upon construction.
-  TOKEN_PRIVILEGES previous_privileges_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedTokenPrivilege);
-};
-
 }  // namespace installer
 
 #endif  // CHROME_INSTALLER_SETUP_SETUP_UTIL_H_
diff --git a/chrome/installer/setup/setup_util_unittest.cc b/chrome/installer/setup/setup_util_unittest.cc
index e3e705c..b3400b5 100644
--- a/chrome/installer/setup/setup_util_unittest.cc
+++ b/chrome/installer/setup/setup_util_unittest.cc
@@ -38,59 +38,6 @@
 #include "chrome/installer/util/util_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace {
-
-// The privilege tested in ScopeTokenPrivilege tests below.
-// Use SE_RESTORE_NAME as it is one of the many privileges that is available,
-// but not enabled by default on processes running at high integrity.
-static const wchar_t kTestedPrivilege[] = SE_RESTORE_NAME;
-
-// Returns true if the current process' token has privilege |privilege_name|
-// enabled.
-bool CurrentProcessHasPrivilege(const wchar_t* privilege_name) {
-  HANDLE temp_handle;
-  if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY,
-                          &temp_handle)) {
-    ADD_FAILURE();
-    return false;
-  }
-
-  base::win::ScopedHandle token(temp_handle);
-
-  // First get the size of the buffer needed for |privileges| below.
-  DWORD size;
-  EXPECT_FALSE(::GetTokenInformation(token.Get(), TokenPrivileges, NULL, 0,
-                                     &size));
-
-  std::unique_ptr<BYTE[]> privileges_bytes(new BYTE[size]);
-  TOKEN_PRIVILEGES* privileges =
-      reinterpret_cast<TOKEN_PRIVILEGES*>(privileges_bytes.get());
-
-  if (!::GetTokenInformation(token.Get(), TokenPrivileges, privileges, size,
-                             &size)) {
-    ADD_FAILURE();
-    return false;
-  }
-
-  // There is no point getting a buffer to store more than |privilege_name|\0 as
-  // anything longer will obviously not be equal to |privilege_name|.
-  const DWORD desired_size = static_cast<DWORD>(wcslen(privilege_name));
-  const DWORD buffer_size = desired_size + 1;
-  std::unique_ptr<wchar_t[]> name_buffer(new wchar_t[buffer_size]);
-  for (int i = privileges->PrivilegeCount - 1; i >= 0 ; --i) {
-    LUID_AND_ATTRIBUTES& luid_and_att = privileges->Privileges[i];
-    DWORD size = buffer_size;
-    ::LookupPrivilegeName(NULL, &luid_and_att.Luid, name_buffer.get(), &size);
-    if (size == desired_size &&
-        wcscmp(name_buffer.get(), privilege_name) == 0) {
-      return luid_and_att.Attributes == SE_PRIVILEGE_ENABLED;
-    }
-  }
-  return false;
-}
-
-}  // namespace
-
 // Test that we are parsing Chrome version correctly.
 TEST(SetupUtilTest, GetMaxVersionFromArchiveDirTest) {
   // Create a version dir
@@ -144,52 +91,6 @@
   EXPECT_FALSE(base::PathExists(test_file)) << test_file.value();
 }
 
-// Note: This test is only valid when run at high integrity (i.e. it will fail
-// at medium integrity).
-TEST(SetupUtilTest, ScopedTokenPrivilegeBasic) {
-  ASSERT_FALSE(CurrentProcessHasPrivilege(kTestedPrivilege));
-
-  if (!::IsUserAnAdmin()) {
-    LOG(WARNING) << "Skipping SetupUtilTest.ScopedTokenPrivilegeBasic due to "
-                    "not running as admin.";
-    return;
-  }
-
-  {
-    installer::ScopedTokenPrivilege test_scoped_privilege(kTestedPrivilege);
-    ASSERT_TRUE(test_scoped_privilege.is_enabled());
-    ASSERT_TRUE(CurrentProcessHasPrivilege(kTestedPrivilege));
-  }
-
-  ASSERT_FALSE(CurrentProcessHasPrivilege(kTestedPrivilege));
-}
-
-// Note: This test is only valid when run at high integrity (i.e. it will fail
-// at medium integrity).
-TEST(SetupUtilTest, ScopedTokenPrivilegeAlreadyEnabled) {
-  ASSERT_FALSE(CurrentProcessHasPrivilege(kTestedPrivilege));
-
-  if (!::IsUserAnAdmin()) {
-    LOG(WARNING) << "Skipping SetupUtilTest.ScopedTokenPrivilegeAlreadyEnabled "
-                    "due to not running as admin.";
-    return;
-  }
-
-  {
-    installer::ScopedTokenPrivilege test_scoped_privilege(kTestedPrivilege);
-    ASSERT_TRUE(test_scoped_privilege.is_enabled());
-    ASSERT_TRUE(CurrentProcessHasPrivilege(kTestedPrivilege));
-    {
-      installer::ScopedTokenPrivilege dup_scoped_privilege(kTestedPrivilege);
-      ASSERT_TRUE(dup_scoped_privilege.is_enabled());
-      ASSERT_TRUE(CurrentProcessHasPrivilege(kTestedPrivilege));
-    }
-    ASSERT_TRUE(CurrentProcessHasPrivilege(kTestedPrivilege));
-  }
-
-  ASSERT_FALSE(CurrentProcessHasPrivilege(kTestedPrivilege));
-}
-
 TEST(SetupUtilTest, GuidToSquid) {
   ASSERT_EQ(installer::GuidToSquid(L"EDA620E3-AA98-3846-B81E-3493CB2E0E02"),
             L"3E026ADE89AA64838BE14339BCE2E020");
diff --git a/chrome/installer/setup/user_hive_visitor.cc b/chrome/installer/setup/user_hive_visitor.cc
index e26f7c9..d28d8a7 100644
--- a/chrome/installer/setup/user_hive_visitor.cc
+++ b/chrome/installer/setup/user_hive_visitor.cc
@@ -18,7 +18,7 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/win/registry.h"
-#include "chrome/installer/setup/setup_util.h"
+#include "chrome/installer/util/scoped_token_privilege.h"
 #include "components/base32/base32.h"
 
 namespace installer {
diff --git a/chrome/installer/util/BUILD.gn b/chrome/installer/util/BUILD.gn
index ca2c3f1..e545edf 100644
--- a/chrome/installer/util/BUILD.gn
+++ b/chrome/installer/util/BUILD.gn
@@ -76,6 +76,8 @@
       "product_operations.h",
       "registry_entry.cc",
       "registry_entry.h",
+      "scoped_token_privilege.cc",
+      "scoped_token_privilege.h",
       "scoped_user_protocol_entry.cc",
       "scoped_user_protocol_entry.h",
       "self_cleaning_temp_dir.cc",
@@ -310,6 +312,7 @@
       "registry_test_data.cc",
       "registry_test_data.h",
       "run_all_unittests.cc",
+      "scoped_token_privilege_unittest.cc",
       "scoped_user_protocol_entry_unittest.cc",
       "self_cleaning_temp_dir_unittest.cc",
       "set_reg_value_work_item_unittest.cc",
diff --git a/chrome/installer/util/scoped_token_privilege.cc b/chrome/installer/util/scoped_token_privilege.cc
new file mode 100644
index 0000000..840a75fa
--- /dev/null
+++ b/chrome/installer/util/scoped_token_privilege.cc
@@ -0,0 +1,50 @@
+// Copyright 2017 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 "chrome/installer/util/scoped_token_privilege.h"
+
+namespace installer {
+
+ScopedTokenPrivilege::ScopedTokenPrivilege(const wchar_t* privilege_name)
+    : is_enabled_(false) {
+  HANDLE temp_handle;
+  if (!::OpenProcessToken(::GetCurrentProcess(),
+                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
+                          &temp_handle)) {
+    return;
+  }
+  token_.Set(temp_handle);
+
+  LUID privilege_luid;
+  if (!::LookupPrivilegeValue(NULL, privilege_name, &privilege_luid)) {
+    token_.Close();
+    return;
+  }
+
+  // Adjust the token's privileges to enable |privilege_name|. If this privilege
+  // was already enabled, |previous_privileges_|.PrivilegeCount will be set to 0
+  // and we then know not to disable this privilege upon destruction.
+  TOKEN_PRIVILEGES tp;
+  tp.PrivilegeCount = 1;
+  tp.Privileges[0].Luid = privilege_luid;
+  tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+  DWORD return_length;
+  if (!::AdjustTokenPrivileges(token_.Get(), FALSE, &tp,
+                               sizeof(TOKEN_PRIVILEGES), &previous_privileges_,
+                               &return_length)) {
+    token_.Close();
+    return;
+  }
+
+  is_enabled_ = true;
+}
+
+ScopedTokenPrivilege::~ScopedTokenPrivilege() {
+  if (is_enabled_ && previous_privileges_.PrivilegeCount != 0) {
+    ::AdjustTokenPrivileges(token_.Get(), FALSE, &previous_privileges_,
+                            sizeof(TOKEN_PRIVILEGES), NULL, NULL);
+  }
+}
+
+}  // namespace installer
diff --git a/chrome/installer/util/scoped_token_privilege.h b/chrome/installer/util/scoped_token_privilege.h
new file mode 100644
index 0000000..3def5eb6
--- /dev/null
+++ b/chrome/installer/util/scoped_token_privilege.h
@@ -0,0 +1,46 @@
+// Copyright 2017 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_INSTALLER_UTIL_SCOPED_TOKEN_PRIVILEGE_H_
+#define CHROME_INSTALLER_UTIL_SCOPED_TOKEN_PRIVILEGE_H_
+
+#include <windows.h>
+
+#include "base/macros.h"
+#include "base/win/scoped_handle.h"
+
+namespace installer {
+
+// This class is available for Windows only and will enable the privilege
+// defined by |privilege_name| on the current process' token. The privilege will
+// be disabled upon the ScopedTokenPrivilege's destruction (unless it was
+// already enabled when the ScopedTokenPrivilege object was constructed).
+// Some privileges might require admin rights to be enabled (check is_enabled()
+// to know whether |privilege_name| was successfully enabled).
+class ScopedTokenPrivilege {
+ public:
+  explicit ScopedTokenPrivilege(const wchar_t* privilege_name);
+  ~ScopedTokenPrivilege();
+
+  // Always returns true unless the privilege could not be enabled.
+  bool is_enabled() const { return is_enabled_; }
+
+ private:
+  // Always true unless the privilege could not be enabled.
+  bool is_enabled_;
+
+  // A scoped handle to the current process' token. This will be closed
+  // preemptively should enabling the privilege fail in the constructor.
+  base::win::ScopedHandle token_;
+
+  // The previous state of the privilege this object is responsible for. As set
+  // by AdjustTokenPrivileges() upon construction.
+  TOKEN_PRIVILEGES previous_privileges_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedTokenPrivilege);
+};
+
+}  // namespace installer
+
+#endif  // CHROME_INSTALLER_UTIL_SCOPED_TOKEN_PRIVILEGE_H_
diff --git a/chrome/installer/util/scoped_token_privilege_unittest.cc b/chrome/installer/util/scoped_token_privilege_unittest.cc
new file mode 100644
index 0000000..cbd75388
--- /dev/null
+++ b/chrome/installer/util/scoped_token_privilege_unittest.cc
@@ -0,0 +1,111 @@
+// Copyright 2017 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 "chrome/installer/util/scoped_token_privilege.h"
+
+#include <shlobj.h>
+#include <memory>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace installer {
+namespace {
+
+// The privilege tested in ScopeTokenPrivilege tests below.
+// Use SE_RESTORE_NAME as it is one of the many privileges that is available,
+// but not enabled by default on processes running at high integrity.
+constexpr wchar_t kTestedPrivilege[] = SE_RESTORE_NAME;
+
+// Returns true if the current process' token has privilege |privilege_name|
+// enabled.
+bool CurrentProcessHasPrivilege(const wchar_t* privilege_name) {
+  HANDLE temp_handle;
+  if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &temp_handle)) {
+    ADD_FAILURE();
+    return false;
+  }
+
+  base::win::ScopedHandle token(temp_handle);
+
+  // First get the size of the buffer needed for |privileges| below.
+  DWORD size;
+  EXPECT_FALSE(
+      ::GetTokenInformation(token.Get(), TokenPrivileges, NULL, 0, &size));
+
+  std::unique_ptr<BYTE[]> privileges_bytes(new BYTE[size]);
+  TOKEN_PRIVILEGES* privileges =
+      reinterpret_cast<TOKEN_PRIVILEGES*>(privileges_bytes.get());
+
+  if (!::GetTokenInformation(token.Get(), TokenPrivileges, privileges, size,
+                             &size)) {
+    ADD_FAILURE();
+    return false;
+  }
+
+  // There is no point getting a buffer to store more than |privilege_name|\0 as
+  // anything longer will obviously not be equal to |privilege_name|.
+  const DWORD desired_size = static_cast<DWORD>(wcslen(privilege_name));
+  const DWORD buffer_size = desired_size + 1;
+  std::unique_ptr<wchar_t[]> name_buffer(new wchar_t[buffer_size]);
+  for (int i = privileges->PrivilegeCount - 1; i >= 0; --i) {
+    LUID_AND_ATTRIBUTES& luid_and_att = privileges->Privileges[i];
+    DWORD size = buffer_size;
+    ::LookupPrivilegeName(NULL, &luid_and_att.Luid, name_buffer.get(), &size);
+    if (size == desired_size &&
+        wcscmp(name_buffer.get(), privilege_name) == 0) {
+      return luid_and_att.Attributes == SE_PRIVILEGE_ENABLED;
+    }
+  }
+  return false;
+}
+
+}  // namespace
+
+// Note: This test is only valid when run at high integrity (i.e. it will fail
+// at medium integrity).
+TEST(ScopedTokenPrivilegeTest, Basic) {
+  ASSERT_FALSE(CurrentProcessHasPrivilege(kTestedPrivilege));
+
+  if (!::IsUserAnAdmin()) {
+    LOG(WARNING) << "Skipping SetupUtilTest.ScopedTokenPrivilegeBasic due to "
+                    "not running as admin.";
+    return;
+  }
+
+  {
+    ScopedTokenPrivilege test_scoped_privilege(kTestedPrivilege);
+    ASSERT_TRUE(test_scoped_privilege.is_enabled());
+    ASSERT_TRUE(CurrentProcessHasPrivilege(kTestedPrivilege));
+  }
+
+  ASSERT_FALSE(CurrentProcessHasPrivilege(kTestedPrivilege));
+}
+
+// Note: This test is only valid when run at high integrity (i.e. it will fail
+// at medium integrity).
+TEST(ScopedTokenPrivilegeTest, AlreadyEnabled) {
+  ASSERT_FALSE(CurrentProcessHasPrivilege(kTestedPrivilege));
+
+  if (!::IsUserAnAdmin()) {
+    LOG(WARNING) << "Skipping SetupUtilTest.ScopedTokenPrivilegeAlreadyEnabled "
+                    "due to not running as admin.";
+    return;
+  }
+
+  {
+    ScopedTokenPrivilege test_scoped_privilege(kTestedPrivilege);
+    ASSERT_TRUE(test_scoped_privilege.is_enabled());
+    ASSERT_TRUE(CurrentProcessHasPrivilege(kTestedPrivilege));
+    {
+      ScopedTokenPrivilege dup_scoped_privilege(kTestedPrivilege);
+      ASSERT_TRUE(dup_scoped_privilege.is_enabled());
+      ASSERT_TRUE(CurrentProcessHasPrivilege(kTestedPrivilege));
+    }
+    ASSERT_TRUE(CurrentProcessHasPrivilege(kTestedPrivilege));
+  }
+
+  ASSERT_FALSE(CurrentProcessHasPrivilege(kTestedPrivilege));
+}
+
+}  // namespace installer
diff --git a/chrome/service/service_process_prefs.cc b/chrome/service/service_process_prefs.cc
index e829880f..29bb98e 100644
--- a/chrome/service/service_process_prefs.cc
+++ b/chrome/service/service_process_prefs.cc
@@ -24,7 +24,7 @@
 }
 
 void ServiceProcessPrefs::WritePrefs() {
-  prefs_->CommitPendingWrite();
+  prefs_->CommitPendingWrite(base::OnceClosure());
 }
 
 std::string ServiceProcessPrefs::GetString(
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 6d128ec..e7fa182 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1008,6 +1008,13 @@
       "//testing/xvfb.py",
       "//testing/scripts/run_telemetry_as_googletest.py",
     ]
+
+    if (enable_package_mash_services) {
+      deps += [ "//chrome:chrome_test" ]
+      data_deps = [
+        "//chrome:chrome_test",
+      ]
+    }
   }
 
   group("telemetry_gpu_unittests_run") {
@@ -2886,6 +2893,13 @@
     "//testing/xvfb.py",
     "//testing/scripts/run_telemetry_as_googletest.py",
   ]
+
+  if (enable_package_mash_services) {
+    deps += [ "//chrome:chrome_test" ]
+    data_deps = [
+      "//chrome:chrome_test",
+    ]
+  }
 }
 
 group("telemetry_perf_tests") {
@@ -4118,7 +4132,9 @@
       sources +=
           [ "../browser/extensions/external_registry_loader_win_unittest.cc" ]
     }
-    if (!is_chromeos) {
+    if (is_chromeos) {
+      sources += [ "../browser/extensions/api/file_system/consent_provider_unittest.cc" ]
+    } else {
       sources += [
         "../browser/extensions/api/messaging/native_message_process_host_unittest.cc",
         "../browser/extensions/api/messaging/native_messaging_host_manifest_unittest.cc",
diff --git a/chrome/test/data/webui/settings/chrome_cleanup_page_test.js b/chrome/test/data/webui/settings/chrome_cleanup_page_test.js
index cd619a6..9af4c29 100644
--- a/chrome/test/data/webui/settings/chrome_cleanup_page_test.js
+++ b/chrome/test/data/webui/settings/chrome_cleanup_page_test.js
@@ -10,8 +10,7 @@
 var TestChromeCleanupProxy = function() {
   TestBrowserProxy.call(this, [
     'dismissCleanupPage',
-    'getChromeCleanupVisibility',
-    'registerChromeCleanupObserver',
+    'registerChromeCleanerObserver',
     'restartComputer',
     'startCleanup',
   ]);
@@ -25,22 +24,17 @@
     this.methodCalled('dismissCleanupPage');
   },
 
-    /** @override */
-  getChromeCleanupVisibility: function() {
-    this.methodCalled('getChromeCleanupVisibility');
+  /** @override */
+  registerChromeCleanerObserver: function() {
+    this.methodCalled('registerChromeCleanerObserver');
   },
 
-    /** @override */
-  registerChromeCleanupObserver: function() {
-    this.methodCalled('registerChromeCleanupObserver');
-  },
-
-    /** @override */
+  /** @override */
   restartComputer: function() {
     this.methodCalled('restartComputer');
   },
 
-    /** @override */
+  /** @override */
   startCleanup: function() {
     this.methodCalled('startCleanup');
   },
diff --git a/chromecast/base/pref_names.cc b/chromecast/base/pref_names.cc
index 237f1336..b7b1b54e 100644
--- a/chromecast/base/pref_names.cc
+++ b/chromecast/base/pref_names.cc
@@ -7,9 +7,6 @@
 namespace chromecast {
 namespace prefs {
 
-// Boolean which specifies if remote debugging is enabled
-const char kEnableRemoteDebugging[] = "enable_remote_debugging";
-
 // Boolean that specifies whether or not the client_id has been regenerated
 // due to bug b/9487011.
 const char kMetricsIsNewClientID[] = "user_experience_metrics.is_new_client_id";
diff --git a/chromecast/base/pref_names.h b/chromecast/base/pref_names.h
index 7454885d..bc415e9c 100644
--- a/chromecast/base/pref_names.h
+++ b/chromecast/base/pref_names.h
@@ -8,7 +8,6 @@
 namespace chromecast {
 namespace prefs {
 
-extern const char kEnableRemoteDebugging[];
 extern const char kMetricsIsNewClientID[];
 extern const char kOptInStats[];
 extern const char kStabilityChildProcessCrashCount[];
diff --git a/chromecast/browser/cast_browser_process.h b/chromecast/browser/cast_browser_process.h
index bff6626..581d45e 100644
--- a/chromecast/browser/cast_browser_process.h
+++ b/chromecast/browser/cast_browser_process.h
@@ -74,6 +74,9 @@
   ConnectivityChecker* connectivity_checker() const {
     return connectivity_checker_.get();
   }
+  RemoteDebuggingServer* remote_debugging_server() const {
+    return remote_debugging_server_.get();
+  }
   net::NetLog* net_log() const { return net_log_; }
 
  private:
diff --git a/chromecast/browser/devtools/cast_devtools_manager_delegate.cc b/chromecast/browser/devtools/cast_devtools_manager_delegate.cc
index 9a34675..0800bb7 100644
--- a/chromecast/browser/devtools/cast_devtools_manager_delegate.cc
+++ b/chromecast/browser/devtools/cast_devtools_manager_delegate.cc
@@ -54,6 +54,10 @@
   enabled_webcontents_.erase(web_contents);
 }
 
+bool CastDevToolsManagerDelegate::HasEnabledWebContents() const {
+  return !enabled_webcontents_.empty();
+}
+
 std::string CastDevToolsManagerDelegate::GetDiscoveryPageHTML() {
 #if defined(OS_ANDROID)
   return std::string();
diff --git a/chromecast/browser/devtools/cast_devtools_manager_delegate.h b/chromecast/browser/devtools/cast_devtools_manager_delegate.h
index c3e5c7865..113bb80 100644
--- a/chromecast/browser/devtools/cast_devtools_manager_delegate.h
+++ b/chromecast/browser/devtools/cast_devtools_manager_delegate.h
@@ -29,6 +29,7 @@
 
   void EnableWebContentsForDebugging(content::WebContents* web_contents);
   void DisableWebContentsForDebugging(content::WebContents* web_contents);
+  bool HasEnabledWebContents() const;
 
   // content::DevToolsManagerDelegate implementation.
   content::DevToolsAgentHost::List RemoteDebuggingTargets() override;
diff --git a/chromecast/browser/devtools/remote_debugging_server.cc b/chromecast/browser/devtools/remote_debugging_server.cc
index bf2681dc..89bbde9 100644
--- a/chromecast/browser/devtools/remote_debugging_server.cc
+++ b/chromecast/browser/devtools/remote_debugging_server.cc
@@ -12,7 +12,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "build/build_config.h"
-#include "chromecast/base/pref_names.h"
 #include "chromecast/browser/cast_browser_process.h"
 #include "chromecast/browser/devtools/cast_devtools_manager_delegate.h"
 #include "chromecast/common/cast_content_client.h"
@@ -120,43 +119,39 @@
   return base::StringPrintf(kFrontEndURL, content::GetWebKitRevision().c_str());
 }
 
-}  // namespace
-
-RemoteDebuggingServer::RemoteDebuggingServer(bool start_immediately)
-    : port_(kDefaultRemoteDebuggingPort),
-      is_started_(false) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  pref_enabled_.Init(prefs::kEnableRemoteDebugging,
-                     CastBrowserProcess::GetInstance()->pref_service(),
-                     base::Bind(&RemoteDebuggingServer::OnEnabledChanged,
-                                base::Unretained(this)));
-
+uint16_t GetPort() {
   std::string port_str =
       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
           switches::kRemoteDebuggingPort);
-  if (!port_str.empty()) {
-    int port = kDefaultRemoteDebuggingPort;
-    if (base::StringToInt(port_str, &port)) {
-      port_ = static_cast<uint16_t>(port);
-    } else {
-      port_ = kDefaultRemoteDebuggingPort;
-    }
-  }
 
-  // Starts new dev tools, clearing port number saved in config.
-  // Remote debugging in production must be triggered only by config server.
-  pref_enabled_.SetValue(start_immediately && port_ != 0);
-  OnEnabledChanged();
+  if (port_str.empty())
+    return kDefaultRemoteDebuggingPort;
+
+  int port;
+  if (base::StringToInt(port_str, &port))
+    return port;
+
+  return kDefaultRemoteDebuggingPort;
+}
+
+}  // namespace
+
+RemoteDebuggingServer::RemoteDebuggingServer(bool start_immediately)
+    : port_(GetPort()), is_started_(false) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 }
 
 RemoteDebuggingServer::~RemoteDebuggingServer() {
-  pref_enabled_.SetValue(false);
-  OnEnabledChanged();
+  if (is_started_) {
+    content::DevToolsAgentHost::StopRemoteDebuggingServer();
+  }
 }
 
-void RemoteDebuggingServer::OnEnabledChanged() {
-  bool enabled = *pref_enabled_ && port_ != 0;
-  if (enabled && !is_started_) {
+void RemoteDebuggingServer::EnableWebContentsForDebugging(
+    content::WebContents* web_contents) {
+  DCHECK(web_contents);
+
+  if (!is_started_) {
     content::DevToolsAgentHost::StartRemoteDebuggingServer(
         CreateSocketFactory(port_),
         GetFrontendUrl(),
@@ -165,10 +160,26 @@
         std::string(),
         GetUserAgent());
     LOG(INFO) << "Devtools started: port=" << port_;
-  } else if (!enabled && is_started_) {
-    LOG(INFO) << "Stop devtools: port=" << port_;
-    is_started_ = false;
+    is_started_ = true;
+  }
+
+  auto* dev_tools_delegate =
+      chromecast::shell::CastDevToolsManagerDelegate::GetInstance();
+  DCHECK(dev_tools_delegate);
+  dev_tools_delegate->EnableWebContentsForDebugging(web_contents);
+}
+
+void RemoteDebuggingServer::DisableWebContentsForDebugging(
+    content::WebContents* web_contents) {
+  DCHECK(web_contents);
+  auto* dev_tools_delegate =
+      chromecast::shell::CastDevToolsManagerDelegate::GetInstance();
+  DCHECK(dev_tools_delegate);
+  dev_tools_delegate->DisableWebContentsForDebugging(web_contents);
+
+  if (is_started_ && !dev_tools_delegate->HasEnabledWebContents()) {
     content::DevToolsAgentHost::StopRemoteDebuggingServer();
+    is_started_ = false;
   }
 }
 
diff --git a/chromecast/browser/devtools/remote_debugging_server.h b/chromecast/browser/devtools/remote_debugging_server.h
index e0aefe4e..200bfaf5 100644
--- a/chromecast/browser/devtools/remote_debugging_server.h
+++ b/chromecast/browser/devtools/remote_debugging_server.h
@@ -10,7 +10,10 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "components/prefs/pref_member.h"
+
+namespace content {
+class WebContents;
+}  // namespace content
 
 namespace chromecast {
 namespace shell {
@@ -20,10 +23,13 @@
   explicit RemoteDebuggingServer(bool start_immediately);
   ~RemoteDebuggingServer();
 
+  // Allows this WebContents to be debugged.
+  void EnableWebContentsForDebugging(content::WebContents* web_contents);
+
+  // Disables remote debugging for this web contents.
+  void DisableWebContentsForDebugging(content::WebContents* web_contents);
+
  private:
-  // Called when pref_enabled_ is changed.
-  void OnEnabledChanged();
-  BooleanPrefMember pref_enabled_;
   uint16_t port_;
   bool is_started_;
 
diff --git a/chromecast/browser/pref_service_helper.cc b/chromecast/browser/pref_service_helper.cc
index 9f1c643..72abc91 100644
--- a/chromecast/browser/pref_service_helper.cc
+++ b/chromecast/browser/pref_service_helper.cc
@@ -44,7 +44,6 @@
   const base::FilePath config_path(GetConfigPath());
   VLOG(1) << "Loading config from " << config_path.value();
 
-  registry->RegisterBooleanPref(prefs::kEnableRemoteDebugging, false);
   registry->RegisterBooleanPref(prefs::kMetricsIsNewClientID, false);
   // Opt-in stats default to true to handle two different cases:
   //  1) Any crashes or UMA logs are recorded prior to setup completing
diff --git a/components/cronet/android/cronet_url_request_context_adapter.cc b/components/cronet/android/cronet_url_request_context_adapter.cc
index ffe89c8..e8e65b4 100644
--- a/components/cronet/android/cronet_url_request_context_adapter.cc
+++ b/components/cronet/android/cronet_url_request_context_adapter.cc
@@ -690,10 +690,6 @@
         std::unique_ptr<net::ExternalEstimateProvider>(),
         base::MakeUnique<net::NetworkQualityEstimatorParams>(variation_params),
         g_net_log.Get().net_log());
-    // Set the socket performance watcher factory so that network quality
-    // estimator is notified of socket performance metrics from TCP and QUIC.
-    context_builder.set_socket_performance_watcher_factory(
-        network_quality_estimator_->GetSocketPerformanceWatcherFactory());
     network_quality_estimator_->AddEffectiveConnectionTypeObserver(this);
     network_quality_estimator_->AddRTTAndThroughputEstimatesObserver(this);
 
@@ -707,6 +703,8 @@
       network_qualities_prefs_manager_->InitializeOnNetworkThread(
           network_quality_estimator_.get());
     }
+    context_builder.set_network_quality_estimator(
+        network_quality_estimator_.get());
   }
 
   context_ = context_builder.Build();
@@ -714,9 +712,6 @@
   context_->set_check_cleartext_permitted(true);
   context_->set_enable_brotli(config->enable_brotli);
 
-  if (network_quality_estimator_)
-    context_->set_network_quality_estimator(network_quality_estimator_.get());
-
   if (config->load_disable_cache)
     default_load_flags_ |= net::LOAD_DISABLE_CACHE;
 
diff --git a/components/cryptauth/cryptauth_device_manager.cc b/components/cryptauth/cryptauth_device_manager.cc
index 3c7a3cf..0fa6a82 100644
--- a/components/cryptauth/cryptauth_device_manager.cc
+++ b/components/cryptauth/cryptauth_device_manager.cc
@@ -419,10 +419,22 @@
     const GetMyDevicesResponse& response) {
   // Update the synced devices stored in the user's prefs.
   std::unique_ptr<base::ListValue> devices_as_list(new base::ListValue());
+
+  if (!response.devices().empty())
+    PA_LOG(INFO) << "Devices were successfully synced.";
+
   for (const auto& device : response.devices()) {
-    devices_as_list->Append(UnlockKeyToDictionary(device));
+    std::unique_ptr<base::DictionaryValue> device_dictionary =
+        UnlockKeyToDictionary(device);
+
+    const std::string& device_name = device.has_friendly_device_name()
+                                         ? device.friendly_device_name()
+                                         : "[unknown]";
+    PA_LOG(INFO) << "Synced device '" << device_name
+                 << "': " << *device_dictionary;
+
+    devices_as_list->Append(std::move(device_dictionary));
   }
-  PA_LOG(INFO) << "Devices Synced:\n" << *devices_as_list;
 
   bool unlock_keys_changed = !devices_as_list->Equals(
       pref_service_->GetList(prefs::kCryptAuthDeviceSyncUnlockKeys));
diff --git a/components/ntp_snippets/BUILD.gn b/components/ntp_snippets/BUILD.gn
index 3ec1da73..8e08151a 100644
--- a/components/ntp_snippets/BUILD.gn
+++ b/components/ntp_snippets/BUILD.gn
@@ -15,6 +15,8 @@
     "bookmarks/bookmark_last_visit_utils.h",
     "bookmarks/bookmark_suggestions_provider.cc",
     "bookmarks/bookmark_suggestions_provider.h",
+    "breaking_news/content_suggestions_gcm_app_handler.cc",
+    "breaking_news/content_suggestions_gcm_app_handler.h",
     "breaking_news/subscription_json_request.cc",
     "breaking_news/subscription_json_request.h",
     "breaking_news/subscription_manager.cc",
@@ -107,6 +109,7 @@
     "//components/data_use_measurement/core",
     "//components/favicon/core",
     "//components/favicon_base",
+    "//components/gcm_driver",
     "//components/history/core/browser",
     "//components/image_fetcher/core",
     "//components/metrics",
diff --git a/components/ntp_snippets/DEPS b/components/ntp_snippets/DEPS
index 777f897e..6af85ea 100644
--- a/components/ntp_snippets/DEPS
+++ b/components/ntp_snippets/DEPS
@@ -2,6 +2,7 @@
   "+components/data_use_measurement/core",
   "+components/favicon/core",
   "+components/favicon_base",
+  "+components/gcm_driver",
   "+components/history/core",
   "+components/image_fetcher",
   "+components/keyed_service/core",
diff --git a/components/ntp_snippets/breaking_news/content_suggestions_gcm_app_handler.cc b/components/ntp_snippets/breaking_news/content_suggestions_gcm_app_handler.cc
new file mode 100644
index 0000000..4ea1acc6
--- /dev/null
+++ b/components/ntp_snippets/breaking_news/content_suggestions_gcm_app_handler.cc
@@ -0,0 +1,144 @@
+// Copyright 2017 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/ntp_snippets/breaking_news/content_suggestions_gcm_app_handler.h"
+
+#include "base/strings/string_util.h"
+#include "components/gcm_driver/gcm_driver.h"
+#include "components/gcm_driver/gcm_profile_service.h"
+#include "components/gcm_driver/instance_id/instance_id.h"
+#include "components/gcm_driver/instance_id/instance_id_driver.h"
+#include "components/ntp_snippets/pref_names.h"
+
+using instance_id::InstanceID;
+
+namespace ntp_snippets {
+
+const char kContentSuggestionsGCMAppID[] = "com.google.contentsuggestions.gcm";
+
+// The sender ID is used in the registration process.
+// See: https://developers.google.com/cloud-messaging/gcm#senderid
+const char kContentSuggestionsGCMSenderId[] = "128223710667";
+
+// OAuth2 Scope passed to getToken to obtain GCM registration tokens.
+// Must match Java GoogleCloudMessaging.INSTANCE_ID_SCOPE.
+const char kGCMScope[] = "GCM";
+
+ContentSuggestionsGCMAppHandler::ContentSuggestionsGCMAppHandler(
+    gcm::GCMDriver* gcm_driver,
+    instance_id::InstanceIDDriver* instance_id_driver,
+    PrefService* pref_service,
+    std::unique_ptr<SubscriptionManager> subscription_manager)
+    : gcm_driver_(gcm_driver),
+      instance_id_driver_(instance_id_driver),
+      pref_service_(pref_service),
+      subscription_manager_(std::move(subscription_manager)),
+      weak_factory_(this) {}
+
+ContentSuggestionsGCMAppHandler::~ContentSuggestionsGCMAppHandler() {
+  StopListening();
+}
+
+void ContentSuggestionsGCMAppHandler::StartListening() {
+#if !defined(OS_ANDROID)
+  NOTREACHED()
+      << "The ContentSuggestionsGCMAppHandler should only be used on Android.";
+#endif
+  Subscribe();
+  gcm_driver_->AddAppHandler(kContentSuggestionsGCMAppID, this);
+}
+
+void ContentSuggestionsGCMAppHandler::StopListening() {
+  DCHECK_EQ(gcm_driver_->GetAppHandler(kContentSuggestionsGCMAppID), this);
+  gcm_driver_->RemoveAppHandler(kContentSuggestionsGCMAppID);
+  std::string token = pref_service_->GetString(
+      ntp_snippets::prefs::kContentSuggestionsGCMSubscriptionTokenCache);
+  subscription_manager_->Unsubscribe(token);
+}
+
+void ContentSuggestionsGCMAppHandler::Subscribe() {
+  std::string token = pref_service_->GetString(
+      ntp_snippets::prefs::kContentSuggestionsGCMSubscriptionTokenCache);
+  // If a token has been already obtained, subscribe directly at the content
+  // suggestions server.
+  if (!token.empty()) {
+    if (!subscription_manager_->IsSubscribed()) {
+      subscription_manager_->Subscribe(token);
+    }
+    return;
+  }
+
+  instance_id_driver_->GetInstanceID(kContentSuggestionsGCMAppID)
+      ->GetToken(kContentSuggestionsGCMSenderId, kGCMScope,
+                 std::map<std::string, std::string>() /* options */,
+                 base::Bind(&ContentSuggestionsGCMAppHandler::DidSubscribe,
+                            weak_factory_.GetWeakPtr()));
+}
+
+void ContentSuggestionsGCMAppHandler::DidSubscribe(
+    const std::string& subscription_id,
+    InstanceID::Result result) {
+  switch (result) {
+    case InstanceID::SUCCESS:
+      pref_service_->SetString(
+          ntp_snippets::prefs::kContentSuggestionsGCMSubscriptionTokenCache,
+          subscription_id);
+      subscription_manager_->Subscribe(subscription_id);
+      return;
+    case InstanceID::INVALID_PARAMETER:
+    case InstanceID::DISABLED:
+    case InstanceID::ASYNC_OPERATION_PENDING:
+    case InstanceID::SERVER_ERROR:
+    case InstanceID::UNKNOWN_ERROR:
+      DLOG(WARNING)
+          << "Push messaging subscription failed; InstanceID::Result = "
+          << result;
+      break;
+    case InstanceID::NETWORK_ERROR:
+      break;
+  }
+}
+
+void ContentSuggestionsGCMAppHandler::ShutdownHandler() {}
+
+void ContentSuggestionsGCMAppHandler::OnStoreReset() {
+  pref_service_->ClearPref(
+      ntp_snippets::prefs::kContentSuggestionsGCMSubscriptionTokenCache);
+}
+
+void ContentSuggestionsGCMAppHandler::OnMessage(
+    const std::string& app_id,
+    const gcm::IncomingMessage& message) {
+  // TODO(mamir): Implement Show notification and update the feed.
+}
+
+void ContentSuggestionsGCMAppHandler::OnMessagesDeleted(
+    const std::string& app_id) {
+  // Messages don't get deleted.
+  NOTREACHED() << "ContentSuggestionsGCMAppHandler messages don't get deleted.";
+}
+
+void ContentSuggestionsGCMAppHandler::OnSendError(
+    const std::string& app_id,
+    const gcm::GCMClient::SendErrorDetails& details) {
+  // Should never be called because we don't send GCM messages to
+  // the server.
+  NOTREACHED() << "ContentSuggestionsGCMAppHandler doesn't send GCM messages.";
+}
+
+void ContentSuggestionsGCMAppHandler::OnSendAcknowledged(
+    const std::string& app_id,
+    const std::string& message_id) {
+  // Should never be called because we don't send GCM messages to
+  // the server.
+  NOTREACHED() << "ContentSuggestionsGCMAppHandler doesn't send GCM messages.";
+}
+
+void ContentSuggestionsGCMAppHandler::RegisterProfilePrefs(
+    PrefRegistrySimple* registry) {
+  registry->RegisterStringPref(
+      prefs::kContentSuggestionsGCMSubscriptionTokenCache, std::string());
+}
+
+}  // namespace ntp_snippets
diff --git a/components/ntp_snippets/breaking_news/content_suggestions_gcm_app_handler.h b/components/ntp_snippets/breaking_news/content_suggestions_gcm_app_handler.h
new file mode 100644
index 0000000..6636757
--- /dev/null
+++ b/components/ntp_snippets/breaking_news/content_suggestions_gcm_app_handler.h
@@ -0,0 +1,83 @@
+// Copyright 2017 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 COMPONENTS_NTP_SNIPPETS_BREAKING_NEWS_CONTENT_SUGGESTIONS_GCM_APP_HANDLER_H_
+#define COMPONENTS_NTP_SNIPPETS_BREAKING_NEWS_CONTENT_SUGGESTIONS_GCM_APP_HANDLER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "components/gcm_driver/gcm_app_handler.h"
+#include "components/gcm_driver/instance_id/instance_id.h"
+#include "components/ntp_snippets/breaking_news/subscription_manager.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+
+class PrefRegistrySimple;
+
+namespace gcm {
+class GCMDriver;
+}
+
+namespace instance_id {
+class InstanceIDDriver;
+}
+
+namespace ntp_snippets {
+
+// Handler for pushed GCM content suggestions. It retrieves a subscription token
+// from the GCM server and registers/unregisters itself with the GCM service to
+// be called upon received push content suggestions.
+class ContentSuggestionsGCMAppHandler : public gcm::GCMAppHandler {
+ public:
+  ContentSuggestionsGCMAppHandler(
+      gcm::GCMDriver* gcm_driver,
+      instance_id::InstanceIDDriver* instance_id_driver,
+      PrefService* pref_service_,
+      std::unique_ptr<SubscriptionManager> subscription_manager);
+
+  // If still listening, calls StopListening()
+  ~ContentSuggestionsGCMAppHandler() override;
+
+  // Subscribe to the GCM service if necessary and start listening for pushed
+  // content suggestions. Must not be called if already listening.
+  void StartListening();
+
+  // Remove the handler, and stop listening for incoming GCM messages. Any
+  // further pushed content suggestions will be ignored. Must be called while
+  // listening.
+  void StopListening();
+
+  // GCMAppHandler overrides.
+  void ShutdownHandler() override;
+  void OnStoreReset() override;
+  void OnMessage(const std::string& app_id,
+                 const gcm::IncomingMessage& message) override;
+  void OnMessagesDeleted(const std::string& app_id) override;
+  void OnSendError(const std::string& app_id,
+                   const gcm::GCMClient::SendErrorDetails& details) override;
+  void OnSendAcknowledged(const std::string& app_id,
+                          const std::string& message_id) override;
+
+  static void RegisterProfilePrefs(PrefRegistrySimple* registry);
+
+ private:
+  // Retrieves a subscription token that allows the content suggestions server
+  // to push content via GCM messages. Calling this method multiple times is not
+  // necessary but does not harm since the same token is returned everytime.
+  void Subscribe();
+
+  // Called after the subscription is obtained from the GCM server.
+  void DidSubscribe(const std::string& subscription_id,
+                    instance_id::InstanceID::Result result);
+
+  gcm::GCMDriver* const gcm_driver_;
+  instance_id::InstanceIDDriver* const instance_id_driver_;
+  PrefService* const pref_service_;
+  const std::unique_ptr<SubscriptionManager> subscription_manager_;
+  base::WeakPtrFactory<ContentSuggestionsGCMAppHandler> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(ContentSuggestionsGCMAppHandler);
+};
+}  // namespace ntp_snippets
+
+#endif  // COMPONENTS_NTP_SNIPPETS_BREAKING_NEWS_CONTENT_SUGGESTIONS_GCM_APP_HANDLER_H_
diff --git a/components/ntp_snippets/breaking_news/subscription_manager.cc b/components/ntp_snippets/breaking_news/subscription_manager.cc
index 8f7dbc9..42495e8 100644
--- a/components/ntp_snippets/breaking_news/subscription_manager.cc
+++ b/components/ntp_snippets/breaking_news/subscription_manager.cc
@@ -15,10 +15,12 @@
 SubscriptionManager::SubscriptionManager(
     scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
     PrefService* pref_service,
-    const GURL& subscribe_url)
+    const GURL& subscribe_url,
+    const GURL& unsubscribe_url)
     : url_request_context_getter_(std::move(url_request_context_getter)),
       pref_service_(pref_service),
-      subscribe_url_(subscribe_url) {}
+      subscribe_url_(subscribe_url),
+      unsubscribe_url_(unsubscribe_url) {}
 
 SubscriptionManager::~SubscriptionManager() = default;
 
@@ -35,6 +37,13 @@
       &SubscriptionManager::DidSubscribe, base::Unretained(this)));
 }
 
+bool SubscriptionManager::CanSubscribeNow() {
+  if (subscription_request_) {
+    return false;
+  }
+  return true;
+}
+
 void SubscriptionManager::DidSubscribe(const ntp_snippets::Status& status) {
   subscription_request_.reset();
 
@@ -54,8 +63,46 @@
   }
 }
 
+bool SubscriptionManager::CanUnsubscribeNow() {
+  if (unsubscription_request_) {
+    return false;
+  }
+  return true;
+}
+
 void SubscriptionManager::Unsubscribe(const std::string& token) {
-  // TODO(mamir): Implement.
+  DCHECK(!unsubscription_request_);
+  unsubscription_token_ = token;
+  SubscriptionJsonRequest::Builder builder;
+  builder.SetToken(token)
+      .SetUrlRequestContextGetter(url_request_context_getter_)
+      .SetUrl(unsubscribe_url_);
+
+  unsubscription_request_ = builder.Build();
+  unsubscription_request_->Start(base::BindOnce(
+      &SubscriptionManager::DidUnsubscribe, base::Unretained(this)));
+}
+
+bool SubscriptionManager::IsSubscribed() {
+  std::string subscription_token_ = pref_service_->GetString(
+      ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken);
+  return !subscription_token_.empty();
+}
+
+void SubscriptionManager::DidUnsubscribe(const ntp_snippets::Status& status) {
+  unsubscription_request_.reset();
+
+  switch (status.code) {
+    case ntp_snippets::StatusCode::SUCCESS:
+      // In case of successful unsubscription, clear the previously stored data.
+      // TODO(mamir): clear stored region and language.
+      pref_service_->ClearPref(
+          ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken);
+      break;
+    default:
+      // TODO(mamir): handle failure.
+      break;
+  }
 }
 
 void SubscriptionManager::RegisterProfilePrefs(PrefRegistrySimple* registry) {
diff --git a/components/ntp_snippets/breaking_news/subscription_manager.h b/components/ntp_snippets/breaking_news/subscription_manager.h
index e30447d..98336118 100644
--- a/components/ntp_snippets/breaking_news/subscription_manager.h
+++ b/components/ntp_snippets/breaking_news/subscription_manager.h
@@ -14,34 +14,47 @@
 
 namespace ntp_snippets {
 
+// Class that wraps around the functionality of SubscriptionJsonRequest. It uses
+// the SubscriptionJsonRequest to send subscription and unsubscription requests
+// to the content suggestions server and does the bookkeeping for the data used
+// for subscription. Bookkeeping is required to detect any change (e.g. the
+// token render invalid), and resubscribe accordingly.
 class SubscriptionManager {
  public:
   SubscriptionManager(
       scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
       PrefService* pref_service,
-      const GURL& subscribe_url);
+      const GURL& subscribe_url,
+      const GURL& unsubscribe_url);
 
   ~SubscriptionManager();
 
   void Subscribe(const std::string& token);
+  bool CanSubscribeNow();
   void Unsubscribe(const std::string& token);
+  bool CanUnsubscribeNow();
+  bool IsSubscribed();
 
   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
 
  private:
   std::string subscription_token_;
+  std::string unsubscription_token_;
 
   // Holds the URL request context.
   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
 
   std::unique_ptr<internal::SubscriptionJsonRequest> subscription_request_;
+  std::unique_ptr<internal::SubscriptionJsonRequest> unsubscription_request_;
 
   PrefService* pref_service_;
 
-  // API endpoint for subscribing.
+  // API endpoint for subscribing and unsubscribing.
   const GURL subscribe_url_;
+  const GURL unsubscribe_url_;
 
   void DidSubscribe(const ntp_snippets::Status& status);
+  void DidUnsubscribe(const ntp_snippets::Status& status);
 
   DISALLOW_COPY_AND_ASSIGN(SubscriptionManager);
 };
diff --git a/components/ntp_snippets/breaking_news/subscription_manager_unittest.cc b/components/ntp_snippets/breaking_news/subscription_manager_unittest.cc
index 1cddf00a..1cf4f41 100644
--- a/components/ntp_snippets/breaking_news/subscription_manager_unittest.cc
+++ b/components/ntp_snippets/breaking_news/subscription_manager_unittest.cc
@@ -54,6 +54,8 @@
     url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
   }
 
+  const std::string url{"http://valid-url.test"};
+
  private:
   base::MessageLoop message_loop_;
   scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
@@ -63,10 +65,11 @@
 
 TEST_F(SubscriptionManagerTest, SubscribeSuccessfully) {
   std::string token = "1234567890";
-  SubscriptionManager manager(GetRequestContext(), GetPrefService(),
-                              GURL("http://valid-url.test"));
+  SubscriptionManager manager(GetRequestContext(), GetPrefService(), GURL(url),
+                              GURL(url));
   manager.Subscribe(token);
   RespondWithData("");
+  EXPECT_TRUE(manager.IsSubscribed());
   EXPECT_EQ(GetPrefService()->GetString(
                 ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken),
             token);
@@ -74,12 +77,40 @@
 
 TEST_F(SubscriptionManagerTest, SubscribeWithErrors) {
   std::string token = "1234567890";
-  SubscriptionManager manager(GetRequestContext(), GetPrefService(),
-                              GURL("http://valid-url.test"));
+  SubscriptionManager manager(GetRequestContext(), GetPrefService(), GURL(url),
+                              GURL(url));
   manager.Subscribe(token);
   RespondWithError(net::ERR_TIMED_OUT);
+  EXPECT_FALSE(manager.IsSubscribed());
   EXPECT_FALSE(GetPrefService()->HasPrefPath(
       ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken));
 }
 
+TEST_F(SubscriptionManagerTest, UnsubscribeSuccessfully) {
+  std::string token = "1234567890";
+  GetPrefService()->SetString(
+      ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken, token);
+  SubscriptionManager manager(GetRequestContext(), GetPrefService(), GURL(url),
+                              GURL(url));
+  manager.Unsubscribe(token);
+  RespondWithData("");
+  EXPECT_FALSE(manager.IsSubscribed());
+  EXPECT_FALSE(GetPrefService()->HasPrefPath(
+      ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken));
+}
+
+TEST_F(SubscriptionManagerTest, UnsubscribeWithErrors) {
+  std::string token = "1234567890";
+  GetPrefService()->SetString(
+      ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken, token);
+  SubscriptionManager manager(GetRequestContext(), GetPrefService(), GURL(url),
+                              GURL(url));
+  manager.Unsubscribe(token);
+  RespondWithError(net::ERR_TIMED_OUT);
+  EXPECT_TRUE(manager.IsSubscribed());
+  EXPECT_EQ(GetPrefService()->GetString(
+                ntp_snippets::prefs::kContentSuggestionsSubscriptionDataToken),
+            token);
+}
+
 }  // namespace ntp_snippets
diff --git a/components/ntp_snippets/pref_names.cc b/components/ntp_snippets/pref_names.cc
index 9414276..13a2b615 100644
--- a/components/ntp_snippets/pref_names.cc
+++ b/components/ntp_snippets/pref_names.cc
@@ -84,5 +84,8 @@
 const char kContentSuggestionsSubscriptionDataToken[] =
     "ntp_suggestions.content_suggestions_subscription_data.token";
 
+const char kContentSuggestionsGCMSubscriptionTokenCache[] =
+    "ntp_suggestions.content_suggestions_gcm_subscription_token_cache";
+
 }  // namespace prefs
 }  // namespace ntp_snippets
diff --git a/components/ntp_snippets/pref_names.h b/components/ntp_snippets/pref_names.h
index c640965..8dac4cd 100644
--- a/components/ntp_snippets/pref_names.h
+++ b/components/ntp_snippets/pref_names.h
@@ -90,9 +90,23 @@
 // The pref name for the time when last click decay has happened.
 extern const char kClickBasedCategoryRankerLastDecayTime[];
 
-// The pref name for the subscription token used when subscription for breaking
-// news push updates,
+// kContentSuggestionsSubscriptionData* hold the data used when subscribing for
+// content suggestions via GCM push updates. They are stored in pref such that
+// in case of change (e.g. the token renders invalid), re-subscription is
+// required.
+///////////////////////////////////////////////////////////////////////////////
+// The pref name for the subscription token used when subscription for
+// breaking news push updates.
 extern const char kContentSuggestionsSubscriptionDataToken[];
+//////////////////////// End of kContentSuggestionsSubscriptionData *
+
+// The pref name for the subscription token received from the gcm server. As
+// recommended by the GCM team, it is cached in pref for faster bookkeeping to
+// see if subscription exists. This is pref holds the valid token even if
+// different from the one used for subscription. When they are different, Chrome
+// unsubscribes the old token from the content suggestions server, subscribe
+// with the new one and update kContentSuggestionsSubscriptionDataToken.
+extern const char kContentSuggestionsGCMSubscriptionTokenCache[];
 
 }  // namespace prefs
 }  // namespace ntp_snippets
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc
index 32433ba..a814bb1d 100644
--- a/components/omnibox/browser/omnibox_field_trial.cc
+++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -91,6 +91,10 @@
     "OmniboxUIExperimentMaxAutocompleteMatches",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Feature used for the omnibox narrow suggestions dropdown UI experiment.
+const base::Feature kUIExperimentNarrowDropdown{
+    "OmniboxUIExperimentNarrowDropdown", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Feature used for the vertical margin UI experiment.
 const base::Feature kUIExperimentVerticalLayout{
     "OmniboxUIExperimentVerticalLayout", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h
index 42b9758..8aa261a5 100644
--- a/components/omnibox/browser/omnibox_field_trial.h
+++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -34,6 +34,7 @@
 extern const base::Feature kZeroSuggestSwapTitleAndUrl;
 extern const base::Feature kDisplayTitleForCurrentUrl;
 extern const base::Feature kUIExperimentMaxAutocompleteMatches;
+extern const base::Feature kUIExperimentNarrowDropdown;
 extern const base::Feature kUIExperimentVerticalLayout;
 extern const base::Feature kUIExperimentVerticalMargin;
 }
diff --git a/components/prefs/BUILD.gn b/components/prefs/BUILD.gn
index 029c712..5387ac4 100644
--- a/components/prefs/BUILD.gn
+++ b/components/prefs/BUILD.gn
@@ -15,6 +15,7 @@
     "json_pref_store.h",
     "overlay_user_pref_store.cc",
     "overlay_user_pref_store.h",
+    "persistent_pref_store.cc",
     "persistent_pref_store.h",
     "pref_change_registrar.cc",
     "pref_change_registrar.h",
@@ -84,6 +85,8 @@
     "in_memory_pref_store_unittest.cc",
     "json_pref_store_unittest.cc",
     "overlay_user_pref_store_unittest.cc",
+    "persistent_pref_store_unittest.cc",
+    "persistent_pref_store_unittest.h",
     "pref_change_registrar_unittest.cc",
     "pref_member_unittest.cc",
     "pref_notifier_impl_unittest.cc",
diff --git a/components/prefs/in_memory_pref_store.h b/components/prefs/in_memory_pref_store.h
index 5529622..8d49f6c0 100644
--- a/components/prefs/in_memory_pref_store.h
+++ b/components/prefs/in_memory_pref_store.h
@@ -46,7 +46,6 @@
   PrefReadError GetReadError() const override;
   PersistentPrefStore::PrefReadError ReadPrefs() override;
   void ReadPrefsAsync(ReadErrorDelegate* error_delegate) override {}
-  void CommitPendingWrite() override {}
   void SchedulePendingLossyWrites() override {}
   void ClearMutableValues() override {}
 
diff --git a/components/prefs/in_memory_pref_store_unittest.cc b/components/prefs/in_memory_pref_store_unittest.cc
index 822aa8f..14da3ef 100644
--- a/components/prefs/in_memory_pref_store_unittest.cc
+++ b/components/prefs/in_memory_pref_store_unittest.cc
@@ -5,10 +5,13 @@
 #include "components/prefs/in_memory_pref_store.h"
 
 #include "base/memory/ptr_util.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/values.h"
+#include "components/prefs/persistent_pref_store_unittest.h"
 #include "components/prefs/pref_store_observer_mock.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+
 namespace {
 const char kTestPref[] = "test.pref";
 
@@ -18,6 +21,7 @@
 
   void SetUp() override { store_ = new InMemoryPrefStore(); }
  protected:
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   scoped_refptr<InMemoryPrefStore> store_;
   PrefStoreObserverMock observer_;
 };
@@ -101,4 +105,8 @@
   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, store_->ReadPrefs());
 }
 
+TEST_F(InMemoryPrefStoreTest, CommitPendingWriteWithCallback) {
+  TestCommitPendingWriteWithCallback(store_.get());
+}
+
 }  // namespace
diff --git a/components/prefs/json_pref_store.cc b/components/prefs/json_pref_store.cc
index c44dfa9..0b6b0f18 100644
--- a/components/prefs/json_pref_store.cc
+++ b/components/prefs/json_pref_store.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
@@ -143,13 +144,13 @@
 
 JsonPrefStore::JsonPrefStore(
     const base::FilePath& pref_filename,
-    scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner,
+    scoped_refptr<base::SequencedTaskRunner> file_task_runner,
     std::unique_ptr<PrefFilter> pref_filter)
     : path_(pref_filename),
-      sequenced_task_runner_(std::move(sequenced_task_runner)),
+      file_task_runner_(std::move(file_task_runner)),
       prefs_(new base::DictionaryValue()),
       read_only_(false),
-      writer_(pref_filename, sequenced_task_runner_),
+      writer_(pref_filename, file_task_runner_),
       pref_filter_(std::move(pref_filter)),
       initialized_(false),
       filtering_in_progress_(false),
@@ -279,12 +280,11 @@
 
   // Weakly binds the read task so that it doesn't kick in during shutdown.
   base::PostTaskAndReplyWithResult(
-      sequenced_task_runner_.get(), FROM_HERE,
-      base::Bind(&ReadPrefsFromDisk, path_),
+      file_task_runner_.get(), FROM_HERE, base::Bind(&ReadPrefsFromDisk, path_),
       base::Bind(&JsonPrefStore::OnFileRead, AsWeakPtr()));
 }
 
-void JsonPrefStore::CommitPendingWrite() {
+void JsonPrefStore::CommitPendingWrite(base::OnceClosure done_callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Schedule a write for any lossy writes that are outstanding to ensure that
@@ -293,6 +293,15 @@
 
   if (writer_.HasPendingWrite() && !read_only_)
     writer_.DoScheduledWrite();
+
+  if (done_callback) {
+    // Since disk operations occur on |file_task_runner_|, the reply of a task
+    // posted to |file_task_runner_| will run after currently pending disk
+    // operations. Also, by definition of PostTaskAndReply(), the reply will run
+    // on the current sequence.
+    file_task_runner_->PostTaskAndReply(
+        FROM_HERE, base::BindOnce(&base::DoNothing), std::move(done_callback));
+  }
 }
 
 void JsonPrefStore::SchedulePendingLossyWrites() {
@@ -442,7 +451,7 @@
 
 JsonPrefStore::~JsonPrefStore() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  CommitPendingWrite();
+  CommitPendingWrite(base::OnceClosure());
 }
 
 bool JsonPrefStore::SerializeData(std::string* output) {
diff --git a/components/prefs/json_pref_store.h b/components/prefs/json_pref_store.h
index 90fde73..1321a1e 100644
--- a/components/prefs/json_pref_store.h
+++ b/components/prefs/json_pref_store.h
@@ -65,12 +65,12 @@
 
   // |pref_filename| is the path to the file to read prefs from. It is incorrect
   // to create multiple JsonPrefStore with the same |pref_filename|.
-  // |sequenced_task_runner| is used for asynchronous reads and writes. It must
+  // |file_task_runner| is used for asynchronous reads and writes. It must
   // have the base::TaskShutdownBehavior::BLOCK_SHUTDOWN and base::MayBlock()
   // traits. Unless external tasks need to run on the same sequence as
   // JsonPrefStore tasks, keep the default value.
   JsonPrefStore(const base::FilePath& pref_filename,
-                scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner =
+                scoped_refptr<base::SequencedTaskRunner> file_task_runner =
                     base::CreateSequencedTaskRunnerWithTraits(
                         {base::MayBlock(),
                          base::TaskShutdownBehavior::BLOCK_SHUTDOWN}),
@@ -101,7 +101,7 @@
   // See details in pref_filter.h.
   PrefReadError ReadPrefs() override;
   void ReadPrefsAsync(ReadErrorDelegate* error_delegate) override;
-  void CommitPendingWrite() override;
+  void CommitPendingWrite(base::OnceClosure done_callback) override;
   void SchedulePendingLossyWrites() override;
   void ReportValueChanged(const std::string& key, uint32_t flags) override;
 
@@ -226,7 +226,7 @@
   void ScheduleWrite(uint32_t flags);
 
   const base::FilePath path_;
-  const scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
+  const scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
 
   std::unique_ptr<base::DictionaryValue> prefs_;
 
diff --git a/components/prefs/json_pref_store_unittest.cc b/components/prefs/json_pref_store_unittest.cc
index f009200..769816d 100644
--- a/components/prefs/json_pref_store_unittest.cc
+++ b/components/prefs/json_pref_store_unittest.cc
@@ -16,7 +16,6 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_samples.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
@@ -25,11 +24,13 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/histogram_tester.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/test/simple_test_clock.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/threading/thread.h"
 #include "base/values.h"
+#include "components/prefs/persistent_pref_store_unittest.h"
 #include "components/prefs/pref_filter.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -129,9 +130,25 @@
   MOCK_METHOD1(OnError, void(PersistentPrefStore::PrefReadError));
 };
 
-}  // namespace
+enum class CommitPendingWriteMode {
+  WITHOUT_CALLBACK,
+  WITH_CALLBACK,
+};
 
-class JsonPrefStoreTest : public testing::Test {
+void CommitPendingWrite(
+    JsonPrefStore* pref_store,
+    CommitPendingWriteMode commit_pending_write_mode,
+    base::test::ScopedTaskEnvironment* scoped_task_environment) {
+  if (commit_pending_write_mode == CommitPendingWriteMode::WITHOUT_CALLBACK) {
+    pref_store->CommitPendingWrite(OnceClosure());
+    scoped_task_environment->RunUntilIdle();
+  } else {
+    TestCommitPendingWriteWithCallback(pref_store);
+  }
+}
+
+class JsonPrefStoreTest
+    : public testing::TestWithParam<CommitPendingWriteMode> {
  public:
   JsonPrefStoreTest() = default;
 
@@ -140,27 +157,21 @@
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
   }
 
-  void TearDown() override {
-    // Make sure all pending tasks have been processed (e.g., deleting the
-    // JsonPrefStore may post write tasks).
-    RunLoop().RunUntilIdle();
-  }
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 
   // The path to temporary directory used to contain the test operations.
   base::ScopedTempDir temp_dir_;
-  // A message loop that we can use as the file thread message loop.
-  MessageLoop message_loop_;
 
   DISALLOW_COPY_AND_ASSIGN(JsonPrefStoreTest);
 };
 
+}  // namespace
+
 // Test fallback behavior for a nonexistent file.
 TEST_F(JsonPrefStoreTest, NonExistentFile) {
   base::FilePath bogus_input_file = temp_dir_.GetPath().AppendASCII("read.txt");
   ASSERT_FALSE(PathExists(bogus_input_file));
-  scoped_refptr<JsonPrefStore> pref_store =
-      new JsonPrefStore(bogus_input_file, message_loop_.task_runner(),
-                        std::unique_ptr<PrefFilter>());
+  auto pref_store = base::MakeRefCounted<JsonPrefStore>(bogus_input_file);
   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
             pref_store->ReadPrefs());
   EXPECT_FALSE(pref_store->ReadOnly());
@@ -172,8 +183,7 @@
   ASSERT_LT(0, base::WriteFile(invalid_file,
                                kInvalidJson, arraysize(kInvalidJson) - 1));
 
-  scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
-      invalid_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
+  auto pref_store = base::MakeRefCounted<JsonPrefStore>(invalid_file);
   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE,
             pref_store->ReadPrefs());
   EXPECT_FALSE(pref_store->ReadOnly());
@@ -191,8 +201,11 @@
 // This function is used to avoid code duplication while testing synchronous
 // and asynchronous version of the JsonPrefStore loading. It validates that the
 // given output file's contents matches kWriteGolden.
-void RunBasicJsonPrefStoreTest(JsonPrefStore* pref_store,
-                               const base::FilePath& output_file) {
+void RunBasicJsonPrefStoreTest(
+    JsonPrefStore* pref_store,
+    const base::FilePath& output_file,
+    CommitPendingWriteMode commit_pending_write_mode,
+    base::test::ScopedTaskEnvironment* scoped_task_environment) {
   const char kNewWindowsInTabs[] = "tabs.new_windows_in_tabs";
   const char kMaxTabs[] = "tabs.max_tabs";
   const char kLongIntPref[] = "long_int.pref";
@@ -253,8 +266,8 @@
   EXPECT_EQ(214748364842LL, value);
 
   // Serialize and compare to expected output.
-  pref_store->CommitPendingWrite();
-  RunLoop().RunUntilIdle();
+  CommitPendingWrite(pref_store, commit_pending_write_mode,
+                     scoped_task_environment);
 
   std::string output_contents;
   ASSERT_TRUE(base::ReadFileToString(output_file, &output_contents));
@@ -262,15 +275,14 @@
   ASSERT_TRUE(base::DeleteFile(output_file, false));
 }
 
-TEST_F(JsonPrefStoreTest, Basic) {
+TEST_P(JsonPrefStoreTest, Basic) {
   base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
   ASSERT_LT(0, base::WriteFile(input_file,
                                kReadJson, arraysize(kReadJson) - 1));
 
   // Test that the persistent value can be loaded.
   ASSERT_TRUE(PathExists(input_file));
-  scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
-      input_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
+  auto pref_store = base::MakeRefCounted<JsonPrefStore>(input_file);
   ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
   EXPECT_FALSE(pref_store->ReadOnly());
   EXPECT_TRUE(pref_store->IsInitializationComplete());
@@ -285,17 +297,17 @@
   //   }
   // }
 
-  RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
+  RunBasicJsonPrefStoreTest(pref_store.get(), input_file, GetParam(),
+                            &scoped_task_environment_);
 }
 
-TEST_F(JsonPrefStoreTest, BasicAsync) {
+TEST_P(JsonPrefStoreTest, BasicAsync) {
   base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
   ASSERT_LT(0, base::WriteFile(input_file,
                                kReadJson, arraysize(kReadJson) - 1));
 
   // Test that the persistent value can be loaded.
-  scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
-      input_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
+  auto pref_store = base::MakeRefCounted<JsonPrefStore>(input_file);
 
   {
     MockPrefStoreObserver mock_observer;
@@ -307,7 +319,7 @@
     EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
     EXPECT_CALL(*mock_error_delegate,
                 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
-    RunLoop().RunUntilIdle();
+    scoped_task_environment_.RunUntilIdle();
     pref_store->RemoveObserver(&mock_observer);
 
     EXPECT_FALSE(pref_store->ReadOnly());
@@ -324,14 +336,14 @@
   //   }
   // }
 
-  RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
+  RunBasicJsonPrefStoreTest(pref_store.get(), input_file, GetParam(),
+                            &scoped_task_environment_);
 }
 
-TEST_F(JsonPrefStoreTest, PreserveEmptyValues) {
+TEST_P(JsonPrefStoreTest, PreserveEmptyValues) {
   FilePath pref_file = temp_dir_.GetPath().AppendASCII("empty_values.json");
 
-  scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
-      pref_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
+  auto pref_store = base::MakeRefCounted<JsonPrefStore>(pref_file);
 
   // Set some keys with empty values.
   pref_store->SetValue("list", base::MakeUnique<base::ListValue>(),
@@ -340,12 +352,10 @@
                        WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
 
   // Write to file.
-  pref_store->CommitPendingWrite();
-  RunLoop().RunUntilIdle();
+  CommitPendingWrite(pref_store.get(), GetParam(), &scoped_task_environment_);
 
   // Reload.
-  pref_store = new JsonPrefStore(pref_file, message_loop_.task_runner(),
-                                 std::unique_ptr<PrefFilter>());
+  pref_store = base::MakeRefCounted<JsonPrefStore>(pref_file);
   ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
   ASSERT_FALSE(pref_store->ReadOnly());
 
@@ -362,8 +372,7 @@
 TEST_F(JsonPrefStoreTest, RemoveClearsEmptyParent) {
   FilePath pref_file = temp_dir_.GetPath().AppendASCII("empty_values.json");
 
-  scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
-      pref_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
+  auto pref_store = base::MakeRefCounted<JsonPrefStore>(pref_file);
 
   std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
   dict->SetString("key", "value");
@@ -382,9 +391,7 @@
 TEST_F(JsonPrefStoreTest, AsyncNonExistingFile) {
   base::FilePath bogus_input_file = temp_dir_.GetPath().AppendASCII("read.txt");
   ASSERT_FALSE(PathExists(bogus_input_file));
-  scoped_refptr<JsonPrefStore> pref_store =
-      new JsonPrefStore(bogus_input_file, message_loop_.task_runner(),
-                        std::unique_ptr<PrefFilter>());
+  auto pref_store = base::MakeRefCounted<JsonPrefStore>(bogus_input_file);
   MockPrefStoreObserver mock_observer;
   pref_store->AddObserver(&mock_observer);
 
@@ -394,13 +401,13 @@
   EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
   EXPECT_CALL(*mock_error_delegate,
               OnError(PersistentPrefStore::PREF_READ_ERROR_NO_FILE)).Times(1);
-  RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   pref_store->RemoveObserver(&mock_observer);
 
   EXPECT_FALSE(pref_store->ReadOnly());
 }
 
-TEST_F(JsonPrefStoreTest, ReadWithInterceptor) {
+TEST_P(JsonPrefStoreTest, ReadWithInterceptor) {
   base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
   ASSERT_LT(0, base::WriteFile(input_file,
                                kReadJson, arraysize(kReadJson) - 1));
@@ -409,9 +416,9 @@
       new InterceptingPrefFilter());
   InterceptingPrefFilter* raw_intercepting_pref_filter_ =
       intercepting_pref_filter.get();
-  scoped_refptr<JsonPrefStore> pref_store =
-      new JsonPrefStore(input_file, message_loop_.task_runner(),
-                        std::move(intercepting_pref_filter));
+  auto pref_store = base::MakeRefCounted<JsonPrefStore>(
+      input_file, base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()}),
+      std::move(intercepting_pref_filter));
 
   ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE,
             pref_store->ReadPrefs());
@@ -439,10 +446,11 @@
   //   }
   // }
 
-  RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
+  RunBasicJsonPrefStoreTest(pref_store.get(), input_file, GetParam(),
+                            &scoped_task_environment_);
 }
 
-TEST_F(JsonPrefStoreTest, ReadAsyncWithInterceptor) {
+TEST_P(JsonPrefStoreTest, ReadAsyncWithInterceptor) {
   base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
   ASSERT_LT(0, base::WriteFile(input_file,
                                kReadJson, arraysize(kReadJson) - 1));
@@ -451,9 +459,9 @@
       new InterceptingPrefFilter());
   InterceptingPrefFilter* raw_intercepting_pref_filter_ =
       intercepting_pref_filter.get();
-  scoped_refptr<JsonPrefStore> pref_store =
-      new JsonPrefStore(input_file, message_loop_.task_runner(),
-                        std::move(intercepting_pref_filter));
+  auto pref_store = base::MakeRefCounted<JsonPrefStore>(
+      input_file, base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()}),
+      std::move(intercepting_pref_filter));
 
   MockPrefStoreObserver mock_observer;
   pref_store->AddObserver(&mock_observer);
@@ -467,7 +475,7 @@
     EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(0);
     // EXPECT_CALL(*mock_error_delegate,
     //             OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
-    RunLoop().RunUntilIdle();
+    scoped_task_environment_.RunUntilIdle();
 
     EXPECT_FALSE(pref_store->ReadOnly());
     EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs());
@@ -500,7 +508,8 @@
   //   }
   // }
 
-  RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
+  RunBasicJsonPrefStoreTest(pref_store.get(), input_file, GetParam(),
+                            &scoped_task_environment_);
 }
 
 TEST_F(JsonPrefStoreTest, WriteCountHistogramTestBasic) {
@@ -652,6 +661,15 @@
   histogram_tester.ExpectTotalCount(histogram_name, 6);
 }
 
+INSTANTIATE_TEST_CASE_P(
+    WithoutCallback,
+    JsonPrefStoreTest,
+    ::testing::Values(CommitPendingWriteMode::WITHOUT_CALLBACK));
+INSTANTIATE_TEST_CASE_P(
+    WithCallback,
+    JsonPrefStoreTest,
+    ::testing::Values(CommitPendingWriteMode::WITH_CALLBACK));
+
 class JsonPrefStoreLossyWriteTest : public JsonPrefStoreTest {
  public:
   JsonPrefStoreLossyWriteTest() = default;
@@ -663,8 +681,7 @@
   }
 
   scoped_refptr<JsonPrefStore> CreatePrefStore() {
-    return new JsonPrefStore(test_file_, message_loop_.task_runner(),
-                             std::unique_ptr<PrefFilter>());
+    return base::MakeRefCounted<JsonPrefStore>(test_file_);
   }
 
   // Return the ImportantFileWriter for a given JsonPrefStore.
@@ -675,7 +692,7 @@
   // Get the contents of kTestFile. Pumps the message loop before returning the
   // result.
   std::string GetTestFileContents() {
-    RunLoop().RunUntilIdle();
+    scoped_task_environment_.RunUntilIdle();
     std::string file_contents;
     ReadFileToString(test_file_, &file_contents);
     return file_contents;
@@ -726,7 +743,7 @@
 
   // Call CommitPendingWrite and check that the lossy pref and the normal pref
   // are there with the last values set above.
-  pref_store->CommitPendingWrite();
+  pref_store->CommitPendingWrite(base::OnceClosure());
   ASSERT_FALSE(file_writer->HasPendingWrite());
   ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
             GetTestFileContents());
@@ -791,7 +808,7 @@
 
   // Call CommitPendingWrite and check that the lossy pref is there with the
   // last value set above.
-  pref_store->CommitPendingWrite();
+  pref_store->CommitPendingWrite(base::OnceClosure());
   ASSERT_FALSE(file_writer->HasPendingWrite());
   ASSERT_EQ("{\"lossy\":\"lossy\"}", GetTestFileContents());
 }
@@ -904,8 +921,7 @@
   }
 
   scoped_refptr<JsonPrefStore> CreatePrefStore() {
-    return new JsonPrefStore(test_file_, message_loop_.task_runner(),
-                             std::unique_ptr<PrefFilter>());
+    return base::MakeRefCounted<JsonPrefStore>(test_file_);
   }
 
   // Return the ImportantFileWriter for a given JsonPrefStore.
@@ -938,9 +954,9 @@
 
   std::unique_ptr<InterceptingPrefFilter> intercepting_pref_filter(
       new InterceptingPrefFilter(write_callback_observer_.GetCallbackPair()));
-  scoped_refptr<JsonPrefStore> pref_store =
-      new JsonPrefStore(input_file, message_loop_.task_runner(),
-                        std::move(intercepting_pref_filter));
+  auto pref_store = base::MakeRefCounted<JsonPrefStore>(
+      input_file, base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()}),
+      std::move(intercepting_pref_filter));
   ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store.get());
 
   EXPECT_EQ(NOT_CALLED,
@@ -954,7 +970,7 @@
   EXPECT_EQ(NOT_CALLED,
             write_callback_observer_.GetAndResetPostWriteObservationState());
 
-  RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   EXPECT_TRUE(write_callback_observer_.GetAndResetPreWriteObservationState());
   EXPECT_EQ(CALLED_WITH_SUCCESS,
@@ -970,7 +986,7 @@
   successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
   write_callback_observer_.ObserveNextWriteCallback(pref_store.get());
   file_writer->WriteNow(MakeUnique<std::string>("foo"));
-  RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
   EXPECT_TRUE(write_callback_observer_.GetAndResetPreWriteObservationState());
   EXPECT_EQ(CALLED_WITH_SUCCESS,
@@ -981,7 +997,7 @@
   successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
   write_callback_observer_.ObserveNextWriteCallback(pref_store.get());
   file_writer->WriteNow(MakeUnique<std::string>("foo"));
-  RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
   EXPECT_TRUE(write_callback_observer_.GetAndResetPreWriteObservationState());
   EXPECT_EQ(CALLED_WITH_SUCCESS,
@@ -990,7 +1006,7 @@
   // Test RegisterOnNextSuccessfulWriteReply only.
   successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
   file_writer->WriteNow(MakeUnique<std::string>("foo"));
-  RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
   EXPECT_FALSE(write_callback_observer_.GetAndResetPreWriteObservationState());
   EXPECT_EQ(NOT_CALLED,
@@ -999,7 +1015,7 @@
   // Test RegisterOnNextWriteSynchronousCallbacks only.
   write_callback_observer_.ObserveNextWriteCallback(pref_store.get());
   file_writer->WriteNow(MakeUnique<std::string>("foo"));
-  RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
   EXPECT_TRUE(write_callback_observer_.GetAndResetPreWriteObservationState());
   EXPECT_EQ(CALLED_WITH_SUCCESS,
@@ -1012,7 +1028,7 @@
   // Confirm that the observers are invoked.
   successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
   TriggerFakeWriteForCallback(pref_store.get(), true);
-  RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
   EXPECT_EQ(CALLED_WITH_SUCCESS,
             write_callback_observer_.GetAndResetPostWriteObservationState());
@@ -1025,7 +1041,7 @@
   // Confirm that re-installing the observers works for another write.
   successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
   TriggerFakeWriteForCallback(pref_store.get(), true);
-  RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
   EXPECT_EQ(CALLED_WITH_SUCCESS,
             write_callback_observer_.GetAndResetPostWriteObservationState());
@@ -1034,7 +1050,7 @@
   // write, and that the synchronous observer is invoked.
   successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
   TriggerFakeWriteForCallback(pref_store.get(), false);
-  RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
   EXPECT_EQ(CALLED_WITH_ERROR,
             write_callback_observer_.GetAndResetPostWriteObservationState());
@@ -1043,7 +1059,7 @@
   // being set by |PostWriteCallback| by the last TriggerFakeWriteCallback.
   ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store.get());
   file_writer->WriteNow(MakeUnique<std::string>("foo"));
-  RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
   EXPECT_EQ(NOT_CALLED,
             write_callback_observer_.GetAndResetPostWriteObservationState());
@@ -1063,7 +1079,7 @@
         soon_out_of_scope_pref_store.get());
     file_writer->WriteNow(MakeUnique<std::string>("foo"));
   }
-  RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
   EXPECT_TRUE(write_callback_observer_.GetAndResetPreWriteObservationState());
   EXPECT_EQ(CALLED_WITH_SUCCESS,
diff --git a/components/prefs/overlay_user_pref_store.cc b/components/prefs/overlay_user_pref_store.cc
index a4d21cd..55f3f687 100644
--- a/components/prefs/overlay_user_pref_store.cc
+++ b/components/prefs/overlay_user_pref_store.cc
@@ -169,8 +169,8 @@
   OnInitializationCompleted(/* overlay */ false, true);
 }
 
-void OverlayUserPrefStore::CommitPendingWrite() {
-  underlay_->CommitPendingWrite();
+void OverlayUserPrefStore::CommitPendingWrite(base::OnceClosure done_callback) {
+  underlay_->CommitPendingWrite(std::move(done_callback));
   // We do not write our content intentionally.
 }
 
diff --git a/components/prefs/overlay_user_pref_store.h b/components/prefs/overlay_user_pref_store.h
index 9aa742f..23cace5 100644
--- a/components/prefs/overlay_user_pref_store.h
+++ b/components/prefs/overlay_user_pref_store.h
@@ -56,7 +56,7 @@
   PrefReadError GetReadError() const override;
   PrefReadError ReadPrefs() override;
   void ReadPrefsAsync(ReadErrorDelegate* delegate) override;
-  void CommitPendingWrite() override;
+  void CommitPendingWrite(base::OnceClosure done_callback) override;
   void SchedulePendingLossyWrites() override;
   void ReportValueChanged(const std::string& key, uint32_t flags) override;
 
diff --git a/components/prefs/overlay_user_pref_store_unittest.cc b/components/prefs/overlay_user_pref_store_unittest.cc
index d421b11c..2624149 100644
--- a/components/prefs/overlay_user_pref_store_unittest.cc
+++ b/components/prefs/overlay_user_pref_store_unittest.cc
@@ -5,7 +5,9 @@
 #include "components/prefs/overlay_user_pref_store.h"
 
 #include "base/memory/ptr_util.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/values.h"
+#include "components/prefs/persistent_pref_store_unittest.h"
 #include "components/prefs/pref_store_observer_mock.h"
 #include "components/prefs/testing_pref_store.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -38,6 +40,7 @@
 
   ~OverlayUserPrefStoreTest() override {}
 
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   scoped_refptr<TestingPrefStore> underlay_;
   scoped_refptr<OverlayUserPrefStore> overlay_;
 };
@@ -271,4 +274,8 @@
   EXPECT_TRUE(base::Value(43).Equals(value));
 }
 
+TEST_F(OverlayUserPrefStoreTest, CommitPendingWriteWithCallback) {
+  TestCommitPendingWriteWithCallback(overlay_.get());
+}
+
 }  // namespace base
diff --git a/components/prefs/persistent_pref_store.cc b/components/prefs/persistent_pref_store.cc
new file mode 100644
index 0000000..2f933659
--- /dev/null
+++ b/components/prefs/persistent_pref_store.cc
@@ -0,0 +1,22 @@
+// Copyright 2017 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/prefs/persistent_pref_store.h"
+
+#include <utility>
+
+#include "base/threading/sequenced_task_runner_handle.h"
+
+void PersistentPrefStore::CommitPendingWrite() {
+  CommitPendingWrite(base::OnceClosure());
+}
+
+void PersistentPrefStore::CommitPendingWrite(base::OnceClosure done_callback) {
+  // Default behavior for PersistentPrefStore implementation that don't issue
+  // disk operations: schedule the callback immediately.
+  if (done_callback) {
+    base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                     std::move(done_callback));
+  }
+}
diff --git a/components/prefs/persistent_pref_store.h b/components/prefs/persistent_pref_store.h
index 7bc2827..b3ff5f46 100644
--- a/components/prefs/persistent_pref_store.h
+++ b/components/prefs/persistent_pref_store.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "base/callback.h"
 #include "components/prefs/base_prefs_export.h"
 #include "components/prefs/writeable_pref_store.h"
 
@@ -61,8 +62,13 @@
   // Owns |error_delegate|.
   virtual void ReadPrefsAsync(ReadErrorDelegate* error_delegate) = 0;
 
-  // Lands any pending writes to disk.
-  virtual void CommitPendingWrite() = 0;
+  // Starts an asynchronous attempt to commit pending writes to disk.
+  void CommitPendingWrite();
+
+  // Starts an asynchronous attempt to commit pending writes to disk. Posts a
+  // task to run |done_callback| on the current sequence when disk operations,
+  // if any, are complete (even if they are unsuccessful).
+  virtual void CommitPendingWrite(base::OnceClosure done_callback);
 
   // Schedule a write if there is any lossy data pending. Unlike
   // CommitPendingWrite() this does not immediately sync to disk, instead it
diff --git a/components/prefs/persistent_pref_store_unittest.cc b/components/prefs/persistent_pref_store_unittest.cc
new file mode 100644
index 0000000..e2a65416
--- /dev/null
+++ b/components/prefs/persistent_pref_store_unittest.cc
@@ -0,0 +1,22 @@
+// Copyright 2017 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/prefs/persistent_pref_store.h"
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "base/sequence_checker_impl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+void TestCommitPendingWriteWithCallback(PersistentPrefStore* store) {
+  base::RunLoop run_loop;
+  base::SequenceCheckerImpl sequence_checker;
+  store->CommitPendingWrite(base::BindOnce(
+      [](base::SequenceCheckerImpl* sequence_checker, base::RunLoop* run_loop) {
+        EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
+        run_loop->Quit();
+      },
+      base::Unretained(&sequence_checker), base::Unretained(&run_loop)));
+  run_loop.Run();
+}
diff --git a/components/prefs/persistent_pref_store_unittest.h b/components/prefs/persistent_pref_store_unittest.h
new file mode 100644
index 0000000..99442336
--- /dev/null
+++ b/components/prefs/persistent_pref_store_unittest.h
@@ -0,0 +1,15 @@
+// Copyright 2017 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 COMPONENTS_PREFS_PERSISTENT_PREF_STORE_UNITTEST_H_
+#define COMPONENTS_PREFS_PERSISTENT_PREF_STORE_UNITTEST_H_
+
+class PersistentPrefStore;
+
+// Calls CommitPendingWrite() on |store| with a callback. Verifies that the
+// callback runs on the appropriate sequence. This function is meant to be
+// reused in the tests of various PersistentPrefStore implementations.
+void TestCommitPendingWriteWithCallback(PersistentPrefStore* store);
+
+#endif  // COMPONENTS_PREFS_PERSISTENT_PREF_STORE_UNITTEST_H_
diff --git a/components/prefs/testing_pref_store.cc b/components/prefs/testing_pref_store.cc
index efdc83f..f214da8 100644
--- a/components/prefs/testing_pref_store.cc
+++ b/components/prefs/testing_pref_store.cc
@@ -9,6 +9,7 @@
 
 #include "base/json/json_writer.h"
 #include "base/memory/ptr_util.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "base/values.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -98,7 +99,10 @@
     NotifyInitializationCompleted();
 }
 
-void TestingPrefStore::CommitPendingWrite() { committed_ = true; }
+void TestingPrefStore::CommitPendingWrite(base::OnceClosure done_callback) {
+  committed_ = true;
+  PersistentPrefStore::CommitPendingWrite(std::move(done_callback));
+}
 
 void TestingPrefStore::SchedulePendingLossyWrites() {}
 
diff --git a/components/prefs/testing_pref_store.h b/components/prefs/testing_pref_store.h
index 4e0afa4..cc40c1d 100644
--- a/components/prefs/testing_pref_store.h
+++ b/components/prefs/testing_pref_store.h
@@ -45,7 +45,7 @@
   PrefReadError GetReadError() const override;
   PersistentPrefStore::PrefReadError ReadPrefs() override;
   void ReadPrefsAsync(ReadErrorDelegate* error_delegate) override;
-  void CommitPendingWrite() override;
+  void CommitPendingWrite(base::OnceClosure done_callback) override;
   void SchedulePendingLossyWrites() override;
 
   // Marks the store as having completed initialization.
diff --git a/components/security_interstitials/core/browser/resources/interstitial_large.css b/components/security_interstitials/core/browser/resources/interstitial_large.css
index 6ca9c0c..c14e72b 100644
--- a/components/security_interstitials/core/browser/resources/interstitial_large.css
+++ b/components/security_interstitials/core/browser/resources/interstitial_large.css
@@ -118,7 +118,7 @@
   box-sizing: border-box;
   font-size: 1em;
   line-height: 1.6em;
-  margin: 100px auto 0;
+  margin: 14vh auto 0;
   max-width: 600px;
   width: 100%;
 }
diff --git a/components/spellcheck/browser/android/java/src/org/chromium/components/spellcheck/SpellCheckerSessionBridge.java b/components/spellcheck/browser/android/java/src/org/chromium/components/spellcheck/SpellCheckerSessionBridge.java
index bcedb75..b2ce329 100644
--- a/components/spellcheck/browser/android/java/src/org/chromium/components/spellcheck/SpellCheckerSessionBridge.java
+++ b/components/spellcheck/browser/android/java/src/org/chromium/components/spellcheck/SpellCheckerSessionBridge.java
@@ -106,6 +106,7 @@
 
         ArrayList<Integer> offsets = new ArrayList<Integer>();
         ArrayList<Integer> lengths = new ArrayList<Integer>();
+        ArrayList<String[]> suggestions = new ArrayList<String[]>();
 
         for (SentenceSuggestionsInfo result : results) {
             if (result == null) {
@@ -121,11 +122,19 @@
                         == SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) {
                     offsets.add(result.getOffsetAt(i));
                     lengths.add(result.getLengthAt(i));
+                    SuggestionsInfo info = result.getSuggestionsInfoAt(i);
+                    ArrayList<String> suggestions_for_word = new ArrayList<String>();
+                    for (int j = 0; j < info.getSuggestionsCount(); ++j) {
+                        suggestions_for_word.add(info.getSuggestionAt(j));
+                    }
+                    suggestions.add(
+                            suggestions_for_word.toArray(new String[suggestions_for_word.size()]));
                 }
             }
         }
         nativeProcessSpellCheckResults(mNativeSpellCheckerSessionBridge,
-                convertListToArray(offsets), convertListToArray(lengths));
+                convertListToArray(offsets), convertListToArray(lengths),
+                suggestions.toArray(new String[suggestions.size()][]));
 
         RecordHistogram.recordTimesHistogram("SpellCheck.Android.Latency",
                 mStopMs - mStartMs, TimeUnit.MILLISECONDS);
@@ -147,6 +156,6 @@
     @Override
     public void onGetSuggestions(SuggestionsInfo[] results) {}
 
-    private native void nativeProcessSpellCheckResults(
-            long nativeSpellCheckerSessionBridge, int[] offsets, int[] lengths);
+    private native void nativeProcessSpellCheckResults(long nativeSpellCheckerSessionBridge,
+            int[] offsets, int[] lengths, String[][] suggestions);
 }
diff --git a/components/spellcheck/browser/spellchecker_session_bridge_android.cc b/components/spellcheck/browser/spellchecker_session_bridge_android.cc
index de8b3f9..68d20a3 100644
--- a/components/spellcheck/browser/spellchecker_session_bridge_android.cc
+++ b/components/spellcheck/browser/spellchecker_session_bridge_android.cc
@@ -94,7 +94,8 @@
     JNIEnv* env,
     const JavaParamRef<jobject>& jobj,
     const JavaParamRef<jintArray>& offset_array,
-    const JavaParamRef<jintArray>& length_array) {
+    const JavaParamRef<jintArray>& length_array,
+    const JavaParamRef<jobjectArray>& suggestions_array) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   std::vector<int> offsets;
   std::vector<int> lengths;
@@ -104,8 +105,14 @@
 
   std::vector<SpellCheckResult> results;
   for (size_t i = 0; i < offsets.size(); i++) {
-    results.push_back(
-        SpellCheckResult(SpellCheckResult::SPELLING, offsets[i], lengths[i]));
+    base::android::ScopedJavaLocalRef<jobjectArray> suggestions_for_word_array(
+        env, static_cast<jobjectArray>(
+                 env->GetObjectArrayElement(suggestions_array, i)));
+    std::vector<base::string16> suggestions_for_word;
+    base::android::AppendJavaStringArrayToStringVector(
+        env, suggestions_for_word_array.obj(), &suggestions_for_word);
+    results.push_back(SpellCheckResult(SpellCheckResult::SPELLING, offsets[i],
+                                       lengths[i], suggestions_for_word));
   }
 
   content::RenderProcessHost* sender =
diff --git a/components/spellcheck/browser/spellchecker_session_bridge_android.h b/components/spellcheck/browser/spellchecker_session_bridge_android.h
index c849d32..a9118dc 100644
--- a/components/spellcheck/browser/spellchecker_session_bridge_android.h
+++ b/components/spellcheck/browser/spellchecker_session_bridge_android.h
@@ -35,7 +35,8 @@
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& jobj,
       const base::android::JavaParamRef<jintArray>& offset_array,
-      const base::android::JavaParamRef<jintArray>& length_array);
+      const base::android::JavaParamRef<jintArray>& length_array,
+      const base::android::JavaParamRef<jobjectArray>& suggestions_array);
 
   // Sets the handle to the Java SpellCheckerSessionBridge object to null,
   // marking the Java object for garbage collection.
diff --git a/components/viz/client/client_compositor_frame_sink.cc b/components/viz/client/client_compositor_frame_sink.cc
index 13e1faf..9c9299a 100644
--- a/components/viz/client/client_compositor_frame_sink.cc
+++ b/components/viz/client/client_compositor_frame_sink.cc
@@ -71,6 +71,8 @@
     return false;
 
   compositor_frame_sink_.Bind(std::move(compositor_frame_sink_info_));
+  compositor_frame_sink_.set_connection_error_with_reason_handler(
+      base::Bind(ClientCompositorFrameSink::OnMojoConnectionError));
   client_binding_.Bind(std::move(client_request_));
 
   if (synthetic_begin_frame_source_) {
@@ -112,6 +114,7 @@
     local_surface_id_ =
         local_surface_id_provider_->GetLocalSurfaceIdForFrame(frame);
   }
+
   compositor_frame_sink_->SubmitCompositorFrame(local_surface_id_,
                                                 std::move(frame));
 }
@@ -146,4 +149,12 @@
   compositor_frame_sink_->SetNeedsBeginFrame(needs_begin_frames);
 }
 
+// static
+void ClientCompositorFrameSink::OnMojoConnectionError(
+    uint32_t custom_reason,
+    const std::string& description) {
+  if (custom_reason)
+    DLOG(FATAL) << description;
+}
+
 }  // namespace viz
diff --git a/components/viz/client/client_compositor_frame_sink.h b/components/viz/client/client_compositor_frame_sink.h
index 25a6dd6..c866188 100644
--- a/components/viz/client/client_compositor_frame_sink.h
+++ b/components/viz/client/client_compositor_frame_sink.h
@@ -66,6 +66,9 @@
   // cc::ExternalBeginFrameSourceClient implementation.
   void OnNeedsBeginFrames(bool needs_begin_frames) override;
 
+  static void OnMojoConnectionError(uint32_t custom_reason,
+                                    const std::string& description);
+
   cc::LocalSurfaceId local_surface_id_;
   std::unique_ptr<LocalSurfaceIdProvider> local_surface_id_provider_;
   std::unique_ptr<cc::ExternalBeginFrameSource> begin_frame_source_;
diff --git a/components/viz/frame_sinks/gpu_compositor_frame_sink.cc b/components/viz/frame_sinks/gpu_compositor_frame_sink.cc
index bcb2441..8bc8039 100644
--- a/components/viz/frame_sinks/gpu_compositor_frame_sink.cc
+++ b/components/viz/frame_sinks/gpu_compositor_frame_sink.cc
@@ -44,7 +44,8 @@
     const cc::LocalSurfaceId& local_surface_id,
     cc::CompositorFrame frame) {
   if (!support_->SubmitCompositorFrame(local_surface_id, std::move(frame))) {
-    compositor_frame_sink_binding_.Close();
+    compositor_frame_sink_binding_.CloseWithReason(
+        1, "Surface invariants violation");
     OnClientConnectionLost();
   }
 }
diff --git a/content/browser/media/media_web_contents_observer.cc b/content/browser/media/media_web_contents_observer.cc
index aea94be..a93fd313 100644
--- a/content/browser/media/media_web_contents_observer.cc
+++ b/content/browser/media/media_web_contents_observer.cc
@@ -16,6 +16,7 @@
 #include "device/wake_lock/public/interfaces/wake_lock_context.mojom.h"
 #include "ipc/ipc_message_macros.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
+#include "ui/gfx/geometry/size.h"
 
 namespace content {
 
@@ -51,7 +52,7 @@
 
 void MediaWebContentsObserver::MaybeUpdateAudibleState() {
   AudioStreamMonitor* audio_stream_monitor =
-      static_cast<WebContentsImpl*>(web_contents())->audio_stream_monitor();
+      web_contents_impl()->audio_stream_monitor();
 
   if (audio_stream_monitor->WasRecentlyAudible())
     LockAudio();
@@ -88,8 +89,10 @@
     IPC_MESSAGE_HANDLER(MediaPlayerDelegateHostMsg_OnMediaPlaying,
                         OnMediaPlaying)
     IPC_MESSAGE_HANDLER(
-        MediaPlayerDelegateHostMsg_OnMediaEffectivelyFullscreenChange,
-        OnMediaEffectivelyFullscreenChange)
+        MediaPlayerDelegateHostMsg_OnMediaEffectivelyFullscreenChanged,
+        OnMediaEffectivelyFullscreenChanged)
+    IPC_MESSAGE_HANDLER(MediaPlayerDelegateHostMsg_OnMediaSizeChanged,
+                        OnMediaSizeChanged)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -139,10 +142,9 @@
 
   if (removed_audio || removed_video) {
     // Notify observers the player has been "paused".
-    static_cast<WebContentsImpl*>(web_contents())
-        ->MediaStoppedPlaying(
-            WebContentsObserver::MediaPlayerInfo(removed_video, removed_audio),
-            player_id);
+    web_contents_impl()->MediaStoppedPlaying(
+        WebContentsObserver::MediaPlayerInfo(removed_video, removed_audio),
+        player_id);
   }
 
   if (reached_end_of_stream)
@@ -172,7 +174,7 @@
     AddMediaPlayerEntry(id, &active_video_players_);
 
     // If we're not hidden and have just created a player, create a wakelock.
-    if (!static_cast<WebContentsImpl*>(web_contents())->IsHidden())
+    if (!web_contents_impl()->IsHidden())
       LockVideo();
   }
 
@@ -183,12 +185,11 @@
 
   // Notify observers of the new player.
   DCHECK(has_audio || has_video);
-  static_cast<WebContentsImpl*>(web_contents())
-      ->MediaStartedPlaying(
-          WebContentsObserver::MediaPlayerInfo(has_video, has_audio), id);
+  web_contents_impl()->MediaStartedPlaying(
+      WebContentsObserver::MediaPlayerInfo(has_video, has_audio), id);
 }
 
-void MediaWebContentsObserver::OnMediaEffectivelyFullscreenChange(
+void MediaWebContentsObserver::OnMediaEffectivelyFullscreenChanged(
     RenderFrameHost* render_frame_host,
     int delegate_id,
     bool is_fullscreen) {
@@ -203,6 +204,14 @@
   fullscreen_player_ = id;
 }
 
+void MediaWebContentsObserver::OnMediaSizeChanged(
+    RenderFrameHost* render_frame_host,
+    int delegate_id,
+    const gfx::Size& size) {
+  const MediaPlayerId id(render_frame_host, delegate_id);
+  web_contents_impl()->MediaResized(size, id);
+}
+
 void MediaWebContentsObserver::ClearWakeLocks(
     RenderFrameHost* render_frame_host) {
   std::set<MediaPlayerId> video_players;
@@ -220,12 +229,11 @@
   MaybeCancelVideoLock();
 
   // Notify all observers the player has been "paused".
-  WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents());
   for (const auto& id : removed_players) {
     auto it = video_players.find(id);
     bool was_video = (it != video_players.end());
     bool was_audio = (audio_players.find(id) != audio_players.end());
-    wci->MediaStoppedPlaying(
+    web_contents_impl()->MediaStoppedPlaying(
         WebContentsObserver::MediaPlayerInfo(was_video, was_audio), id);
   }
 }
@@ -330,4 +338,8 @@
   player_map->erase(it);
 }
 
+WebContentsImpl* MediaWebContentsObserver::web_contents_impl() const {
+  return static_cast<WebContentsImpl*>(web_contents());
+}
+
 }  // namespace content
diff --git a/content/browser/media/media_web_contents_observer.h b/content/browser/media/media_web_contents_observer.h
index 6e4ce5a5..095cddf 100644
--- a/content/browser/media/media_web_contents_observer.h
+++ b/content/browser/media/media_web_contents_observer.h
@@ -25,6 +25,10 @@
 enum class MediaContentType;
 }  // namespace media
 
+namespace gfx {
+class Size;
+}  // namespace size
+
 namespace content {
 
 // This class manages all RenderFrame based media related managers at the
@@ -84,9 +88,12 @@
                       bool has_audio,
                       bool is_remote,
                       media::MediaContentType media_content_type);
-  void OnMediaEffectivelyFullscreenChange(RenderFrameHost* render_frame_host,
-                                          int delegate_id,
-                                          bool is_fullscreen);
+  void OnMediaEffectivelyFullscreenChanged(RenderFrameHost* render_frame_host,
+                                           int delegate_id,
+                                           bool is_fullscreen);
+  void OnMediaSizeChanged(RenderFrameHost* render_frame_host,
+                          int delegate_id,
+                          const gfx::Size& size);
 
   // Clear |render_frame_host|'s tracking entry for its WakeLocks.
   void ClearWakeLocks(RenderFrameHost* render_frame_host);
@@ -115,6 +122,9 @@
                                    ActiveMediaPlayerMap* player_map,
                                    std::set<MediaPlayerId>* removed_players);
 
+  // Convenience method that casts web_contents() to a WebContentsImpl*.
+  WebContentsImpl* web_contents_impl() const;
+
   // Tracking variables and associated wake locks for media playback.
   ActiveMediaPlayerMap active_audio_players_;
   ActiveMediaPlayerMap active_video_players_;
diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc
index 3b2550c2..6e28ceb 100644
--- a/content/browser/web_contents/web_contents_android.cc
+++ b/content/browser/web_contents/web_contents_android.cc
@@ -670,6 +670,25 @@
   return web_contents_->HasActiveEffectivelyFullscreenVideo();
 }
 
+base::android::ScopedJavaLocalRef<jobject>
+WebContentsAndroid::GetCurrentlyPlayingVideoSizes(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& obj) {
+  const WebContents::VideoSizeMap& sizes =
+      web_contents_->GetCurrentlyPlayingVideoSizes();
+  DCHECK_GT(sizes.size(), 0u);
+
+  ScopedJavaLocalRef<jobject> jsizes = Java_WebContentsImpl_createSizeList(env);
+
+  using MapEntry = std::pair<WebContentsObserver::MediaPlayerId, gfx::Size>;
+  for (const MapEntry& entry : sizes) {
+    Java_WebContentsImpl_createSizeAndAddToList(
+        env, jsizes, entry.second.width(), entry.second.height());
+  }
+
+  return jsizes;
+}
+
 ScopedJavaLocalRef<jobject> WebContentsAndroid::GetOrCreateEventForwarder(
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& obj) {
diff --git a/content/browser/web_contents/web_contents_android.h b/content/browser/web_contents/web_contents_android.h
index 846b5de..6d26a839 100644
--- a/content/browser/web_contents/web_contents_android.h
+++ b/content/browser/web_contents/web_contents_android.h
@@ -211,6 +211,9 @@
   bool HasActiveEffectivelyFullscreenVideo(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj);
+  base::android::ScopedJavaLocalRef<jobject> GetCurrentlyPlayingVideoSizes(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
 
   base::android::ScopedJavaLocalRef<jobject> GetOrCreateEventForwarder(
       JNIEnv* env,
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index ffba46b..19218bc 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -5586,6 +5586,20 @@
     observer.MediaStoppedPlaying(media_info, id);
 }
 
+void WebContentsImpl::MediaResized(
+    const gfx::Size& size,
+    const WebContentsObserver::MediaPlayerId& id) {
+  cached_video_sizes_[id] = size;
+
+  for (auto& observer : observers_)
+    observer.MediaResized(size, id);
+}
+
+const WebContents::VideoSizeMap&
+WebContentsImpl::GetCurrentlyPlayingVideoSizes() {
+  return cached_video_sizes_;
+}
+
 int WebContentsImpl::GetCurrentlyPlayingVideoCount() {
   return currently_playing_video_count_;
 }
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 6f3dcbd9..f0248372 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -823,8 +823,13 @@
   void MediaStoppedPlaying(
       const WebContentsObserver::MediaPlayerInfo& media_info,
       const WebContentsObserver::MediaPlayerId& id);
-  int GetCurrentlyPlayingVideoCount() override;
+  // This will be called before playback is started, check
+  // GetCurrentlyPlayingVideoCount if you need this when playback starts.
+  void MediaResized(const gfx::Size& size,
+                    const WebContentsObserver::MediaPlayerId& id);
 
+  int GetCurrentlyPlayingVideoCount() override;
+  const VideoSizeMap& GetCurrentlyPlayingVideoSizes() override;
   bool IsFullscreen() override;
 
   MediaWebContentsObserver* media_web_contents_observer() {
@@ -1613,6 +1618,7 @@
   bool showing_context_menu_;
 
   int currently_playing_video_count_ = 0;
+  VideoSizeMap cached_video_sizes_;
 
   bool has_persistent_video_ = false;
 
diff --git a/content/browser/webrtc/webrtc_image_capture_browsertest.cc b/content/browser/webrtc/webrtc_image_capture_browsertest.cc
index d5641934..687c325 100644
--- a/content/browser/webrtc/webrtc_image_capture_browsertest.cc
+++ b/content/browser/webrtc/webrtc_image_capture_browsertest.cc
@@ -22,13 +22,19 @@
 
 #if defined(OS_WIN)
 // These tests are flaky on WebRTC Windows bots: https://crbug.com/633242.
-#define MAYBE_GetCapabilities DISABLED_GetCapabilities
+#define MAYBE_GetPhotoCapabilities DISABLED_GetPhotoCapabilities
 #define MAYBE_TakePhoto DISABLED_TakePhoto
 #define MAYBE_GrabFrame DISABLED_GrabFrame
+#define MAYBE_GetTrackCapabilities DISABLED_GetTrackCapabilities
+#define MAYBE_GetTrackSettings DISABLED_GetTrackSettings
+#define MAYBE_ManipulateZoom DISABLED_ManipulateZoom
 #else
-#define MAYBE_GetCapabilities GetCapabilities
+#define MAYBE_GetPhotoCapabilities GetPhotoCapabilities
 #define MAYBE_TakePhoto TakePhoto
 #define MAYBE_GrabFrame GrabFrame
+#define MAYBE_GetTrackCapabilities GetTrackCapabilities
+#define MAYBE_GetTrackSettings GetTrackSettings
+#define MAYBE_ManipulateZoom ManipulateZoom
 #endif
 
 namespace {
@@ -71,10 +77,8 @@
 
     // "GetUserMedia": enables navigator.mediaDevices.getUserMedia();
     // TODO(mcasas): remove GetUserMedia after https://crbug.com/503227.
-    // "ImageCapture": enables the ImageCapture API.
-    // TODO(mcasas): remove ImageCapture after https://crbug.com/603328.
     base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-        switches::kEnableBlinkFeatures, "GetUserMedia,ImageCapture");
+        switches::kEnableBlinkFeatures, "GetUserMedia");
   }
 
   void SetUp() override {
@@ -112,9 +116,10 @@
   DISALLOW_COPY_AND_ASSIGN(WebRtcImageCaptureBrowserTest);
 };
 
-IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureBrowserTest, MAYBE_GetCapabilities) {
+IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureBrowserTest,
+                       MAYBE_GetPhotoCapabilities) {
   embedded_test_server()->StartAcceptingConnections();
-  ASSERT_TRUE(RunImageCaptureTestCase("testCreateAndGetCapabilities()"));
+  ASSERT_TRUE(RunImageCaptureTestCase("testCreateAndGetPhotoCapabilities()"));
 }
 
 IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureBrowserTest, MAYBE_TakePhoto) {
@@ -127,6 +132,22 @@
   ASSERT_TRUE(RunImageCaptureTestCase("testCreateAndGrabFrame()"));
 }
 
+IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureBrowserTest,
+                       MAYBE_GetTrackCapabilities) {
+  embedded_test_server()->StartAcceptingConnections();
+  ASSERT_TRUE(RunImageCaptureTestCase("testCreateAndGetTrackCapabilities()"));
+}
+
+IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureBrowserTest, MAYBE_GetTrackSettings) {
+  embedded_test_server()->StartAcceptingConnections();
+  ASSERT_TRUE(RunImageCaptureTestCase("testCreateAndGetTrackSettings()"));
+}
+
+IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureBrowserTest, MAYBE_ManipulateZoom) {
+  embedded_test_server()->StartAcceptingConnections();
+  ASSERT_TRUE(RunImageCaptureTestCase("testManipulateZoom()"));
+}
+
 INSTANTIATE_TEST_CASE_P(,
                         WebRtcImageCaptureBrowserTest,
                         testing::ValuesIn(kTestParameters));
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc
index acd699d..5a38041 100644
--- a/content/child/web_url_loader_impl.cc
+++ b/content/child/web_url_loader_impl.cc
@@ -13,7 +13,6 @@
 #include <vector>
 
 #include "base/bind.h"
-#include "base/debug/dump_without_crashing.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
@@ -616,17 +615,6 @@
     }
   }
 
-  // PlzNavigate: Invalid renderer main resource requests are rejected by the
-  // browser. This should not happen.
-  // TODO(arthursonzogni): Remove this when the root cause for
-  // https://crbug.com/705508 is found.
-  if (IsBrowserSideNavigationEnabled() &&
-      IsResourceTypeFrame(resource_request->resource_type) &&
-      !resource_request->resource_body_stream_url.SchemeIs(url::kBlobScheme) &&
-      !consumer_handle.is_valid()) {
-    base::debug::DumpWithoutCrashing();
-  }
-
   RequestExtraData empty_extra_data;
   RequestExtraData* extra_data;
   if (request.GetExtraData())
diff --git a/content/common/media/media_player_delegate_messages.h b/content/common/media/media_player_delegate_messages.h
index 0be4c6c..9f6e0eb4 100644
--- a/content/common/media/media_player_delegate_messages.h
+++ b/content/common/media/media_player_delegate_messages.h
@@ -11,6 +11,7 @@
 #include "content/common/content_export.h"
 #include "ipc/ipc_message_macros.h"
 #include "media/base/media_content_type.h"
+#include "ui/gfx/ipc/geometry/gfx_param_traits.h"
 
 #undef IPC_MESSAGE_EXPORT
 #define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@@ -57,6 +58,10 @@
                     media::MediaContentType /* media_content_type */)
 
 IPC_MESSAGE_ROUTED2(
-    MediaPlayerDelegateHostMsg_OnMediaEffectivelyFullscreenChange,
-    int /* delegate_id */,
+    MediaPlayerDelegateHostMsg_OnMediaEffectivelyFullscreenChanged,
+    int /* delegate_id, distinguishes instances */,
     bool /* is_fullscreen */)
+
+IPC_MESSAGE_ROUTED2(MediaPlayerDelegateHostMsg_OnMediaSizeChanged,
+                    int /* delegate_id, distinguishes instances */,
+                    gfx::Size /* new size of video */)
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
index 5d9f7277..57b60f42 100644
--- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
@@ -582,6 +582,11 @@
         return nativeHasActiveEffectivelyFullscreenVideo(mNativeWebContentsAndroid);
     }
 
+    @Override
+    public List<Rect> getCurrentlyPlayingVideoSizes() {
+        return nativeGetCurrentlyPlayingVideoSizes(mNativeWebContentsAndroid);
+    }
+
     @CalledByNative
     private final void setMediaSession(MediaSessionImpl mediaSession) {
         mMediaSession = mediaSession;
@@ -675,5 +680,6 @@
             long nativeWebContentsAndroid, int x, int y);
     private native void nativeSetHasPersistentVideo(long nativeWebContentsAndroid, boolean value);
     private native boolean nativeHasActiveEffectivelyFullscreenVideo(long nativeWebContentsAndroid);
+    private native List<Rect> nativeGetCurrentlyPlayingVideoSizes(long nativeWebContentsAndroid);
     private native EventForwarder nativeGetOrCreateEventForwarder(long nativeWebContentsAndroid);
 }
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
index 800ee61..4a0bcc23 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
@@ -4,6 +4,7 @@
 
 package org.chromium.content_public.browser;
 
+import android.graphics.Rect;
 import android.os.Handler;
 import android.os.Parcelable;
 
@@ -13,6 +14,8 @@
 import org.chromium.ui.base.EventForwarder;
 import org.chromium.ui.base.WindowAndroid;
 
+import java.util.List;
+
 /**
  * The WebContents Java wrapper to allow communicating with the native WebContents object.
  *
@@ -424,6 +427,12 @@
     public boolean hasActiveEffectivelyFullscreenVideo();
 
     /**
+     * Gets a Rect containing the size of the currently playing video. The position of the rectangle
+     * is meaningless.
+     */
+    public List<Rect> getCurrentlyPlayingVideoSizes();
+
+    /**
      * Issues a fake notification about the renderer being killed.
      *
      * @param wasOomProtected True if the renderer was protected from the OS out-of-memory killer
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index 3e1ed690..7975145 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -23,6 +23,7 @@
 #include "content/public/browser/save_page_type.h"
 #include "content/public/browser/screen_orientation_delegate.h"
 #include "content/public/browser/site_instance.h"
+#include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/common/stop_find_action.h"
 #include "ipc/ipc_sender.h"
@@ -774,6 +775,11 @@
   virtual void SetIsOverlayContent(bool is_overlay_content) = 0;
 
   virtual int GetCurrentlyPlayingVideoCount() = 0;
+
+  // Returns a map containing the sizes of all currently playing videos.
+  using VideoSizeMap =
+      base::flat_map<WebContentsObserver::MediaPlayerId, gfx::Size>;
+  virtual const VideoSizeMap& GetCurrentlyPlayingVideoSizes() = 0;
   virtual bool IsFullscreen() = 0;
 
   // Tells the renderer to clear the focused element (if any).
diff --git a/content/public/browser/web_contents_observer.h b/content/public/browser/web_contents_observer.h
index c16a615..a9ebcc33 100644
--- a/content/public/browser/web_contents_observer.h
+++ b/content/public/browser/web_contents_observer.h
@@ -23,6 +23,10 @@
 #include "ui/base/page_transition_types.h"
 #include "ui/base/window_open_disposition.h"
 
+namespace gfx {
+class Size;
+}  // namespace gfx
+
 namespace content {
 
 class NavigationEntry;
@@ -414,6 +418,7 @@
                                    const MediaPlayerId& id) {}
   virtual void MediaStoppedPlaying(const MediaPlayerInfo& video_type,
                                    const MediaPlayerId& id) {}
+  virtual void MediaResized(const gfx::Size& size, const MediaPlayerId& id) {}
 
   // Invoked when the renderer process changes the page scale factor.
   virtual void OnPageScaleFactorChanged(float page_scale_factor) {}
diff --git a/content/renderer/media/renderer_webmediaplayer_delegate.cc b/content/renderer/media/renderer_webmediaplayer_delegate.cc
index 99d76f6..5c60e6a 100644
--- a/content/renderer/media/renderer_webmediaplayer_delegate.cc
+++ b/content/renderer/media/renderer_webmediaplayer_delegate.cc
@@ -15,6 +15,7 @@
 #include "content/public/renderer/render_thread.h"
 #include "third_party/WebKit/public/platform/WebMediaPlayer.h"
 #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
+#include "ui/gfx/geometry/size.h"
 
 #if defined(OS_ANDROID)
 #include "base/android/build_info.h"
@@ -165,10 +166,17 @@
 void RendererWebMediaPlayerDelegate::SetIsEffectivelyFullscreen(
     int player_id,
     bool is_fullscreen) {
-  Send(new MediaPlayerDelegateHostMsg_OnMediaEffectivelyFullscreenChange(
+  Send(new MediaPlayerDelegateHostMsg_OnMediaEffectivelyFullscreenChanged(
       routing_id(), player_id, is_fullscreen));
 }
 
+void RendererWebMediaPlayerDelegate::DidPlayerSizeChange(
+    int delegate_id,
+    const gfx::Size& size) {
+  Send(new MediaPlayerDelegateHostMsg_OnMediaSizeChanged(routing_id(),
+                                                         delegate_id, size));
+}
+
 void RendererWebMediaPlayerDelegate::WasHidden() {
   RecordAction(base::UserMetricsAction("Media.Hidden"));
 
diff --git a/content/renderer/media/renderer_webmediaplayer_delegate.h b/content/renderer/media/renderer_webmediaplayer_delegate.h
index de7f7ed..e2f9f00b 100644
--- a/content/renderer/media/renderer_webmediaplayer_delegate.h
+++ b/content/renderer/media/renderer_webmediaplayer_delegate.h
@@ -58,6 +58,7 @@
   void ClearStaleFlag(int player_id) override;
   bool IsStale(int player_id) override;
   void SetIsEffectivelyFullscreen(int player_id, bool is_fullscreen) override;
+  void DidPlayerSizeChange(int delegate_id, const gfx::Size& size) override;
 
   // content::RenderFrameObserver overrides.
   void WasHidden() override;
diff --git a/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc b/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc
index 4c075e1..7ad468d 100644
--- a/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc
+++ b/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc
@@ -153,6 +153,22 @@
         MediaPlayerDelegateHostMsg_OnMediaDestroyed::Read(msg, &result));
     EXPECT_EQ(delegate_id, std::get<0>(result));
   }
+
+  // Verify the resize message.
+  {
+    test_sink().ClearMessages();
+    delegate_manager_->DidPlayerSizeChange(delegate_id, gfx::Size(16, 9));
+    const IPC::Message* msg = test_sink().GetUniqueMessageMatching(
+        MediaPlayerDelegateHostMsg_OnMediaSizeChanged::ID);
+    ASSERT_TRUE(msg);
+
+    std::tuple<int, gfx::Size> result;
+    ASSERT_TRUE(
+        MediaPlayerDelegateHostMsg_OnMediaSizeChanged::Read(msg, &result));
+    EXPECT_EQ(delegate_id, std::get<0>(result));
+    EXPECT_EQ(16, std::get<1>(result).width());
+    EXPECT_EQ(9, std::get<1>(result).height());
+  }
 }
 
 TEST_F(RendererWebMediaPlayerDelegateTest, DeliversObserverNotifications) {
diff --git a/content/renderer/media/webmediaplayer_ms.cc b/content/renderer/media/webmediaplayer_ms.cc
index d41842b8..b4af48649 100644
--- a/content/renderer/media/webmediaplayer_ms.cc
+++ b/content/renderer/media/webmediaplayer_ms.cc
@@ -290,6 +290,8 @@
   if (audio_renderer_)
     audio_renderer_->Play();
 
+  if (HasVideo())
+    delegate_->DidPlayerSizeChange(delegate_id_, NaturalSize());
   // TODO(perkj, magjed): We use OneShot focus type here so that it takes
   // audio focus once it starts, and then will not respond to further audio
   // focus changes. See http://crbug.com/596516 for more details.
@@ -719,6 +721,8 @@
 
 void WebMediaPlayerMS::TriggerResize() {
   get_client()->SizeChanged();
+
+  delegate_->DidPlayerSizeChange(delegate_id_, NaturalSize());
 }
 
 }  // namespace content
diff --git a/content/renderer/media/webmediaplayer_ms_unittest.cc b/content/renderer/media/webmediaplayer_ms_unittest.cc
index 3f89c88..3cb79ca 100644
--- a/content/renderer/media/webmediaplayer_ms_unittest.cc
+++ b/content/renderer/media/webmediaplayer_ms_unittest.cc
@@ -71,6 +71,10 @@
     playing_ = false;
   }
 
+  void DidPlayerSizeChange(int delegate_id, const gfx::Size& size) override {
+    EXPECT_EQ(delegate_id_, delegate_id);
+  }
+
   void PlayerGone(int delegate_id) override {
     EXPECT_EQ(delegate_id_, delegate_id);
     is_gone_ = true;
diff --git a/content/test/data/media/image_capture_test.html b/content/test/data/media/image_capture_test.html
index 3fddb19..5ce478b9 100644
--- a/content/test/data/media/image_capture_test.html
+++ b/content/test/data/media/image_capture_test.html
@@ -1,4 +1,4 @@
-B<!DOCTYPE html>
+<!DOCTYPE html>
 <html>
 <head>
 <!-- Image Capture Browser Test -->
@@ -9,8 +9,15 @@
 const WIDTH = 320;
 /** @const */ var CONSTRAINTS = { width: { max : WIDTH } };
 
+// Returns a Promise resolved with |object| after a delay of |delayInMs|.
+function delayedResolver(object, delayInMs) {
+  return new Promise((resolve, reject) => {
+    setTimeout(() => { resolve(object); }, delayInMs);
+  });
+}
+
 // Runs an ImageCapture.getPhotoCapabilities().
-function testCreateAndGetCapabilities() {
+function testCreateAndGetPhotoCapabilities() {
   navigator.mediaDevices.getUserMedia({"video" : CONSTRAINTS})
       .then(stream => {
         assertEquals('video', stream.getVideoTracks()[0].kind);
@@ -71,6 +78,87 @@
       });
 }
 
+// Runs a MediaStreamTrack.getCapabilities().
+function testCreateAndGetTrackCapabilities() {
+  navigator.mediaDevices.getUserMedia({"video" : CONSTRAINTS})
+      .then(stream => {
+        assertEquals('video', stream.getVideoTracks()[0].kind);
+        return new ImageCapture(stream.getVideoTracks()[0]);
+      })
+      .then(capturer => {
+        // TODO(mcasas): remove this extra timeout, https://crbug.com/711524.
+        return delayedResolver(capturer, 200);
+      })
+      .then(capturer => {
+        capturer.track.getCapabilities();
+        // There's nothing to check here since |capabilities| vary per device.
+        reportTestSuccess();
+      })
+      .catch(err => {
+        return failTest(err.toString());
+      });
+}
+
+// Runs an MediaStreamTrack.getSettings().
+function testCreateAndGetTrackSettings() {
+  navigator.mediaDevices.getUserMedia({"video" : CONSTRAINTS})
+      .then(stream => {
+        assertEquals('video', stream.getVideoTracks()[0].kind);
+        return new ImageCapture(stream.getVideoTracks()[0]);
+      })
+      .then(capturer => {
+        // TODO(mcasas): remove this extra timeout, https://crbug.com/711524.
+        return delayedResolver(capturer, 200);
+      })
+      .then(capturer => {
+        capturer.track.getSettings();
+        // There's nothing to check here since |settings| vary per device.
+        reportTestSuccess();
+      })
+      .catch(err => {
+        return failTest(err.toString());
+      });
+}
+
+// Tries to read, set and read back the zoom capability if available.
+function testManipulateZoom() {
+  var newZoom = -1;
+  var imageCapturer;
+  navigator.mediaDevices.getUserMedia({"video" : CONSTRAINTS})
+      .then(stream => {
+        assertEquals('video', stream.getVideoTracks()[0].kind);
+        return new ImageCapture(stream.getVideoTracks()[0]);
+      })
+      .then(capturer => {
+        // TODO(mcasas): remove this extra timeout, https://crbug.com/711524.
+        return delayedResolver(capturer, 200);
+      })
+      .then(capturer => {
+        const trackCapabilities = capturer.track.getCapabilities();
+        if (trackCapabilities.zoom === undefined) {
+          console.log('zoom not supported, skipping test');
+          reportTestSuccess();
+          return;
+        }
+
+        const currentZoom = capturer.track.getSettings().zoom;
+        newZoom = currentZoom + trackCapabilities.zoom.step;
+        newZoom = Math.min(newZoom, trackCapabilities.zoom.max);
+        console.log("Setting zoom from " + currentZoom + " to " + newZoom);
+
+        imageCapturer = capturer;
+        return capturer.track.applyConstraints({advanced : [{zoom : newZoom}]});
+      })
+      .then(appliedConstraints => {
+        assertEquals(newZoom, appliedConstraints.advanced[0].zoom);
+        assertEquals(newZoom, imageCapturer.track.getSettings().zoom);
+        reportTestSuccess();
+      })
+      .catch(err => {
+        return failTest(err.toString());
+      });
+}
+
 </script>
 </body>
 </html>
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index 4654ae71..9e451d7 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -72,16 +72,33 @@
         'draw-with-integer-texture-base-level.html',
         ['win', 'nvidia', 'd3d11'], bug=679639)
 
-    # Win10 / NVIDIA Quadro P400 / D3D11 failures
+    # Win10 / NVIDIA Quadro P400 / D3D11 flaky failures
     self.Fail('deqp/functional/gles3/transformfeedback/' +
         'basic_types_interleaved_lines.html',
         ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754)
     self.Fail('deqp/functional/gles3/transformfeedback/' +
+        'basic_types_interleaved_triangles.html',
+        ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754)
+    self.Fail('deqp/functional/gles3/transformfeedback/' +
         'basic_types_separate_lines.html',
         ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754)
     self.Fail('deqp/functional/gles3/transformfeedback/' +
+        'basic_types_separate_triangles.html',
+        ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754)
+    self.Fail('deqp/functional/gles3/transformfeedback/' +
+        'random_interleaved_lines.html',
+        ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754)
+    self.Fail('deqp/functional/gles3/transformfeedback/' +
         'random_interleaved_triangles.html',
         ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754)
+    self.Fail('deqp/functional/gles3/transformfeedback/' +
+        'random_separate_lines.html',
+        ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754)
+    self.Fail('deqp/functional/gles3/transformfeedback/' +
+        'random_separate_triangles.html',
+        ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754)
+    self.Fail('deqp/functional/gles3/transformfeedback/interpolation_flat.html',
+        ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=680754)
     self.Flaky('conformance/textures/image_bitmap_from_video/' +
         'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html',
         ['win10', ('nvidia', 0x1cb3), 'd3d11'], bug=728670)
diff --git a/docs/task_scheduler_migration.md b/docs/task_scheduler_migration.md
index c08ccc6..c5afe28 100644
--- a/docs/task_scheduler_migration.md
+++ b/docs/task_scheduler_migration.md
@@ -12,8 +12,17 @@
 Much of the migration has already been automated but the callers that remain
 require manual intervention from the OWNERS.
 
+Here's [a list](https://docs.google.com/spreadsheets/d/18x9PGMlfgWcBr4fDz2SEEtIwTpSjcBFT2Puib47ZF1w/edit)
+of everything that's left. Please pick items in this list, assign them to self
+and tick the boxes when done.
+
+And some [slides](https://docs.google.com/presentation/d/191H9hBO0r5pH2JVMeYYV-yrP1175JoSlrZyK5QEeUlE/edit?usp=sharing)
+with a migration example.
+
 ## BlockingPool (and other SequencedWorkerPools)
 
+Tag migration CLs with BUG=[667892](https://crbug.com/667892).
+
 The remaining callers of BrowserThread::GetBlockingPool() require manual
 intervention because they're plumbing the SequencedWorkerPool multiple layers
 into another component.
@@ -39,11 +48,20 @@
 will run in TaskScheduler and that'd be meaningless... As such prefer asserting
 the properties your task needs as documentation rather than where it runs.
 
+You can of course still use
+```cpp
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
+```
+if you have access to the TaskRunner instance (generic asserts discussed above
+are meant for anonymous methods that require static checks).
+
 ## BrowserThreads
 
 All BrowserThreads but UI/IO are being migrated to TaskScheduler
 (i.e. FILE/FILE_USER_BLOCKING/DB/PROCESS_LAUNCHER/CACHE).
 
+Tag migration CLs with BUG=[689520](https://crbug.com/689520).
+
 This migration requires manual intervention because:
  1. Everything on BrowserThread::FOO has to be assumed to depend on being
     sequenced with everything else on BrowserThread::FOO until decided otherwise
@@ -51,11 +69,16 @@
  2. Everything on BrowserThread::FOO has to be assumed to be thread-affine until
     decided otherwise by a developer.
 
-As a developer your goal is to get rid of all uses of BrowserThread::FOO in your assigned files by:
+As a developer your goal is to get rid of all uses of BrowserThread::FOO in your
+assigned files by:
  1. Splitting things into their own execution sequence (i.e. post to a TaskRunner
     obtained from post_task.h -- see [Threading and Tasks in
     Chrome](threading_and_tasks.md) for details).
- 2. Ideally migrating from a single-threaded context to a [much preferred]
+ 2. Removing the plumbing: if GetTaskRunnerForThread(BrowserThread::FOO) is
+    passed down into a component the prefered paradigm is to remove all of that
+    plumbing and simply have the leaf layers requiring a TaskRunner get it from
+    base::CreateSequenceTaskRunnerWithTraits() directly.
+ 3. Ideally migrating from a single-threaded context to a [much preferred]
     (threading_and_tasks.md#Prefer-Sequences-to-Threads) sequenced context.
     * Note: if your tasks use COM APIs (Component Object Model on Windows),
       you'll need to use CreateCOMSTATaskRunnerWithTraits() and sequencing will
@@ -96,6 +119,10 @@
 * Everything in a file/component needs to run on the same sequence but there
   isn't a clear place to own/access the common SequencedTaskRunner =>
   [base::Lazy*TaskRunner](https://chromium-review.googlesource.com/c/524141/).
+* Mojo isn't sequence-friendly yet ([coming soon](https://crbug.com/678155)).
+  Use base::CreateSingleThreadTaskRunnerWithTraits() instead of
+  base::CreateSequenceTaskRunnerWithTraits() for sequences that need to use mojo
+  constructs for now (tag with TODO against https://crbug.com/678155).
 * For anything else, ping [base/task_scheduler/OWNERS](https://cs.chromium.org/chromium/src/base/task_scheduler/OWNERS)
   or [scheduler-dev@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/scheduler-dev),
   thanks!
diff --git a/extensions/shell/installer/BUILD.gn b/extensions/shell/installer/BUILD.gn
new file mode 100644
index 0000000..5d8aa82
--- /dev/null
+++ b/extensions/shell/installer/BUILD.gn
@@ -0,0 +1,25 @@
+# Copyright 2017 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("//build/config/ui.gni")
+import("//build/util/process_version.gni")
+import("//extensions/features/features.gni")
+
+assert(enable_extensions)
+
+declare_args() {
+  enable_app_shell_installer =
+      is_desktop_linux && is_chrome_branded && current_cpu == "x64"
+}
+
+# Meta-target that forwards to the installer of the correct type (if any).
+group("installer") {
+  # See the "app_shell_lib" definition for why testonly is needed.
+  testonly = true
+  if (enable_app_shell_installer) {
+    deps = [
+      "//extensions/shell/installer/linux",
+    ]
+  }
+}
diff --git a/extensions/shell/installer/linux/BUILD.gn b/extensions/shell/installer/linux/BUILD.gn
new file mode 100644
index 0000000..8883c20
--- /dev/null
+++ b/extensions/shell/installer/linux/BUILD.gn
@@ -0,0 +1,220 @@
+# Copyright 2017 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.
+
+# TODO(michaelpg): Dedupe with Chrome installer.
+
+import("//build/config/chrome_build.gni")
+import("//build/config/features.gni")
+import("//build/config/sanitizers/sanitizers.gni")
+import("//build/config/sysroot.gni")
+import("//build/util/version.gni")
+import("//chrome/process_version_rc_template.gni")  # For branding_file_path.
+
+assert(is_desktop_linux)
+assert(current_cpu == "x64")
+
+# The packages list the exact versions of each library used. The versions used
+# on the bots are likely different than those on your workstation, so you'll
+# get a stream of errors like:
+#   < libasound2 (>= 1.0.23)
+#   ---
+#   > libasound2 (>= 1.0.16)
+#
+# To avoid these warnings for testing purposes, do:
+#
+#   export IGNORE_DEPS_CHANGES=1
+#
+# before you build.
+group("linux") {
+  # See the "app_shell_lib" definition for why testonly is needed.
+  testonly = true
+  deps = [
+    # TODO(michaelpg): Add beta/stable once we verify the unstable installer is
+    # building and installing properly.
+    ":unstable",
+  ]
+}
+
+branding_dir = "//chrome/app/theme/$branding_path_component"
+
+copy("common_packaging_files") {
+  visibility = [ ":*" ]
+  sources = [
+    "//chrome/installer/linux/common/apt.include",
+    "//chrome/installer/linux/common/repo.cron",
+    "//chrome/installer/linux/common/symlinks.include",
+    "//chrome/installer/linux/common/variables.include",
+    "/usr/bin/eu-strip",
+    "common/installer.include",
+    "common/wrapper",
+  ]
+
+  if (is_chrome_branded) {
+    sources += [ "common/google-app-shell/google-app-shell.info" ]
+  } else {
+    sources += [ "common/chromium-app-shell/chromium-app-shell.info" ]
+  }
+
+  outputs = [
+    "$root_out_dir/app_shell_installer/common/{{source_file_part}}",
+  ]
+}
+
+copy("deb_packaging_files") {
+  visibility = [ ":*" ]
+  sources = [
+    "//chrome/installer/linux/debian/changelog.template",
+    "//chrome/installer/linux/debian/control.template",
+    "debian/build.sh",
+    "debian/expected_deps_x64_jessie",
+    "debian/postinst",
+    "debian/postrm",
+  ]
+  outputs = [
+    "$root_out_dir/app_shell_installer/debian/{{source_file_part}}",
+  ]
+}
+
+copy("theme_files") {
+  visibility = [ ":*" ]
+  sources = [
+    "$branding_dir/BRANDING",
+  ]
+  outputs = [
+    "$root_out_dir/app_shell_installer/theme/{{source_file_part}}",
+  ]
+}
+
+process_version("save_build_info") {
+  # Just output the default version info variables (no template).
+  process_only = true
+  sources = [
+    "//build/util/LASTCHANGE",
+    "//chrome/VERSION",
+    branding_file_path,
+  ]
+  output = "$root_out_dir/app_shell_installer/version.txt"
+}
+
+# Dependencies for all Linux installer targets.
+group("installer_deps") {
+  testonly = true
+
+  # Though many of these things appear in data_deps further down the
+  # dependency chain, they must appear here as public_deps so that they can
+  # be listed as inputs to the actions that depend on ":installer_deps"
+  # and are guaranteed to have been built before those actions run.
+
+  public_deps = [
+    ":common_packaging_files",
+    ":deb_packaging_files",
+    ":save_build_info",
+    ":theme_files",
+    "//extensions:shell_and_test_pak",
+    "//extensions/shell:app_shell",
+  ]
+  if (enable_nacl) {
+    public_deps += [
+      "//components/nacl/loader:nacl_helper",
+
+      # These are data_deps of nacl_helper, but that is not enough,
+      # as explained above.
+      "//native_client/src/trusted/service_runtime/linux:bootstrap",
+      "//ppapi/native_client:irt",
+    ]
+  }
+  if (use_custom_libcxx) {
+    public_deps += [ "//buildtools/third_party/libc++" ]
+  }
+}
+
+# Creates .deb installer package.
+#
+# channel:
+#   Name of the channel.
+template("linux_package") {
+  testonly = true
+  assert(defined(invoker.channel))
+  channel = invoker.channel
+
+  packaging_files_binaries = [
+    # TODO(mmoss) Any convenient way to get all the relevant build
+    # files? (e.g. all locales, resources, etc.)
+    "$root_out_dir/app_shell",
+    "$root_out_dir/extensions_shell_and_test.pak",
+  ]
+
+  if (enable_nacl) {
+    packaging_files_binaries += [
+      "$root_out_dir/nacl_helper",
+      "$root_out_dir/nacl_helper_bootstrap",
+      "$root_out_dir/nacl_irt_x86_64.nexe",
+    ]
+  }
+
+  if (use_custom_libcxx) {
+    packaging_files_binaries += [ "$root_out_dir/libc++.so" ]
+  }
+
+  deb_target_name = "${target_name}_deb"
+  action(deb_target_name) {
+    visibility = [ ":*" ]
+    script = "//chrome/installer/linux/flock_make_package.py"
+    deb_arch = "amd64"
+
+    inputs = packaging_files_binaries
+    outputs = [
+      "$root_out_dir/google-app-shell-${channel}_${chrome_version_full}-1_${deb_arch}.deb",
+    ]
+
+    args = [
+      rebase_path("$root_out_dir/linux_package.lock", root_build_dir),
+      rebase_path("$root_out_dir/app_shell_installer/debian/build.sh",
+                  root_build_dir),
+      "-o",
+      rebase_path(root_out_dir, root_build_dir),
+      "-b",
+      rebase_path(root_out_dir, root_build_dir),
+      "-a",
+      current_cpu,
+      "-c",
+      invoker.channel,
+      "-d",
+      branding_path_component,
+      "-s",
+      rebase_path(sysroot),
+    ]
+    deps = [
+      ":installer_deps",
+    ]
+  }
+
+  group(target_name) {
+    deps = [
+      ":$deb_target_name",
+    ]
+  }
+}
+
+# Standard packages.
+linux_package("unstable") {
+  channel = "unstable"
+}
+linux_package("stable") {
+  channel = "stable"
+}
+linux_package("beta") {
+  channel = "beta"
+}
+
+# Other packages that we support that aren't included in the default "linux"
+# target.
+linux_package("trunk") {
+  channel = "trunk"
+}
+if (is_asan) {
+  linux_package("asan") {
+    channel = "asan"
+  }
+}
diff --git a/extensions/shell/installer/linux/common/chromium-app-shell/chromium-app-shell.info b/extensions/shell/installer/linux/common/chromium-app-shell/chromium-app-shell.info
new file mode 100644
index 0000000..ee88042
--- /dev/null
+++ b/extensions/shell/installer/linux/common/chromium-app-shell/chromium-app-shell.info
@@ -0,0 +1,30 @@
+# Copyright 2017 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 provides common configuration information for building
+# chromium-app-shell for various platforms.
+
+# Base name of the package.
+PACKAGE="chromium-app-shell"
+
+# Filename of the main executable (for generating launcher scripts, etc.)
+PROGNAME=app_shell
+
+# Base directory for package installation.
+INSTALLDIR=/opt/chromium.org/app-shell
+
+# Display string for desktop menu/icon.
+MENUNAME="Chromium App Shell"
+
+# Brief package description.
+SHORTDESC="The app shell from Chromium.org"
+
+# Detailed package description.
+FULLDESC="The app shell from Chromium.org"
+
+# Package maintainer information.
+# TODO(mmoss) Setup a mailbox for this address
+MAINTNAME="Chromium Linux Team"
+MAINTMAIL="chromium-linux-packager@chromium.org"
+PRODUCTURL="http://www.chromium.org/"
diff --git a/extensions/shell/installer/linux/common/google-app-shell/google-app-shell.info b/extensions/shell/installer/linux/common/google-app-shell/google-app-shell.info
new file mode 100644
index 0000000..4086733
--- /dev/null
+++ b/extensions/shell/installer/linux/common/google-app-shell/google-app-shell.info
@@ -0,0 +1,30 @@
+# Copyright 2017 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 provides common configuration information for building
+# app-shell packages for various platforms.
+
+# Base name of the package.
+PACKAGE="google-app-shell"
+
+# Filename of the main executable (for generating launcher scripts, etc.)
+PROGNAME=app_shell
+
+# Base directory for package installation.
+INSTALLDIR=/opt/google/app-shell
+
+# Display string for desktop menu/icon.
+MENUNAME="App Shell"
+
+# Brief package description.
+SHORTDESC="The app shell from Google"
+
+# Detailed package description.
+FULLDESC="The app shell from Google"
+
+# Package maintainer information.
+# TODO(mmoss) Setup a mailbox for this address
+MAINTNAME="Chrome Linux Team"
+MAINTMAIL="chromium-dev@chromium.org"
+PRODUCTURL="https://chrome.google.com/"
diff --git a/extensions/shell/installer/linux/common/installer.include b/extensions/shell/installer/linux/common/installer.include
new file mode 100644
index 0000000..521916f
--- /dev/null
+++ b/extensions/shell/installer/linux/common/installer.include
@@ -0,0 +1,193 @@
+# TODO(michaelpg): Dedupe common functionality with the Chrome installer.
+
+# Recursively replace @@include@@ template variables with the referenced file,
+# and write the resulting text to stdout.
+process_template_includes() {
+  INCSTACK+="$1->"
+  # Includes are relative to the file that does the include.
+  INCDIR=$(dirname $1)
+  # Clear IFS so 'read' doesn't trim whitespace
+  local OLDIFS="$IFS"
+  IFS=''
+  while read -r LINE
+  do
+    INCLINE=$(sed -e '/^[[:space:]]*@@include@@/!d' <<<$LINE)
+    if [ -n "$INCLINE" ]; then
+      INCFILE=$(echo $INCLINE | sed -e "s#@@include@@\(.*\)#\1#")
+      # Simple filename match to detect cyclic includes.
+      CYCLE=$(sed -e "\#$INCFILE#"'!d' <<<$INCSTACK)
+      if [ "$CYCLE" ]; then
+        echo "ERROR: Possible cyclic include detected." 1>&2
+        echo "$INCSTACK$INCFILE" 1>&2
+        exit 1
+      fi
+      if [ ! -r "$INCDIR/$INCFILE" ]; then
+        echo "ERROR: Couldn't read include file: $INCDIR/$INCFILE" 1>&2
+        exit 1
+      fi
+      process_template_includes "$INCDIR/$INCFILE"
+    else
+      echo "$LINE"
+    fi
+  done < "$1"
+  IFS="$OLDIFS"
+  INCSTACK=${INCSTACK%"$1->"}
+}
+
+# Replace template variables (@@VARNAME@@) in the given template file. If a
+# second argument is given, save the processed text to that filename, otherwise
+# modify the template file in place.
+process_template() (
+  # Don't worry if some of these substitution variables aren't set.
+  # Note that this function is run in a sub-shell so we don't leak this
+  # setting, since we still want unbound variables to be an error elsewhere.
+  set +u
+
+  local TMPLIN="$1"
+  if [ -z "$2" ]; then
+    local TMPLOUT="$TMPLIN"
+  else
+    local TMPLOUT="$2"
+  fi
+  # Process includes first so included text also gets substitutions.
+  TMPLINCL="$(process_template_includes "$TMPLIN")"
+  sed \
+    -e "s#@@PACKAGE@@#${PACKAGE}#g" \
+    -e "s#@@PACKAGE_FILENAME@@#${PACKAGE_FILENAME}#g" \
+    -e "s#@@PROGNAME@@#${PROGNAME}#g" \
+    -e "s#@@CHANNEL@@#${CHANNEL}#g" \
+    -e "s#@@COMPANY_FULLNAME@@#${COMPANY_FULLNAME}#g" \
+    -e "s#@@VERSION@@#${VERSION}#g" \
+    -e "s#@@PACKAGE_RELEASE@@#${PACKAGE_RELEASE}#g" \
+    -e "s#@@VERSIONFULL@@#${VERSIONFULL}#g" \
+    -e "s#@@INSTALLDIR@@#${INSTALLDIR}#g" \
+    -e "s#@@BUILDDIR@@#${BUILDDIR}#g" \
+    -e "s#@@STAGEDIR@@#${STAGEDIR}#g" \
+    -e "s#@@SCRIPTDIR@@#${SCRIPTDIR}#g" \
+    -e "s#@@MENUNAME@@#${MENUNAME}#g" \
+    -e "s#@@PRODUCTURL@@#${PRODUCTURL}#g" \
+    -e "s#@@PREDEPENDS@@#${PREDEPENDS}#g" \
+    -e "s#@@DEPENDS@@#${DEPENDS}#g" \
+    -e "s#@@PROVIDES@@#${PROVIDES}#g" \
+    -e "s#@@REPLACES@@#${REPLACES}#g" \
+    -e "s#@@CONFLICTS@@#${CONFLICTS}#g" \
+    -e "s#@@ARCHITECTURE@@#${ARCHITECTURE}#g" \
+    -e "s#@@MAINTNAME@@#${MAINTNAME}#g" \
+    -e "s#@@MAINTMAIL@@#${MAINTMAIL}#g" \
+    -e "s#@@REPOCONFIG@@#${REPOCONFIG}#g" \
+    -e "s#@@REPOCONFIGREGEX@@#${REPOCONFIGREGEX}#g" \
+    -e "s#@@SHORTDESC@@#${SHORTDESC}#g" \
+    -e "s#@@FULLDESC@@#${FULLDESC}#g" \
+    -e "s#@@USR_BIN_SYMLINK_NAME@@#${USR_BIN_SYMLINK_NAME:-}#g" \
+    > "$TMPLOUT" <<< "$TMPLINCL"
+)
+
+# Setup the installation directory hierachy in the package staging area.
+prep_staging_common() {
+  install -m 755 -d "${STAGEDIR}/${INSTALLDIR}" \
+    "${STAGEDIR}/usr/bin"
+}
+
+get_version_info() {
+  source "${BUILDDIR}/app_shell_installer/version.txt"
+  VERSION="${MAJOR}.${MINOR}.${BUILD}.${PATCH}"
+  # TODO(phajdan.jr): Provide a mechanism to pass a different package
+  # release number if needed. The meaning of it is to bump it for
+  # packaging-only changes while the underlying software has the same version.
+  # This corresponds to the Release field in RPM spec files and debian_revision
+  # component of the Version field for DEB control file.
+  # Generally with Chrome's fast release cycle it'd be more hassle to try
+  # to bump this number between releases.
+  PACKAGE_RELEASE="1"
+}
+
+stage_install_common() {
+  echo "Staging common install files in '${STAGEDIR}'..."
+
+  # TODO(mmoss) This assumes we built the static binaries. To support shared
+  # builds, we probably want an install target in scons so it can give us all
+  # the right files. See also:
+  # http://code.google.com/p/chromium/issues/detail?id=4451
+  #
+  # app
+  # We need to add the debug link so gdb knows to look for the symbols.
+  DEBUGFILE="${BUILDDIR}/${PROGNAME}.debug"
+  STRIPPEDFILE="${BUILDDIR}/${PROGNAME}.stripped"
+  "${BUILDDIR}/app_shell_installer/common/eu-strip" -o "${STRIPPEDFILE}" -f "${DEBUGFILE}" "${BUILDDIR}/${PROGNAME}"
+  install -m 755 "${STRIPPEDFILE}" "${STAGEDIR}/${INSTALLDIR}/${PROGNAME}"
+  rm "${DEBUGFILE}" "${STRIPPEDFILE}"
+
+  # resources
+  install -m 644 \
+    "${BUILDDIR}/extensions_shell_and_test.pak" \
+    "${STAGEDIR}/${INSTALLDIR}/"
+
+
+  # ICU data file; only necessary when icu_use_data_file_flag is set to 1
+  # in build/common.gypi.
+  install -m 644 "${BUILDDIR}/icudtl.dat" "${STAGEDIR}/${INSTALLDIR}/"
+
+  # V8 snapshot files; only necessary when v8_use_external_startup_data is
+  # set to 1 in build/common.gypi.
+  if [ -f "${BUILDDIR}/natives_blob.bin" ]; then
+    install -m 644 "${BUILDDIR}/natives_blob.bin" "${STAGEDIR}/${INSTALLDIR}/"
+    install -m 644 "${BUILDDIR}/snapshot_blob.bin" "${STAGEDIR}/${INSTALLDIR}/"
+  fi
+
+  # ANGLE
+  if [ "${CHANNEL}" != "stable" ]; then
+    install -m 644 "${BUILDDIR}/libGLESv2.so" "${STAGEDIR}/${INSTALLDIR}/"
+    install -m 644 "${BUILDDIR}/libEGL.so" "${STAGEDIR}/${INSTALLDIR}/"
+  fi
+
+  # SwiftShader
+  if [ -f "${BUILDDIR}/swiftshader/libEGL.so" ]; then
+    install -m 755 -d "${STAGEDIR}/${INSTALLDIR}/swiftshader/"
+    install -m 644 "${BUILDDIR}/swiftshader/libEGL.so" "${STAGEDIR}/${INSTALLDIR}/swiftshader/"
+    install -m 644 "${BUILDDIR}/swiftshader/libGLESv2.so" "${STAGEDIR}/${INSTALLDIR}/swiftshader/"
+  fi
+
+  # libc++
+  if [ -f "${BUILDDIR}/lib/libc++.so" ]; then
+    install -m 755 -d "${STAGEDIR}/${INSTALLDIR}/lib/"
+
+    install -m 644 -s "${BUILDDIR}/lib/libc++.so" "${STAGEDIR}/${INSTALLDIR}/lib/"
+  fi
+
+
+  # nacl_helper and nacl_helper_bootstrap
+  # Don't use "-s" (strip) because this runs binutils "strip", which
+  # mangles the special ELF program headers of nacl_helper_bootstrap.
+  # Explicitly use eu-strip instead, because it doesn't have that problem.
+  for file in nacl_helper nacl_helper_bootstrap; do
+    buildfile="${BUILDDIR}/${file}"
+    if [ -f "${buildfile}" ]; then
+      strippedfile="${buildfile}.stripped"
+      debugfile="${buildfile}.debug"
+      "${BUILDDIR}/app_shell_installer/common/eu-strip" -o "${strippedfile}" -f "${debugfile}" "${buildfile}"
+      install -m 755 "${strippedfile}" "${STAGEDIR}/${INSTALLDIR}/${file}"
+    fi
+  done
+  # Don't use "-s" (strip) because this would use the Linux toolchain to
+  # strip the NaCl binary, which has the potential to break it.  It
+  # certainly resets the OSABI and ABIVERSION fields to non-NaCl values,
+  # although the NaCl IRT loader doesn't care about these fields.  In any
+  # case, the IRT binaries are already stripped by NaCl's build process.
+  for filename in ${BUILDDIR}/nacl_irt_*.nexe; do
+    # Re-check the filename in case globbing matched nothing.
+    if [ -f "$filename" ]; then
+      install -m 644 "$filename" "${STAGEDIR}/${INSTALLDIR}/`basename "$filename"`"
+    fi
+  done
+
+  # launcher script and symlink
+  process_template "${BUILDDIR}/app_shell_installer/common/wrapper" \
+    "${STAGEDIR}/${INSTALLDIR}/${PACKAGE}"
+  chmod 755 "${STAGEDIR}/${INSTALLDIR}/${PACKAGE}"
+  if [ ! -f "${STAGEDIR}/${INSTALLDIR}/app-shell" ]; then
+    ln -sn "${INSTALLDIR}/${PACKAGE}" \
+      "${STAGEDIR}/${INSTALLDIR}/app-shell"
+  fi
+  ln -snf "${INSTALLDIR}/${PACKAGE}" \
+    "${STAGEDIR}/usr/bin/${USR_BIN_SYMLINK_NAME}"
+}
diff --git a/extensions/shell/installer/linux/common/wrapper b/extensions/shell/installer/linux/common/wrapper
new file mode 100755
index 0000000..487e522
--- /dev/null
+++ b/extensions/shell/installer/linux/common/wrapper
@@ -0,0 +1,32 @@
+#!/bin/bash
+#
+# Copyright 2017 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.
+
+# Let the wrapped binary know that it has been run through the wrapper.
+export APP_SHELL_WRAPPER="`readlink -f "$0"`"
+
+HERE="`dirname "$APP_SHELL_WRAPPER"`"
+
+# Always use our versions of ffmpeg libs.
+if [[ -n "$LD_LIBRARY_PATH" ]]; then
+  LD_LIBRARY_PATH="$HERE:$HERE/lib:$LD_LIBRARY_PATH"
+else
+  LD_LIBRARY_PATH="$HERE:$HERE/lib"
+fi
+export LD_LIBRARY_PATH
+
+export CHROME_VERSION_EXTRA="@@CHANNEL@@"
+
+# We don't want bug-buddy intercepting our crashes. http://crbug.com/24120
+export GNOME_DISABLE_CRASH_DIALOG=SET_BY_GOOGLE_CHROME
+
+# Sanitize std{in,out,err} because they'll be shared with untrusted child
+# processes (http://crbug.com/376567).
+exec < /dev/null
+exec > >(exec cat)
+exec 2> >(exec cat >&2)
+
+# Note: exec -a below is a bashism.
+exec -a "$0" "$HERE/@@PROGNAME@@" "$@"
diff --git a/extensions/shell/installer/linux/debian/build.sh b/extensions/shell/installer/linux/debian/build.sh
new file mode 100755
index 0000000..331d9ad4
--- /dev/null
+++ b/extensions/shell/installer/linux/debian/build.sh
@@ -0,0 +1,351 @@
+#!/bin/bash
+#
+# Copyright 2017 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.
+
+# TODO(michaelpg): Dedupe common functionality with the Chrome installer.
+
+# TODO(mmoss) This currently only works with official builds, since non-official
+# builds don't add the "${BUILDDIR}/app_shell_installer/" files needed for
+# packaging.
+
+set -e
+set -o pipefail
+if [ "$VERBOSE" ]; then
+  set -x
+fi
+set -u
+
+# Create the Debian changelog file needed by dpkg-gencontrol. This just adds a
+# placeholder change, indicating it is the result of an automatic build.
+# TODO(mmoss) Release packages should create something meaningful for a
+# changelog, but simply grabbing the actual 'svn log' is way too verbose. Do we
+# have any type of "significant/visible changes" log that we could use for this?
+gen_changelog() {
+  rm -f "${DEB_CHANGELOG}"
+  process_template "${SCRIPTDIR}/changelog.template" "${DEB_CHANGELOG}"
+  debchange -a --nomultimaint -m --changelog "${DEB_CHANGELOG}" \
+    "Release Notes: ${RELEASENOTES}"
+  GZLOG="${STAGEDIR}/usr/share/doc/${PACKAGE}-${CHANNEL}/changelog.gz"
+  mkdir -p "$(dirname "${GZLOG}")"
+  gzip -9 -c "${DEB_CHANGELOG}" > "${GZLOG}"
+  chmod 644 "${GZLOG}"
+}
+
+# Create the Debian control file needed by dpkg-deb.
+gen_control() {
+  dpkg-gencontrol -v"${VERSIONFULL}" -c"${DEB_CONTROL}" -l"${DEB_CHANGELOG}" \
+  -f"${DEB_FILES}" -p"${PACKAGE}-${CHANNEL}" -P"${STAGEDIR}" \
+  -O > "${STAGEDIR}/DEBIAN/control"
+  rm -f "${DEB_CONTROL}"
+}
+
+# Setup the installation directory hierachy in the package staging area.
+prep_staging_debian() {
+  prep_staging_common
+  install -m 755 -d "${STAGEDIR}/DEBIAN" \
+    "${STAGEDIR}/etc/cron.daily" \
+    "${STAGEDIR}/usr/share/doc/${USR_BIN_SYMLINK_NAME}"
+}
+
+# Put the package contents in the staging area.
+stage_install_debian() {
+  # Always use a different name for /usr/bin symlink depending on channel to
+  # avoid file collisions.
+  local USR_BIN_SYMLINK_NAME="${PACKAGE}-${CHANNEL}"
+
+  if [ "$CHANNEL" != "stable" ]; then
+    # Avoid file collisions between channels.
+    local INSTALLDIR="${INSTALLDIR}-${CHANNEL}"
+
+    local PACKAGE="${PACKAGE}-${CHANNEL}"
+  fi
+  prep_staging_debian
+  stage_install_common
+  echo "Staging Debian install files in '${STAGEDIR}'..."
+  install -m 755 -d "${STAGEDIR}/${INSTALLDIR}/cron"
+  process_template "${BUILDDIR}/app_shell_installer/common/repo.cron" \
+      "${STAGEDIR}/${INSTALLDIR}/cron/${PACKAGE}"
+  chmod 755 "${STAGEDIR}/${INSTALLDIR}/cron/${PACKAGE}"
+  pushd "${STAGEDIR}/etc/cron.daily/"
+  ln -snf "${INSTALLDIR}/cron/${PACKAGE}" "${PACKAGE}"
+  popd
+  process_template "${BUILDDIR}/app_shell_installer/debian/postinst" \
+    "${STAGEDIR}/DEBIAN/postinst"
+  chmod 755 "${STAGEDIR}/DEBIAN/postinst"
+  process_template "${BUILDDIR}/app_shell_installer/debian/postrm" \
+    "${STAGEDIR}/DEBIAN/postrm"
+  chmod 755 "${STAGEDIR}/DEBIAN/postrm"
+}
+
+# Actually generate the package file.
+do_package() {
+  echo "Packaging ${ARCHITECTURE}..."
+  PREDEPENDS="$COMMON_PREDEPS"
+  DEPENDS="${COMMON_DEPS}"
+  REPLACES=""
+  CONFLICTS=""
+  PROVIDES=""
+  gen_changelog
+  process_template "${SCRIPTDIR}/control.template" "${DEB_CONTROL}"
+  export DEB_HOST_ARCH="${ARCHITECTURE}"
+  if [ -f "${DEB_CONTROL}" ]; then
+    gen_control
+  fi
+  fakeroot dpkg-deb -Zxz -z9 -b "${STAGEDIR}" .
+}
+
+verify_package() {
+  DEPENDS="${COMMON_DEPS}"  # This needs to match do_package() above.
+  echo ${DEPENDS} | sed 's/, /\n/g' | LANG=C sort > expected_deb_depends
+  dpkg -I "${PACKAGE}-${CHANNEL}_${VERSIONFULL}_${ARCHITECTURE}.deb" | \
+      grep '^ Depends: ' | sed 's/^ Depends: //' | sed 's/, /\n/g' | \
+      LANG=C sort > actual_deb_depends
+  BAD_DIFF=0
+  diff -u expected_deb_depends actual_deb_depends || BAD_DIFF=1
+  if [ $BAD_DIFF -ne 0 ] && [ -z "${IGNORE_DEPS_CHANGES:-}" ]; then
+    echo
+    echo "ERROR: bad dpkg dependencies!"
+    echo
+    exit $BAD_DIFF
+  fi
+}
+
+# Remove temporary files and unwanted packaging output.
+cleanup() {
+  echo "Cleaning..."
+  rm -rf "${STAGEDIR}"
+  rm -rf "${TMPFILEDIR}"
+}
+
+usage() {
+  echo "usage: $(basename $0) [-c channel] [-a target_arch] [-o 'dir'] "
+  echo "                      [-b 'dir'] -d branding"
+  echo "-c channel the package channel (trunk, asan, unstable, beta, stable)"
+  echo "-a arch    package architecture (ia32 or x64)"
+  echo "-o dir     package output directory [${OUTPUTDIR}]"
+  echo "-b dir     build input directory    [${BUILDDIR}]"
+  echo "-d brand   either chromium or google_chrome"
+  echo "-s dir     /path/to/sysroot"
+  echo "-h         this help message"
+}
+
+# Check that the channel name is one of the allowable ones.
+verify_channel() {
+  case $CHANNEL in
+    stable )
+      CHANNEL=stable
+      RELEASENOTES="http://googlechromereleases.blogspot.com/search/label/Stable%20updates"
+      ;;
+    unstable|dev|alpha )
+      CHANNEL=unstable
+      RELEASENOTES="http://googlechromereleases.blogspot.com/search/label/Dev%20updates"
+      ;;
+    testing|beta )
+      CHANNEL=beta
+      RELEASENOTES="http://googlechromereleases.blogspot.com/search/label/Beta%20updates"
+      ;;
+    trunk|asan )
+      # Setting this to empty will prevent it from updating any existing configs
+      # from release packages.
+      REPOCONFIG=""
+      RELEASENOTES="http://googlechromereleases.blogspot.com/"
+      ;;
+    * )
+      echo
+      echo "ERROR: '$CHANNEL' is not a valid channel type."
+      echo
+      exit 1
+      ;;
+  esac
+}
+
+process_opts() {
+  while getopts ":s:o:b:c:a:d:h" OPTNAME
+  do
+    case $OPTNAME in
+      o )
+        OUTPUTDIR=$(readlink -f "${OPTARG}")
+        mkdir -p "${OUTPUTDIR}"
+        ;;
+      b )
+        BUILDDIR=$(readlink -f "${OPTARG}")
+        ;;
+      c )
+        CHANNEL="$OPTARG"
+        ;;
+      a )
+        TARGETARCH="$OPTARG"
+        ;;
+      d )
+        BRANDING="$OPTARG"
+        ;;
+      s )
+        SYSROOT="$OPTARG"
+        ;;
+      h )
+        usage
+        exit 0
+        ;;
+      \: )
+        echo "'-$OPTARG' needs an argument."
+        usage
+        exit 1
+        ;;
+      * )
+        echo "invalid command-line option: $OPTARG"
+        usage
+        exit 1
+        ;;
+    esac
+  done
+}
+
+#=========
+# MAIN
+#=========
+
+SCRIPTDIR=$(readlink -f "$(dirname "$0")")
+OUTPUTDIR="${PWD}"
+STAGEDIR=$(mktemp -d -t deb.build.XXXXXX) || exit 1
+TMPFILEDIR=$(mktemp -d -t deb.tmp.XXXXXX) || exit 1
+DEB_CHANGELOG="${TMPFILEDIR}/changelog"
+DEB_FILES="${TMPFILEDIR}/files"
+DEB_CONTROL="${TMPFILEDIR}/control"
+CHANNEL="trunk"
+# Default target architecture to same as build host.
+if [ "$(uname -m)" = "x86_64" ]; then
+  TARGETARCH="x64"
+else
+  TARGETARCH="ia32"
+fi
+
+# call cleanup() on exit
+trap cleanup 0
+process_opts "$@"
+BUILDDIR=${BUILDDIR:=$(readlink -f "${SCRIPTDIR}/../../../../out/Release")}
+
+if [[ "$(basename ${SYSROOT})" = "debian_jessie_"*"-sysroot" ]]; then
+  TARGET_DISTRO="jessie"
+else
+  echo "Debian package can only be built using the jessie sysroot."
+  exit 1
+fi
+
+source ${BUILDDIR}/app_shell_installer/common/installer.include
+
+get_version_info
+VERSIONFULL="${VERSION}-${PACKAGE_RELEASE}"
+
+if [ "$BRANDING" = "google_chrome" ]; then
+  source "${BUILDDIR}/app_shell_installer/common/google-app-shell.info"
+else
+  source "${BUILDDIR}/app_shell_installer/common/chromium-app-shell.info"
+fi
+eval $(sed -e "s/^\([^=]\+\)=\(.*\)$/export \1='\2'/" \
+  "${BUILDDIR}/app_shell_installer/theme/BRANDING")
+
+verify_channel
+
+# Some Debian packaging tools want these set.
+export DEBFULLNAME="${MAINTNAME}"
+export DEBEMAIL="${MAINTMAIL}"
+
+# We'd like to eliminate more of these deps by relying on the 'lsb' package, but
+# that brings in tons of unnecessary stuff, like an mta and rpm. Until that full
+# 'lsb' package is installed by default on DEB distros, we'll have to stick with
+# the LSB sub-packages, to avoid pulling in all that stuff that's not installed
+# by default.
+
+# Generate the dependencies,
+# TODO(mmoss): This is a workaround for a problem where dpkg-shlibdeps was
+# resolving deps using some of our build output shlibs (i.e.
+# out/Release/lib.target/libfreetype.so.6), and was then failing with:
+#   dpkg-shlibdeps: error: no dependency information found for ...
+# It's not clear if we ever want to look in LD_LIBRARY_PATH to resolve deps,
+# but it seems that we don't currently, so this is the most expediant fix.
+SAVE_LDLP=${LD_LIBRARY_PATH:-}
+unset LD_LIBRARY_PATH
+if [ ${TARGETARCH} = "x64" ]; then
+  SHLIB_ARGS="-l${SYSROOT}/usr/lib/x86_64-linux-gnu"
+  SHLIB_ARGS="${SHLIB_ARGS} -l${SYSROOT}/lib/x86_64-linux-gnu"
+else
+  SHLIB_ARGS="-l${SYSROOT}/usr/lib/i386-linux-gnu"
+  SHLIB_ARGS="${SHLIB_ARGS} -l${SYSROOT}/lib/i386-linux-gnu"
+fi
+SHLIB_ARGS="${SHLIB_ARGS} -l${SYSROOT}/usr/lib"
+DPKG_SHLIB_DEPS=$(cd ${SYSROOT} && dpkg-shlibdeps ${SHLIB_ARGS:-} -O \
+                  -e"$BUILDDIR/app_shell" | sed 's/^shlibs:Depends=//')
+if [ -n "$SAVE_LDLP" ]; then
+  LD_LIBRARY_PATH=$SAVE_LDLP
+fi
+
+# Format it nicely and save it for comparison.
+echo "$DPKG_SHLIB_DEPS" | sed 's/, /\n/g' | LANG=C sort > actual
+
+# Compare the expected dependency list to the generated list.
+BAD_DIFF=0
+diff -u "$SCRIPTDIR/expected_deps_${TARGETARCH}_${TARGET_DISTRO}" actual || \
+  BAD_DIFF=1
+if [ $BAD_DIFF -ne 0 ] && [ -z "${IGNORE_DEPS_CHANGES:-}" ]; then
+  echo
+  echo "ERROR: Shared library dependencies changed!"
+  echo "If this is intentional, please update:"
+  echo "extensions/shell/installer/linux/debian/expected_deps_*"
+  echo
+  exit $BAD_DIFF
+fi
+
+# Additional dependencies not in the dpkg-shlibdeps output.
+# ca-certificates: Make sure users have SSL certificates.
+# libnss3: Pull a more recent version of NSS than required by runtime linking,
+#          for security and stability updates in NSS.
+# lsb-release: For lsb-release.
+# wget: For uploading crash reports with Breakpad.
+ADDITIONAL_DEPS="ca-certificates, libnss3 (>= 3.26), lsb-release, wget"
+
+# Fix-up libnspr dependency due to renaming in Ubuntu (the old package still
+# exists, but it was moved to "universe" repository, which isn't installed by
+# default).
+DPKG_SHLIB_DEPS=$(sed \
+    's/\(libnspr4-0d ([^)]*)\), /\1 | libnspr4 (>= 4.9.5-0ubuntu0), /g' \
+    <<< $DPKG_SHLIB_DEPS)
+
+# Remove libnss dependency so the one in $ADDITIONAL_DEPS can supercede it.
+DPKG_SHLIB_DEPS=$(sed 's/\(libnss3 ([^)]*)\), //g' <<< $DPKG_SHLIB_DEPS)
+
+COMMON_DEPS="${DPKG_SHLIB_DEPS}, ${ADDITIONAL_DEPS}"
+COMMON_PREDEPS="dpkg (>= 1.14.0)"
+
+
+# Make everything happen in the OUTPUTDIR.
+cd "${OUTPUTDIR}"
+
+case "$TARGETARCH" in
+  ia32 )
+    export ARCHITECTURE="i386"
+    ;;
+  x64 )
+    export ARCHITECTURE="amd64"
+    ;;
+  * )
+    echo
+    echo "ERROR: Don't know how to build DEBs for '$TARGETARCH'."
+    echo
+    exit 1
+    ;;
+esac
+# TODO(michaelpg): Get a working repo URL.
+BASEREPOCONFIG="dl.google.com/linux/app-shell/deb/ stable main"
+# Only use the default REPOCONFIG if it's unset (e.g. verify_channel might have
+# set it to an empty string)
+REPOCONFIG="${REPOCONFIG-deb [arch=${ARCHITECTURE}] http://${BASEREPOCONFIG}}"
+# Allowed configs include optional HTTPS support and explicit multiarch
+# platforms.
+REPOCONFIGREGEX="deb (\\\\[arch=[^]]*\\\\b${ARCHITECTURE}\\\\b[^]]*\\\\]"
+REPOCONFIGREGEX+="[[:space:]]*) https?://${BASEREPOCONFIG}"
+stage_install_debian
+
+do_package
+verify_package
diff --git a/extensions/shell/installer/linux/debian/expected_deps_x64_jessie b/extensions/shell/installer/linux/debian/expected_deps_x64_jessie
new file mode 100644
index 0000000..5fc6eff
--- /dev/null
+++ b/extensions/shell/installer/linux/debian/expected_deps_x64_jessie
@@ -0,0 +1,28 @@
+gconf-service
+libasound2 (>= 1.0.16)
+libatk1.0-0 (>= 1.12.4)
+libc6 (>= 2.15)
+libdbus-1-3 (>= 1.1.4)
+libexpat1 (>= 2.0.1)
+libfontconfig1 (>= 2.11)
+libgcc1 (>= 1:4.1.1)
+libgconf-2-4 (>= 3.2.5)
+libglib2.0-0 (>= 2.14.0)
+libnspr4 (>= 2:4.9-2~)
+libnss3 (>= 2:3.13.4-2~)
+libpango-1.0-0 (>= 1.14.0)
+libpangocairo-1.0-0 (>= 1.14.0)
+libstdc++6 (>= 4.8.1)
+libx11-6 (>= 2:1.4.99.1)
+libx11-xcb1
+libxcb1 (>= 1.6)
+libxcomposite1 (>= 1:0.3-1)
+libxcursor1 (>> 1.1.2)
+libxdamage1 (>= 1:1.1)
+libxext6
+libxfixes3
+libxi6 (>= 2:1.2.99.4)
+libxrandr2
+libxrender1
+libxss1
+libxtst6
diff --git a/extensions/shell/installer/linux/debian/postinst b/extensions/shell/installer/linux/debian/postinst
new file mode 100755
index 0000000..68aa893
--- /dev/null
+++ b/extensions/shell/installer/linux/debian/postinst
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright 2017 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.
+
+set -e
+
+@@include@@../common/apt.include
+
+@@include@@../common/symlinks.include
+
+remove_udev_symlinks
+
+## MAIN ##
+if [ ! -e "$DEFAULTS_FILE" ]; then
+  echo 'repo_add_once="true"' > "$DEFAULTS_FILE"
+  echo 'repo_reenable_on_distupgrade="true"' >> "$DEFAULTS_FILE"
+fi
+
+# Run the cron job immediately to perform repository configuration.
+nohup sh /etc/cron.daily/@@PACKAGE@@ > /dev/null 2>&1 &
diff --git a/extensions/shell/installer/linux/debian/postrm b/extensions/shell/installer/linux/debian/postrm
new file mode 100755
index 0000000..6d369e7
--- /dev/null
+++ b/extensions/shell/installer/linux/debian/postrm
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# Copyright 2017 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.
+
+set -e
+
+action="$1"
+
+# Only do complete clean-up on purge.
+if [ "$action" != "purge" ] ; then
+  exit 0
+fi
+
+@@include@@../common/apt.include
+
+@@include@@../common/symlinks.include
+
+remove_udev_symlinks
+
+# Only remove the defaults file if it is not empty. An empty file was probably
+# put there by the sysadmin to disable automatic repository configuration, as
+# per the instructions on the package download page.
+if [ -s "$DEFAULTS_FILE" ]; then
+  # Make sure the package defaults are removed before the repository config,
+  # otherwise it could result in the repository config being removed, but the
+  # package defaults remain and are set to not recreate the repository config.
+  # In that case, future installs won't recreate it and won't get auto-updated.
+  rm "$DEFAULTS_FILE" || exit 1
+fi
+# Remove any Google repository added by the package.
+clean_sources_lists
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index e7e1255..663fe51 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -1823,6 +1823,7 @@
 // both browser state and tab model are valid.
 - (void)addUIFunctionalityForModelAndBrowserState {
   DCHECK(_browserState);
+  DCHECK(_toolbarModelIOS);
   DCHECK(_model);
   DCHECK([self isViewLoaded]);
 
@@ -1852,6 +1853,7 @@
     _paymentRequestManager = [[PaymentRequestManager alloc]
         initWithBaseViewController:self
                       browserState:_browserState];
+    [_paymentRequestManager setToolbarModel:_toolbarModelIOS.get()];
     [_paymentRequestManager setWebState:[_model currentTab].webState];
   }
 }
diff --git a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
index b1049d4..0ed8f1b7 100644
--- a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
+++ b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
@@ -479,12 +479,18 @@
 #pragma mark - Pan gesture recognizer handling
 
 - (void)panGesture:(UIPanGestureRecognizer*)gesture {
-  if (gesture.state == UIGestureRecognizerStateBegan) {
-    [self setWebViewInteractionEnabled:NO];
-  } else if (gesture.state == UIGestureRecognizerStateEnded ||
-             gesture.state == UIGestureRecognizerStateCancelled) {
+  if (gesture.state == UIGestureRecognizerStateEnded ||
+      gesture.state == UIGestureRecognizerStateCancelled) {
     [self setWebViewInteractionEnabled:YES];
   }
+  if (self.overscrollState == OverscrollState::NO_PULL_STARTED) {
+    return;
+  }
+
+  if (gesture.state == UIGestureRecognizerStateBegan) {
+    [self setWebViewInteractionEnabled:NO];
+  }
+
   const CGPoint panPointScreen = [gesture locationInView:nil];
   if (self.overscrollState == OverscrollState::ACTION_READY) {
     const CGFloat direction = UseRTLLayout() ? -1 : 1;
diff --git a/ios/chrome/browser/ui/payments/BUILD.gn b/ios/chrome/browser/ui/payments/BUILD.gn
index 12c1714..6ee8b40 100644
--- a/ios/chrome/browser/ui/payments/BUILD.gn
+++ b/ios/chrome/browser/ui/payments/BUILD.gn
@@ -15,6 +15,10 @@
     "billing_address_selection_coordinator.mm",
     "billing_address_selection_mediator.h",
     "billing_address_selection_mediator.mm",
+    "contact_info_edit_coordinator.h",
+    "contact_info_edit_coordinator.mm",
+    "contact_info_edit_mediator.h",
+    "contact_info_edit_mediator.mm",
     "contact_info_selection_coordinator.h",
     "contact_info_selection_coordinator.mm",
     "contact_info_selection_mediator.h",
@@ -81,6 +85,7 @@
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/icons",
     "//ios/chrome/browser/ui/payments/cells",
+    "//ios/chrome/browser/ui/toolbar",
     "//ios/third_party/material_components_ios",
     "//ios/third_party/material_roboto_font_loader_ios",
     "//ios/web",
@@ -146,6 +151,8 @@
     "address_edit_coordinator_unittest.mm",
     "billing_address_selection_coordinator_unittest.mm",
     "billing_address_selection_mediator_unittest.mm",
+    "contact_info_edit_coordinator_unittest.mm",
+    "contact_info_edit_mediator_unittest.mm",
     "contact_info_selection_coordinator_unittest.mm",
     "contact_info_selection_mediator_unittest.mm",
     "country_selection_coordinator_unittest.mm",
@@ -182,6 +189,7 @@
     "//ios/chrome/browser/payments:test_support",
     "//ios/chrome/browser/signin",
     "//ios/chrome/browser/signin:test_support",
+    "//ios/chrome/browser/ui/autofill",
     "//ios/chrome/browser/ui/autofill:autofill_ui",
     "//ios/chrome/browser/ui/autofill/cells",
     "//ios/chrome/browser/ui/collection_view:test_support",
diff --git a/ios/chrome/browser/ui/payments/cells/page_info_item.mm b/ios/chrome/browser/ui/payments/cells/page_info_item.mm
index 1364f12..18c7165 100644
--- a/ios/chrome/browser/ui/payments/cells/page_info_item.mm
+++ b/ios/chrome/browser/ui/payments/cells/page_info_item.mm
@@ -127,12 +127,18 @@
     _pageHostLabel = [[UILabel alloc] initWithFrame:CGRectZero];
     _pageHostLabel.font = [[MDCTypography fontLoader] regularFontOfSize:12];
     _pageHostLabel.textColor = [[MDCPalette greyPalette] tint600];
-    // Allow the label to break to multiple lines. This should be very rare but
-    // will prevent malicious domains from suppling very long host names and
-    // having the domain name truncated.
-    _pageHostLabel.numberOfLines = 0;
+    // Truncate host name from the leading side if it is too long. This is
+    // according to Eliding Origin Names and Hostnames guideline found here:
+    // https://www.chromium.org/Home/chromium-security/enamel#TOC-Presenting-Origins
+    _pageHostLabel.lineBreakMode = NSLineBreakByTruncatingHead;
     _pageHostLabel.backgroundColor = [UIColor clearColor];
     _pageHostLabel.translatesAutoresizingMaskIntoConstraints = NO;
+    // Prevents host label from bleeding into lock indicator view when host text
+    // is very long.
+    [_pageHostLabel
+        setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
+                                        forAxis:
+                                            UILayoutConstraintAxisHorizontal];
     [self.contentView addSubview:_pageHostLabel];
 
     // Lock indicator
@@ -171,7 +177,8 @@
           constraintLessThanOrEqualToAnchor:self.contentView.trailingAnchor
                                    constant:-kHorizontalPadding],
       [_pageHostLabel.trailingAnchor
-          constraintEqualToAnchor:_pageTitleLabel.trailingAnchor],
+          constraintLessThanOrEqualToAnchor:self.contentView.trailingAnchor
+                                   constant:-kHorizontalPadding],
 
       // UILabel leaves some empty space above the height of capital letters. In
       // order to align the tops of the letters with the top of the favicon,
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.h b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.h
new file mode 100644
index 0000000..b9fb1382
--- /dev/null
+++ b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.h
@@ -0,0 +1,58 @@
+// Copyright 2017 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 IOS_CHROME_BROWSER_UI_PAYMENTS_CONTACT_INFO_EDIT_COORDINATOR_H_
+#define IOS_CHROME_BROWSER_UI_PAYMENTS_CONTACT_INFO_EDIT_COORDINATOR_H_
+
+#import "ios/chrome/browser/chrome_coordinator.h"
+#import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h"
+
+namespace autofill {
+class AutofillProfile;
+}  // namespace autofill
+
+class PaymentRequest;
+
+@class ContactInfoEditCoordinator;
+
+// Delegate protocol for ContactInfoEditCoordinator.
+@protocol ContactInfoEditCoordinatorDelegate<NSObject>
+
+// Notifies the delegate that the user has finished editing or creating
+// |profile|. |profile| will be a new autofill profile instance owned by the
+// PaymentRequest object if none was provided to the coordinator. Otherwise, it
+// will be the same edited instance.
+- (void)contactInfoEditCoordinator:(ContactInfoEditCoordinator*)coordinator
+           didFinishEditingProfile:(autofill::AutofillProfile*)profile;
+
+// Notifies the delegate that the user has chosen to cancel editing or creating
+// a profile and return to the previous screen.
+- (void)contactInfoEditCoordinatorDidCancel:
+    (ContactInfoEditCoordinator*)coordinator;
+
+@end
+
+// Coordinator responsible for creating and presenting a profile editor view
+// controller. This view controller will be presented by the view controller
+// provided in the initializer.
+@interface ContactInfoEditCoordinator
+    : ChromeCoordinator<PaymentRequestEditViewControllerDelegate,
+                        PaymentRequestEditViewControllerValidator>
+
+// The profile to be edited, if any. This pointer is not owned by this class
+// and should outlive it.
+@property(nonatomic, assign) autofill::AutofillProfile* profile;
+
+// The PaymentRequest object owning an instance of web::PaymentRequest as
+// provided by the page invoking the Payment Request API. This pointer is not
+// owned by this class and should outlive it.
+@property(nonatomic, assign) PaymentRequest* paymentRequest;
+
+// The delegate to be notified when the user returns or finishes creating or
+// editing a profile.
+@property(nonatomic, weak) id<ContactInfoEditCoordinatorDelegate> delegate;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_PAYMENTS_CONTACT_INFO_EDIT_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm
new file mode 100644
index 0000000..6624c4c
--- /dev/null
+++ b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm
@@ -0,0 +1,156 @@
+// Copyright 2017 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 "ios/chrome/browser/ui/payments/contact_info_edit_coordinator.h"
+
+#include "base/guid.h"
+#include "base/logging.h"
+#include "base/strings/sys_string_conversions.h"
+#include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/validation.h"
+#include "components/autofill/core/common/autofill_constants.h"
+#include "components/payments/core/payments_profile_comparator.h"
+#include "components/strings/grit/components_strings.h"
+#include "ios/chrome/browser/application_context.h"
+#include "ios/chrome/browser/payments/payment_request.h"
+#import "ios/chrome/browser/ui/autofill/autofill_ui_type_util.h"
+#import "ios/chrome/browser/ui/payments/contact_info_edit_mediator.h"
+#import "ios/chrome/browser/ui/payments/payment_request_editor_field.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+using ::AutofillTypeFromAutofillUIType;
+}  // namespace
+
+@interface ContactInfoEditCoordinator ()
+
+@property(nonatomic, strong) PaymentRequestEditViewController* viewController;
+
+@property(nonatomic, strong) ContactInfoEditMediator* mediator;
+
+@end
+
+@implementation ContactInfoEditCoordinator
+
+@synthesize profile = _profile;
+@synthesize paymentRequest = _paymentRequest;
+@synthesize delegate = _delegate;
+@synthesize viewController = _viewController;
+@synthesize mediator = _mediator;
+
+- (void)start {
+  self.viewController = [[PaymentRequestEditViewController alloc] init];
+  // TODO(crbug.com/602666): Title varies depending on what field is missing.
+  // e.g., Add Email vs. Add Phone Number.
+  NSString* title =
+      self.profile
+          ? l10n_util::GetNSString(IDS_PAYMENTS_EDIT_CONTACT_DETAILS_LABEL)
+          : l10n_util::GetNSString(IDS_PAYMENTS_ADD_CONTACT_DETAILS_LABEL);
+  [self.viewController setTitle:title];
+  [self.viewController setDelegate:self];
+  [self.viewController setValidatorDelegate:self];
+  self.mediator = [[ContactInfoEditMediator alloc]
+      initWithPaymentRequest:self.paymentRequest
+                     profile:self.profile];
+  [self.mediator setConsumer:self.viewController];
+  [self.viewController setDataSource:self.mediator];
+  [self.viewController loadModel];
+
+  DCHECK(self.baseViewController.navigationController);
+  [[self baseViewController].navigationController
+      pushViewController:self.viewController
+                animated:YES];
+}
+
+- (void)stop {
+  [self.viewController.navigationController popViewControllerAnimated:YES];
+  self.viewController = nil;
+}
+
+#pragma mark - PaymentRequestEditViewControllerValidator
+
+- (NSString*)paymentRequestEditViewController:
+                 (PaymentRequestEditViewController*)controller
+                                validateField:(EditorField*)field {
+  if (field.value.length) {
+    switch (field.autofillUIType) {
+      case AutofillUITypeProfileHomePhoneWholeNumber: {
+        const std::string countryCode =
+            autofill::AutofillCountry::CountryCodeForLocale(
+                GetApplicationContext()->GetApplicationLocale());
+        if (!autofill::IsValidPhoneNumber(base::SysNSStringToUTF16(field.value),
+                                          countryCode)) {
+          return l10n_util::GetNSString(
+              IDS_PAYMENTS_PHONE_INVALID_VALIDATION_MESSAGE);
+        }
+        break;
+      }
+      case AutofillUITypeProfileEmailAddress: {
+        if (!autofill::IsValidEmailAddress(
+                base::SysNSStringToUTF16(field.value))) {
+          return l10n_util::GetNSString(
+              IDS_PAYMENTS_EMAIL_INVALID_VALIDATION_MESSAGE);
+        }
+        break;
+      }
+      default:
+        break;
+    }
+  } else if (field.isRequired) {
+    return l10n_util::GetNSString(
+        IDS_PAYMENTS_FIELD_REQUIRED_VALIDATION_MESSAGE);
+  }
+  return nil;
+}
+
+#pragma mark - PaymentRequestEditViewControllerDelegate
+
+- (void)paymentRequestEditViewController:
+            (PaymentRequestEditViewController*)controller
+                  didFinishEditingFields:(NSArray<EditorField*>*)fields {
+  // Create an empty autofill profile. If a profile is being edited, copy over
+  // the information.
+  autofill::AutofillProfile profile =
+      self.profile ? *self.profile
+                   : autofill::AutofillProfile(base::GenerateGUID(),
+                                               autofill::kSettingsOrigin);
+
+  for (EditorField* field in fields) {
+    profile.SetRawInfo(AutofillTypeFromAutofillUIType(field.autofillUIType),
+                       base::SysNSStringToUTF16(field.value));
+  }
+
+  if (!self.profile) {
+    self.paymentRequest->GetPersonalDataManager()->AddProfile(profile);
+
+    // Add the profile to the list of profiles in |self.paymentRequest|.
+    self.profile = self.paymentRequest->AddAutofillProfile(profile);
+  } else {
+    // Override the origin.
+    profile.set_origin(autofill::kSettingsOrigin);
+    self.paymentRequest->GetPersonalDataManager()->UpdateProfile(profile);
+
+    // Cached profile must be invalidated once the profile is modified.
+    _paymentRequest->profile_comparator()->Invalidate(profile);
+
+    // Update the original profile instance that is being edited.
+    *self.profile = profile;
+  }
+
+  [self.delegate contactInfoEditCoordinator:self
+                    didFinishEditingProfile:self.profile];
+}
+
+- (void)paymentRequestEditViewControllerDidCancel:
+    (PaymentRequestEditViewController*)controller {
+  [self.delegate contactInfoEditCoordinatorDidCancel:self];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator_unittest.mm
new file mode 100644
index 0000000..ee48d85
--- /dev/null
+++ b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator_unittest.mm
@@ -0,0 +1,294 @@
+// Copyright 2017 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 "ios/chrome/browser/ui/payments/contact_info_edit_coordinator.h"
+
+#include "base/logging.h"
+#include "base/mac/foundation_util.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/ios/wait_util.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/browser/test_personal_data_manager.h"
+#include "components/autofill/core/browser/test_region_data_loader.h"
+#include "components/payments/core/payments_profile_comparator.h"
+#include "components/prefs/pref_service.h"
+#include "ios/chrome/browser/application_context.h"
+#include "ios/chrome/browser/payments/payment_request_test_util.h"
+#include "ios/chrome/browser/payments/test_payment_request.h"
+#import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h"
+#import "ios/chrome/browser/ui/payments/payment_request_editor_field.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+#include "third_party/ocmock/OCMock/OCMock.h"
+#include "third_party/ocmock/gtest_support.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+class MockTestPersonalDataManager : public autofill::TestPersonalDataManager {
+ public:
+  MockTestPersonalDataManager() : TestPersonalDataManager() {}
+  MOCK_METHOD1(AddProfile, void(const autofill::AutofillProfile&));
+  MOCK_METHOD1(UpdateProfile, void(const autofill::AutofillProfile&));
+};
+
+class MockPaymentsProfileComparator
+    : public payments::PaymentsProfileComparator {
+ public:
+  MockPaymentsProfileComparator(const std::string& app_locale,
+                                const payments::PaymentOptionsProvider& options)
+      : PaymentsProfileComparator(app_locale, options) {}
+  MOCK_METHOD1(Invalidate, void(const autofill::AutofillProfile&));
+};
+
+class MockTestPaymentRequest : public TestPaymentRequest {
+ public:
+  MockTestPaymentRequest(web::PaymentRequest web_payment_request,
+                         autofill::PersonalDataManager* personal_data_manager)
+      : TestPaymentRequest(web_payment_request, personal_data_manager) {}
+  MOCK_METHOD1(AddAutofillProfile,
+               autofill::AutofillProfile*(const autofill::AutofillProfile&));
+};
+
+MATCHER_P3(ProfileMatches, name, email, phone_number, "") {
+  return arg.GetRawInfo(autofill::NAME_FULL) == base::ASCIIToUTF16(name) &&
+         arg.GetRawInfo(autofill::EMAIL_ADDRESS) == base::ASCIIToUTF16(email) &&
+         arg.GetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER) ==
+             base::ASCIIToUTF16(phone_number);
+}
+
+NSArray<EditorField*>* GetEditorFields() {
+  return @[
+    [[EditorField alloc] initWithAutofillUIType:AutofillUITypeProfileFullName
+                                      fieldType:EditorFieldTypeTextField
+                                          label:@"Name"
+                                          value:@"John Doe"
+                                       required:YES],
+    [[EditorField alloc]
+        initWithAutofillUIType:AutofillUITypeProfileEmailAddress
+                     fieldType:EditorFieldTypeTextField
+                         label:@"Email"
+                         value:@"john@doe.com"
+                      required:YES],
+    [[EditorField alloc]
+        initWithAutofillUIType:AutofillUITypeProfileHomePhoneWholeNumber
+                     fieldType:EditorFieldTypeTextField
+                         label:@"Phone"
+                         value:@"16502111111"
+                      required:YES],
+  ];
+}
+
+using ::testing::_;
+}  // namespace
+
+class PaymentRequestContactInfoEditCoordinatorTest : public PlatformTest {
+ protected:
+  PaymentRequestContactInfoEditCoordinatorTest()
+      : pref_service_(autofill::test::PrefServiceForTesting()) {
+    personal_data_manager_.SetTestingPrefService(pref_service_.get());
+    payment_request_ = base::MakeUnique<MockTestPaymentRequest>(
+        payment_request_test_util::CreateTestWebPaymentRequest(),
+        &personal_data_manager_);
+
+    profile_comparator_ = base::MakeUnique<MockPaymentsProfileComparator>(
+        GetApplicationContext()->GetApplicationLocale(),
+        *payment_request_.get());
+    payment_request_->SetProfileComparator(profile_comparator_.get());
+
+    test_region_data_loader_.set_synchronous_callback(true);
+    payment_request_->SetRegionDataLoader(&test_region_data_loader_);
+  }
+
+  void TearDown() override {
+    personal_data_manager_.SetTestingPrefService(nullptr);
+  }
+
+  std::unique_ptr<PrefService> pref_service_;
+  MockTestPersonalDataManager personal_data_manager_;
+  autofill::TestRegionDataLoader test_region_data_loader_;
+  std::unique_ptr<MockPaymentsProfileComparator> profile_comparator_;
+  std::unique_ptr<MockTestPaymentRequest> payment_request_;
+};
+
+// Tests that invoking start and stop on the coordinator presents and dismisses
+// the contact info edit view controller, respectively.
+TEST_F(PaymentRequestContactInfoEditCoordinatorTest, StartAndStop) {
+  UIViewController* base_view_controller = [[UIViewController alloc] init];
+  UINavigationController* navigation_controller =
+      [[UINavigationController alloc]
+          initWithRootViewController:base_view_controller];
+
+  ContactInfoEditCoordinator* coordinator = [[ContactInfoEditCoordinator alloc]
+      initWithBaseViewController:base_view_controller];
+  [coordinator setPaymentRequest:payment_request_.get()];
+
+  EXPECT_EQ(1u, navigation_controller.viewControllers.count);
+
+  [coordinator start];
+  // Short delay to allow animation to complete.
+  base::test::ios::SpinRunLoopWithMaxDelay(base::TimeDelta::FromSecondsD(1.0));
+  EXPECT_EQ(2u, navigation_controller.viewControllers.count);
+
+  [coordinator stop];
+  // Short delay to allow animation to complete.
+  base::test::ios::SpinRunLoopWithMaxDelay(base::TimeDelta::FromSecondsD(1.0));
+  EXPECT_EQ(1u, navigation_controller.viewControllers.count);
+}
+
+// Tests that calling the view controller delegate method which signals that the
+// user has finished creating a new profile, causes the profile to be added to
+// the PaymentRequest instance and the corresponding coordinator delegate method
+// to get called. The new profile should also get added to the
+// PersonalDataManager.
+TEST_F(PaymentRequestContactInfoEditCoordinatorTest, DidFinishCreating) {
+  UIViewController* base_view_controller = [[UIViewController alloc] init];
+  UINavigationController* navigation_controller =
+      [[UINavigationController alloc]
+          initWithRootViewController:base_view_controller];
+
+  ContactInfoEditCoordinator* coordinator = [[ContactInfoEditCoordinator alloc]
+      initWithBaseViewController:base_view_controller];
+  [coordinator setPaymentRequest:payment_request_.get()];
+
+  // Mock the coordinator delegate.
+  id delegate = [OCMockObject
+      mockForProtocol:@protocol(ContactInfoEditCoordinatorDelegate)];
+  [[delegate expect]
+      contactInfoEditCoordinator:coordinator
+         didFinishEditingProfile:static_cast<autofill::AutofillProfile*>(
+                                     [OCMArg anyPointer])];
+  [coordinator setDelegate:delegate];
+
+  EXPECT_EQ(1u, navigation_controller.viewControllers.count);
+
+  [coordinator start];
+  // Short delay to allow animation to complete.
+  base::test::ios::SpinRunLoopWithMaxDelay(base::TimeDelta::FromSecondsD(1.0));
+  EXPECT_EQ(2u, navigation_controller.viewControllers.count);
+
+  // Expect an autofill profile to be added to the PaymentRequest.
+  EXPECT_CALL(*payment_request_,
+              AddAutofillProfile(
+                  ProfileMatches("John Doe", "john@doe.com", "16502111111")))
+      .Times(1);
+  // Expect an autofill profile to be added to the PersonalDataManager.
+  EXPECT_CALL(
+      personal_data_manager_,
+      AddProfile(ProfileMatches("John Doe", "john@doe.com", "16502111111")))
+      .Times(1);
+  // No autofill profile should get updated in the PersonalDataManager.
+  EXPECT_CALL(personal_data_manager_, UpdateProfile(_)).Times(0);
+  // No autofill profile should get invalidated in PaymentsProfileComparator.
+  EXPECT_CALL(*profile_comparator_, Invalidate(_)).Times(0);
+
+  // Call the controller delegate method.
+  PaymentRequestEditViewController* view_controller =
+      base::mac::ObjCCastStrict<PaymentRequestEditViewController>(
+          navigation_controller.visibleViewController);
+  [coordinator paymentRequestEditViewController:view_controller
+                         didFinishEditingFields:GetEditorFields()];
+
+  EXPECT_OCMOCK_VERIFY(delegate);
+}
+
+// Tests that calling the view controller delegate method which signals that the
+// user has finished editing a profile, causes the corresponding coordinator
+// delegate method to get called. The profile should not get re-added to the
+// PaymentRequest instance or the PersonalDataManager. However, it is expected
+// to get updated in the PersonalDataManager.
+TEST_F(PaymentRequestContactInfoEditCoordinatorTest, DidFinishEditing) {
+  UIViewController* base_view_controller = [[UIViewController alloc] init];
+  UINavigationController* navigation_controller =
+      [[UINavigationController alloc]
+          initWithRootViewController:base_view_controller];
+
+  ContactInfoEditCoordinator* coordinator = [[ContactInfoEditCoordinator alloc]
+      initWithBaseViewController:base_view_controller];
+  [coordinator setPaymentRequest:payment_request_.get()];
+
+  // Set the profile to be edited.
+  autofill::AutofillProfile profile;
+  [coordinator setProfile:&profile];
+
+  // Mock the coordinator delegate.
+  id delegate = [OCMockObject
+      mockForProtocol:@protocol(ContactInfoEditCoordinatorDelegate)];
+  [[delegate expect]
+      contactInfoEditCoordinator:coordinator
+         didFinishEditingProfile:static_cast<autofill::AutofillProfile*>(
+                                     [OCMArg anyPointer])];
+  [coordinator setDelegate:delegate];
+
+  EXPECT_EQ(1u, navigation_controller.viewControllers.count);
+
+  [coordinator start];
+  // Short delay to allow animation to complete.
+  base::test::ios::SpinRunLoopWithMaxDelay(base::TimeDelta::FromSecondsD(1.0));
+  EXPECT_EQ(2u, navigation_controller.viewControllers.count);
+
+  // No autofill profile should get added to the PaymentRequest.
+  EXPECT_CALL(*payment_request_, AddAutofillProfile(_)).Times(0);
+  // No autofill profile should get added to the PersonalDataManager.
+  EXPECT_CALL(personal_data_manager_, AddProfile(_)).Times(0);
+  // Expect an autofill profile to be updated in the PersonalDataManager.
+  EXPECT_CALL(
+      personal_data_manager_,
+      UpdateProfile(ProfileMatches("John Doe", "john@doe.com", "16502111111")))
+      .Times(1);
+  // Expect an autofill profile to be invalidated in PaymentsProfileComparator.
+  EXPECT_CALL(
+      *profile_comparator_,
+      Invalidate(ProfileMatches("John Doe", "john@doe.com", "16502111111")))
+      .Times(1);
+
+  // Call the controller delegate method.
+  PaymentRequestEditViewController* view_controller =
+      base::mac::ObjCCastStrict<PaymentRequestEditViewController>(
+          navigation_controller.visibleViewController);
+  [coordinator paymentRequestEditViewController:view_controller
+                         didFinishEditingFields:GetEditorFields()];
+
+  EXPECT_OCMOCK_VERIFY(delegate);
+}
+
+// Tests that calling the view controller delegate method which signals that the
+// user has chosen to cancel creating/editing a profile, causes the
+// corresponding coordinator delegate method to get called.
+TEST_F(PaymentRequestContactInfoEditCoordinatorTest, DidCancel) {
+  UIViewController* base_view_controller = [[UIViewController alloc] init];
+  UINavigationController* navigation_controller =
+      [[UINavigationController alloc]
+          initWithRootViewController:base_view_controller];
+
+  ContactInfoEditCoordinator* coordinator = [[ContactInfoEditCoordinator alloc]
+      initWithBaseViewController:base_view_controller];
+  [coordinator setPaymentRequest:payment_request_.get()];
+
+  // Mock the coordinator delegate.
+  id delegate = [OCMockObject
+      mockForProtocol:@protocol(ContactInfoEditCoordinatorDelegate)];
+  [[delegate expect] contactInfoEditCoordinatorDidCancel:coordinator];
+  [coordinator setDelegate:delegate];
+
+  EXPECT_EQ(1u, navigation_controller.viewControllers.count);
+
+  [coordinator start];
+  // Short delay to allow animation to complete.
+  base::test::ios::SpinRunLoopWithMaxDelay(base::TimeDelta::FromSecondsD(1.0));
+  EXPECT_EQ(2u, navigation_controller.viewControllers.count);
+
+  // Call the controller delegate method.
+  PaymentRequestEditViewController* view_controller =
+      base::mac::ObjCCastStrict<PaymentRequestEditViewController>(
+          navigation_controller.visibleViewController);
+  [coordinator paymentRequestEditViewControllerDidCancel:view_controller];
+
+  EXPECT_OCMOCK_VERIFY(delegate);
+}
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_mediator.h b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.h
new file mode 100644
index 0000000..c5824719
--- /dev/null
+++ b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.h
@@ -0,0 +1,39 @@
+// Copyright 2017 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 IOS_CHROME_BROWSER_UI_PAYMENTS_CONTACT_INFO_EDIT_MEDIATOR_H_
+#define IOS_CHROME_BROWSER_UI_PAYMENTS_CONTACT_INFO_EDIT_MEDIATOR_H_
+
+#import <Foundation/Foundation.h>
+
+#import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller_data_source.h"
+
+class PaymentRequest;
+@protocol PaymentRequestEditConsumer;
+
+namespace autofill {
+class AutofillProfile;
+}  // namespace autofill
+
+// Serves as data source for AddressEditViewController.
+@interface ContactInfoEditMediator
+    : NSObject<PaymentRequestEditViewControllerDataSource>
+
+// The consumer for this object. This can change during the lifetime of this
+// object and may be nil.
+@property(nonatomic, weak) id<PaymentRequestEditConsumer> consumer;
+
+// Initializes this object with an instance of PaymentRequest which has a copy
+// of web::PaymentRequest as provided by the page invoking the Payment Request
+// API as well as |profile| which is the profile to be edited, if any.
+// This object will not take ownership of |paymentRequest| or |profile|.
+- (instancetype)initWithPaymentRequest:(PaymentRequest*)paymentRequest
+                               profile:(autofill::AutofillProfile*)profile
+    NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_PAYMENTS_CONTACT_INFO_EDIT_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm
new file mode 100644
index 0000000..6539749a
--- /dev/null
+++ b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm
@@ -0,0 +1,142 @@
+// Copyright 2017 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 "ios/chrome/browser/ui/payments/contact_info_edit_mediator.h"
+
+#include "base/logging.h"
+#include "base/strings/sys_string_conversions.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/field_types.h"
+#include "components/strings/grit/components_strings.h"
+#include "ios/chrome/browser/application_context.h"
+#include "ios/chrome/browser/payments/payment_request.h"
+#import "ios/chrome/browser/ui/autofill/autofill_ui_type.h"
+#import "ios/chrome/browser/ui/payments/payment_request_edit_consumer.h"
+#import "ios/chrome/browser/ui/payments/payment_request_editor_field.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@interface ContactInfoEditMediator ()
+
+// The PaymentRequest object owning an instance of web::PaymentRequest as
+// provided by the page invoking the Payment Request API. This is a weak
+// pointer and should outlive this class.
+@property(nonatomic, assign) PaymentRequest* paymentRequest;
+
+// The profile to be edited, if any. This pointer is not owned by this class and
+// should outlive it.
+@property(nonatomic, assign) autofill::AutofillProfile* profile;
+
+// The list of current editor fields.
+@property(nonatomic, strong) NSMutableArray<EditorField*>* fields;
+
+@end
+
+@implementation ContactInfoEditMediator
+
+@synthesize state = _state;
+@synthesize consumer = _consumer;
+@synthesize paymentRequest = _paymentRequest;
+@synthesize profile = _profile;
+@synthesize fields = _fields;
+
+- (instancetype)initWithPaymentRequest:(PaymentRequest*)paymentRequest
+                               profile:(autofill::AutofillProfile*)profile {
+  self = [super init];
+  if (self) {
+    _paymentRequest = paymentRequest;
+    _profile = profile;
+    _state =
+        _profile ? EditViewControllerStateEdit : EditViewControllerStateCreate;
+  }
+  return self;
+}
+
+#pragma mark - Setters
+
+- (void)setConsumer:(id<PaymentRequestEditConsumer>)consumer {
+  _consumer = consumer;
+  [self.consumer setEditorFields:[self createEditorFields]];
+}
+
+#pragma mark - PaymentRequestEditViewControllerDataSource
+
+- (CollectionViewItem*)headerItem {
+  return nil;
+}
+
+- (BOOL)shouldHideBackgroundForHeaderItem {
+  return NO;
+}
+
+- (UIImage*)iconIdentifyingEditorField:(EditorField*)field {
+  return nil;
+}
+
+#pragma mark - Helper methods
+
+// Creates and returns an array of editor fields.
+- (NSArray<EditorField*>*)createEditorFields {
+  self.fields = [[NSMutableArray alloc] init];
+
+  if (_paymentRequest->request_payer_name()) {
+    NSString* name = self.profile
+                         ? base::SysUTF16ToNSString(self.profile->GetInfo(
+                               autofill::AutofillType(autofill::NAME_FULL),
+                               GetApplicationContext()->GetApplicationLocale()))
+                         : nil;
+    EditorField* nameField = [[EditorField alloc]
+        initWithAutofillUIType:AutofillUITypeProfileFullName
+                     fieldType:EditorFieldTypeTextField
+                         label:l10n_util::GetNSString(
+                                   IDS_PAYMENTS_NAME_FIELD_IN_CONTACT_DETAILS)
+                         value:name
+                      required:YES];
+    [self.fields addObject:nameField];
+  }
+
+  if (_paymentRequest->request_payer_phone()) {
+    NSString* phone =
+        self.profile
+            ? base::SysUTF16ToNSString(self.profile->GetInfo(
+                  autofill::AutofillType(autofill::PHONE_HOME_WHOLE_NUMBER),
+                  GetApplicationContext()->GetApplicationLocale()))
+            : nil;
+    EditorField* phoneField = [[EditorField alloc]
+        initWithAutofillUIType:AutofillUITypeProfileHomePhoneWholeNumber
+                     fieldType:EditorFieldTypeTextField
+                         label:l10n_util::GetNSString(
+                                   IDS_PAYMENTS_PHONE_FIELD_IN_CONTACT_DETAILS)
+                         value:phone
+                      required:YES];
+    [self.fields addObject:phoneField];
+  }
+
+  if (_paymentRequest->request_payer_email()) {
+    NSString* email =
+        self.profile ? base::SysUTF16ToNSString(self.profile->GetInfo(
+                           autofill::AutofillType(autofill::EMAIL_ADDRESS),
+                           GetApplicationContext()->GetApplicationLocale()))
+                     : nil;
+    EditorField* emailField = [[EditorField alloc]
+        initWithAutofillUIType:AutofillUITypeProfileEmailAddress
+                     fieldType:EditorFieldTypeTextField
+                         label:l10n_util::GetNSString(
+                                   IDS_PAYMENTS_EMAIL_FIELD_IN_CONTACT_DETAILS)
+                         value:email
+                      required:YES];
+    [self.fields addObject:emailField];
+  }
+
+  DCHECK(self.fields.count > 0) << "The contact info editor shouldn't be "
+                                   "reachable if no contact information is "
+                                   "requested.";
+  return self.fields;
+}
+
+@end
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm b/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm
new file mode 100644
index 0000000..639fbed
--- /dev/null
+++ b/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm
@@ -0,0 +1,199 @@
+// Copyright 2017 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 "ios/chrome/browser/ui/payments/contact_info_edit_mediator.h"
+
+#include "base/mac/foundation_util.h"
+#include "base/memory/ptr_util.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/browser/test_personal_data_manager.h"
+#include "components/strings/grit/components_strings.h"
+#include "ios/chrome/browser/payments/payment_request_test_util.h"
+#include "ios/chrome/browser/payments/test_payment_request.h"
+#import "ios/chrome/browser/ui/autofill/autofill_ui_type_util.h"
+#import "ios/chrome/browser/ui/payments/payment_request_edit_consumer.h"
+#import "ios/chrome/browser/ui/payments/payment_request_editor_field.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+#include "third_party/ocmock/OCMock/OCMock.h"
+#include "third_party/ocmock/gtest_support.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+class PaymentRequestContactInfoEditMediatorTest : public PlatformTest {
+ protected:
+  PaymentRequestContactInfoEditMediatorTest()
+      : payment_request_(base::MakeUnique<TestPaymentRequest>(
+            payment_request_test_util::CreateTestWebPaymentRequest(),
+            &personal_data_manager_)) {}
+
+  autofill::TestPersonalDataManager personal_data_manager_;
+  std::unique_ptr<TestPaymentRequest> payment_request_;
+};
+
+// Tests that the expected editor fields are created when creating a profile.
+TEST_F(PaymentRequestContactInfoEditMediatorTest, TestFieldsWhenCreate) {
+  id check_block = ^BOOL(id value) {
+    EXPECT_TRUE([value isKindOfClass:[NSArray class]]);
+    NSArray* fields = base::mac::ObjCCastStrict<NSArray>(value);
+    EXPECT_EQ(3U, fields.count);
+
+    id field = fields[0];
+    EXPECT_TRUE([field isKindOfClass:[EditorField class]]);
+    EditorField* editor_field = base::mac::ObjCCastStrict<EditorField>(field);
+    EXPECT_EQ(AutofillUITypeProfileFullName, editor_field.autofillUIType);
+    EXPECT_EQ(EditorFieldTypeTextField, editor_field.fieldType);
+    EXPECT_TRUE([editor_field.label
+        isEqualToString:l10n_util::GetNSString(
+                            IDS_PAYMENTS_NAME_FIELD_IN_CONTACT_DETAILS)]);
+    EXPECT_EQ(nil, editor_field.value);
+
+    field = fields[1];
+    EXPECT_TRUE([field isKindOfClass:[EditorField class]]);
+    editor_field = base::mac::ObjCCastStrict<EditorField>(field);
+    EXPECT_EQ(AutofillUITypeProfileHomePhoneWholeNumber,
+              editor_field.autofillUIType);
+    EXPECT_EQ(EditorFieldTypeTextField, editor_field.fieldType);
+    EXPECT_TRUE([editor_field.label
+        isEqualToString:l10n_util::GetNSString(
+                            IDS_PAYMENTS_PHONE_FIELD_IN_CONTACT_DETAILS)]);
+    EXPECT_EQ(nil, editor_field.value);
+
+    field = fields[2];
+    EXPECT_TRUE([field isKindOfClass:[EditorField class]]);
+    editor_field = base::mac::ObjCCastStrict<EditorField>(field);
+    EXPECT_EQ(AutofillUITypeProfileEmailAddress, editor_field.autofillUIType);
+    EXPECT_EQ(EditorFieldTypeTextField, editor_field.fieldType);
+    EXPECT_TRUE([editor_field.label
+        isEqualToString:l10n_util::GetNSString(
+                            IDS_PAYMENTS_EMAIL_FIELD_IN_CONTACT_DETAILS)]);
+    EXPECT_EQ(nil, editor_field.value);
+
+    return YES;
+  };
+
+  // Mock the consumer.
+  id consumer =
+      [OCMockObject mockForProtocol:@protocol(PaymentRequestEditConsumer)];
+  [[consumer expect] setEditorFields:[OCMArg checkWithBlock:check_block]];
+
+  ContactInfoEditMediator* mediator = [[ContactInfoEditMediator alloc]
+      initWithPaymentRequest:payment_request_.get()
+                     profile:nil];
+  [mediator setConsumer:consumer];
+
+  EXPECT_OCMOCK_VERIFY(consumer);
+}
+
+// Tests that the expected editor fields are created when editing a profile.
+TEST_F(PaymentRequestContactInfoEditMediatorTest, TestFieldsWhenEdit) {
+  id check_block = ^BOOL(id value) {
+    EXPECT_TRUE([value isKindOfClass:[NSArray class]]);
+    NSArray* fields = base::mac::ObjCCastStrict<NSArray>(value);
+    EXPECT_EQ(3U, fields.count);
+
+    id field = fields[0];
+    EXPECT_TRUE([field isKindOfClass:[EditorField class]]);
+    EditorField* editor_field = base::mac::ObjCCastStrict<EditorField>(field);
+    EXPECT_TRUE([editor_field.value isEqualToString:@"John H. Doe"]);
+
+    field = fields[1];
+    EXPECT_TRUE([field isKindOfClass:[EditorField class]]);
+    editor_field = base::mac::ObjCCastStrict<EditorField>(field);
+    EXPECT_TRUE([editor_field.value isEqualToString:@"16502111111"]);
+
+    field = fields[2];
+    EXPECT_TRUE([field isKindOfClass:[EditorField class]]);
+    editor_field = base::mac::ObjCCastStrict<EditorField>(field);
+    EXPECT_TRUE([editor_field.value isEqualToString:@"johndoe@hades.com"]);
+
+    return YES;
+  };
+
+  // Mock the consumer.
+  id consumer =
+      [OCMockObject mockForProtocol:@protocol(PaymentRequestEditConsumer)];
+  [[consumer expect] setEditorFields:[OCMArg checkWithBlock:check_block]];
+
+  autofill::AutofillProfile autofill_profile = autofill::test::GetFullProfile();
+  ContactInfoEditMediator* mediator = [[ContactInfoEditMediator alloc]
+      initWithPaymentRequest:payment_request_.get()
+                     profile:&autofill_profile];
+  [mediator setConsumer:consumer];
+
+  EXPECT_OCMOCK_VERIFY(consumer);
+}
+
+// Tests that the expected editor fields are created when only name is
+// requested.
+TEST_F(PaymentRequestContactInfoEditMediatorTest, TestFieldsRequestNameOnly) {
+  id check_block = ^BOOL(id value) {
+    EXPECT_TRUE([value isKindOfClass:[NSArray class]]);
+    NSArray* fields = base::mac::ObjCCastStrict<NSArray>(value);
+    EXPECT_EQ(1U, fields.count);
+
+    id field = fields[0];
+    EXPECT_TRUE([field isKindOfClass:[EditorField class]]);
+    EditorField* editor_field = base::mac::ObjCCastStrict<EditorField>(field);
+    EXPECT_EQ(AutofillUITypeProfileFullName, editor_field.autofillUIType);
+
+    return YES;
+  };
+
+  payment_request_->web_payment_request().options.request_payer_phone = false;
+  payment_request_->web_payment_request().options.request_payer_email = false;
+
+  // Mock the consumer.
+  id consumer =
+      [OCMockObject mockForProtocol:@protocol(PaymentRequestEditConsumer)];
+  [[consumer expect] setEditorFields:[OCMArg checkWithBlock:check_block]];
+
+  ContactInfoEditMediator* mediator = [[ContactInfoEditMediator alloc]
+      initWithPaymentRequest:payment_request_.get()
+                     profile:nil];
+  [mediator setConsumer:consumer];
+
+  EXPECT_OCMOCK_VERIFY(consumer);
+}
+
+// Tests that the expected editor fields are created when phone number and email
+// are requested.
+TEST_F(PaymentRequestContactInfoEditMediatorTest, TestFieldsRequestPhoneEmail) {
+  id check_block = ^BOOL(id value) {
+    EXPECT_TRUE([value isKindOfClass:[NSArray class]]);
+    NSArray* fields = base::mac::ObjCCastStrict<NSArray>(value);
+    EXPECT_EQ(2U, fields.count);
+
+    id field = fields[0];
+    EXPECT_TRUE([field isKindOfClass:[EditorField class]]);
+    EditorField* editor_field = base::mac::ObjCCastStrict<EditorField>(field);
+    EXPECT_EQ(AutofillUITypeProfileHomePhoneWholeNumber,
+              editor_field.autofillUIType);
+
+    field = fields[1];
+    EXPECT_TRUE([field isKindOfClass:[EditorField class]]);
+    editor_field = base::mac::ObjCCastStrict<EditorField>(field);
+    EXPECT_EQ(AutofillUITypeProfileEmailAddress, editor_field.autofillUIType);
+
+    return YES;
+  };
+
+  payment_request_->web_payment_request().options.request_payer_name = false;
+
+  // Mock the consumer.
+  id consumer =
+      [OCMockObject mockForProtocol:@protocol(PaymentRequestEditConsumer)];
+  [[consumer expect] setEditorFields:[OCMArg checkWithBlock:check_block]];
+
+  ContactInfoEditMediator* mediator = [[ContactInfoEditMediator alloc]
+      initWithPaymentRequest:payment_request_.get()
+                     profile:nil];
+  [mediator setConsumer:consumer];
+
+  EXPECT_OCMOCK_VERIFY(consumer);
+}
diff --git a/ios/chrome/browser/ui/payments/contact_info_selection_coordinator.h b/ios/chrome/browser/ui/payments/contact_info_selection_coordinator.h
index 509d4a50..5c0541c 100644
--- a/ios/chrome/browser/ui/payments/contact_info_selection_coordinator.h
+++ b/ios/chrome/browser/ui/payments/contact_info_selection_coordinator.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #import "ios/chrome/browser/chrome_coordinator.h"
+#import "ios/chrome/browser/ui/payments/contact_info_edit_coordinator.h"
 #import "ios/chrome/browser/ui/payments/payment_request_selector_view_controller.h"
 
 class PaymentRequest;
@@ -38,7 +39,8 @@
 // selection view controller. This view controller will be presented by the view
 // controller provided in the initializer.
 @interface ContactInfoSelectionCoordinator
-    : ChromeCoordinator<PaymentRequestSelectorViewControllerDelegate>
+    : ChromeCoordinator<PaymentRequestSelectorViewControllerDelegate,
+                        ContactInfoEditCoordinatorDelegate>
 
 // The PaymentRequest object having a copy of web::PaymentRequest as provided by
 // the page invoking the Payment Request API. This pointer is not owned by this
diff --git a/ios/chrome/browser/ui/payments/contact_info_selection_coordinator.mm b/ios/chrome/browser/ui/payments/contact_info_selection_coordinator.mm
index 8a7c400..0c07deb 100644
--- a/ios/chrome/browser/ui/payments/contact_info_selection_coordinator.mm
+++ b/ios/chrome/browser/ui/payments/contact_info_selection_coordinator.mm
@@ -28,6 +28,9 @@
 @interface ContactInfoSelectionCoordinator ()
 
 @property(nonatomic, strong)
+    ContactInfoEditCoordinator* contactInfoEditCoordinator;
+
+@property(nonatomic, strong)
     PaymentRequestSelectorViewController* viewController;
 
 @property(nonatomic, strong) ContactInfoSelectionMediator* mediator;
@@ -44,6 +47,7 @@
 
 @synthesize paymentRequest = _paymentRequest;
 @synthesize delegate = _delegate;
+@synthesize contactInfoEditCoordinator = _contactInfoEditCoordinator;
 @synthesize viewController = _viewController;
 @synthesize mediator = _mediator;
 
@@ -66,6 +70,8 @@
 
 - (void)stop {
   [self.baseViewController.navigationController popViewControllerAnimated:YES];
+  [self.contactInfoEditCoordinator stop];
+  self.contactInfoEditCoordinator = nil;
   self.viewController = nil;
   self.mediator = nil;
 }
@@ -90,7 +96,29 @@
 
 - (void)paymentRequestSelectorViewControllerDidSelectAddItem:
     (PaymentRequestSelectorViewController*)controller {
-  // TODO(crbug.com/602666): Display contact info editor.
+  self.contactInfoEditCoordinator = [[ContactInfoEditCoordinator alloc]
+      initWithBaseViewController:self.viewController];
+  self.contactInfoEditCoordinator.paymentRequest = self.paymentRequest;
+  self.contactInfoEditCoordinator.delegate = self;
+  [self.contactInfoEditCoordinator start];
+}
+
+#pragma mark - ContactInfoEditCoordinatorDelegate
+
+- (void)contactInfoEditCoordinator:(ContactInfoEditCoordinator*)coordinator
+           didFinishEditingProfile:(autofill::AutofillProfile*)profile {
+  [self.contactInfoEditCoordinator stop];
+  self.contactInfoEditCoordinator = nil;
+
+  // Inform |self.delegate| that |profile| has been selected.
+  [self.delegate contactInfoSelectionCoordinator:self
+                         didSelectContactProfile:profile];
+}
+
+- (void)contactInfoEditCoordinatorDidCancel:
+    (ContactInfoEditCoordinator*)coordinator {
+  [self.contactInfoEditCoordinator stop];
+  self.contactInfoEditCoordinator = nil;
 }
 
 #pragma mark - Helper methods
diff --git a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h
index 4352f8e..8aea55d 100644
--- a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h
+++ b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h
@@ -21,11 +21,6 @@
 // Delegate protocol for PaymentRequestEditViewController.
 @protocol PaymentRequestEditViewControllerDelegate<NSObject>
 
-// Notifies the delegate that the user has selected |field|.
-- (void)paymentRequestEditViewController:
-            (PaymentRequestEditViewController*)controller
-                          didSelectField:(EditorField*)field;
-
 // Notifies the delegate that the user has finished editing the editor fields.
 - (void)paymentRequestEditViewController:
             (PaymentRequestEditViewController*)controller
@@ -36,6 +31,13 @@
 - (void)paymentRequestEditViewControllerDidCancel:
     (PaymentRequestEditViewController*)controller;
 
+@optional
+
+// Notifies the delegate that the user has selected |field|.
+- (void)paymentRequestEditViewController:
+            (PaymentRequestEditViewController*)controller
+                          didSelectField:(EditorField*)field;
+
 @end
 
 // Validator protocol for PaymentRequestEditViewController.
diff --git a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
index 523bdb16..14227ebb 100644
--- a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
+++ b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
@@ -548,7 +548,10 @@
   if (field.fieldType == EditorFieldTypeSelector)
     [[_currentEditingCell textField] resignFirstResponder];
 
-  [_delegate paymentRequestEditViewController:self didSelectField:field];
+  if ([self.delegate respondsToSelector:@selector
+                     (paymentRequestEditViewController:didSelectField:)]) {
+    [_delegate paymentRequestEditViewController:self didSelectField:field];
+  }
 }
 
 #pragma mark MDCCollectionViewStylingDelegate
diff --git a/ios/chrome/browser/ui/payments/payment_request_manager.h b/ios/chrome/browser/ui/payments/payment_request_manager.h
index 1776b8f..22595b9 100644
--- a/ios/chrome/browser/ui/payments/payment_request_manager.h
+++ b/ios/chrome/browser/ui/payments/payment_request_manager.h
@@ -7,6 +7,8 @@
 
 #import <UIKit/UIKit.h>
 
+class ToolbarModelIOS;
+
 namespace ios {
 class ChromeBrowserState;
 }  // namespace ios
@@ -25,6 +27,10 @@
 // YES if Payment Request is enabled on the current web state.
 @property(readonly) BOOL enabled;
 
+// IOS specific version of ToolbarModel that is used for grabbing security
+// info.
+@property(nonatomic, assign) ToolbarModelIOS* toolbarModel;
+
 // The current web state being observed for PaymentRequest invocations.
 @property(nonatomic, assign) web::WebState* webState;
 
diff --git a/ios/chrome/browser/ui/payments/payment_request_manager.mm b/ios/chrome/browser/ui/payments/payment_request_manager.mm
index 9fc18f8..72fee7b2 100644
--- a/ios/chrome/browser/ui/payments/payment_request_manager.mm
+++ b/ios/chrome/browser/ui/payments/payment_request_manager.mm
@@ -34,9 +34,11 @@
 #import "ios/chrome/browser/ui/commands/ios_command_ids.h"
 #import "ios/chrome/browser/ui/payments/js_payment_request_manager.h"
 #import "ios/chrome/browser/ui/payments/payment_request_coordinator.h"
+#include "ios/chrome/browser/ui/toolbar/toolbar_model_ios.h"
 #include "ios/web/public/favicon_status.h"
 #include "ios/web/public/navigation_item.h"
 #include "ios/web/public/navigation_manager.h"
+#include "ios/web/public/origin_util.h"
 #include "ios/web/public/payments/payment_request.h"
 #include "ios/web/public/ssl_status.h"
 #import "ios/web/public/url_scheme_util.h"
@@ -47,6 +49,7 @@
 #import "ios/web/public/web_state/web_state_observer_bridge.h"
 #include "third_party/libaddressinput/chromium/chrome_metadata_source.h"
 #include "third_party/libaddressinput/chromium/chrome_storage_impl.h"
+#include "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -201,6 +204,7 @@
 @implementation PaymentRequestManager
 
 @synthesize enabled = _enabled;
+@synthesize toolbarModel = _toolbarModel;
 @synthesize webState = _webState;
 @synthesize browserState = _browserState;
 @synthesize paymentRequestJsManager = _paymentRequestJsManager;
@@ -433,8 +437,8 @@
   NSString* pageTitle = base::SysUTF16ToNSString([self webState]->GetTitle());
   NSString* pageHost =
       base::SysUTF8ToNSString([self webState]->GetLastCommittedURL().host());
-  // TODO(crbug.com/728639): Determine when connection is secure.
-  BOOL connectionSecure = false;
+  BOOL connectionSecure =
+      [self webState]->GetLastCommittedURL().SchemeIs(url::kHttpsScheme);
   autofill::AutofillManager* autofillManager =
       autofill::AutofillDriverIOS::FromWebState(_webState)->autofill_manager();
   _paymentRequestCoordinator = [[PaymentRequestCoordinator alloc]
@@ -603,15 +607,31 @@
     return NO;
   }
 
-  if (!web::UrlHasWebScheme([self webState]->GetLastCommittedURL()) ||
+  if (![self toolbarModel]) {
+    return NO;
+  }
+
+  // Checks if the current page is a web view with HTML and that the
+  // origin is localhost, file://, or cryptographic.
+  if (!web::IsOriginSecure([self webState]->GetLastCommittedURL()) ||
       ![self webState]->ContentIsHTML()) {
     return NO;
   }
 
-  const web::NavigationItem* navigationItem =
-      [self webState]->GetNavigationManager()->GetLastCommittedItem();
-  return navigationItem && navigationItem->GetSSL().security_style ==
-                               web::SECURITY_STYLE_AUTHENTICATED;
+  if (![self webState]->GetLastCommittedURL().SchemeIsCryptographic()) {
+    // The URL has a secure origin, but is not https, so it must be local.
+    // Return YES at this point, because localhost and filesystem URLS are
+    // considered secure regardless of scheme.
+    return YES;
+  }
+
+  // The following security level checks ensure that if the scheme is
+  // cryptographic then the SSL certificate is valid.
+  security_state::SecurityLevel securityLevel =
+      _toolbarModel->GetToolbarModel()->GetSecurityLevel(true);
+  return securityLevel == security_state::EV_SECURE ||
+         securityLevel == security_state::SECURE ||
+         securityLevel == security_state::SECURE_WITH_POLICY_INSTALLED_CERT;
 }
 
 #pragma mark - PaymentRequestCoordinatorDelegate methods
diff --git a/media/blink/webmediaplayer_delegate.h b/media/blink/webmediaplayer_delegate.h
index c756e3c..e4949b17 100644
--- a/media/blink/webmediaplayer_delegate.h
+++ b/media/blink/webmediaplayer_delegate.h
@@ -8,6 +8,9 @@
 namespace blink {
 class WebMediaPlayer;
 }
+namespace gfx {
+class Size;
+}
 namespace media {
 
 enum class MediaContentType;
@@ -88,6 +91,9 @@
   // so that we can do the right thing with media that starts paused.
   virtual void DidPause(int player_id) = 0;
 
+  // Notify that the size of the media player is changed.
+  virtual void DidPlayerSizeChange(int delegate_id, const gfx::Size& size) = 0;
+
   // Notify that playback is stopped. This will drop wake locks and remove any
   // external controls.
   //
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index a993c41..c6188ab 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -1517,6 +1517,8 @@
 
   if (observer_)
     observer_->OnMetadataChanged(pipeline_metadata_);
+
+  delegate_->DidPlayerSizeChange(delegate_id_, NaturalSize());
 }
 
 void WebMediaPlayerImpl::OnVideoOpacityChange(bool opaque) {
@@ -2042,6 +2044,8 @@
       delegate_->PlayerGone(delegate_id_);
       break;
     case DelegateState::PLAYING: {
+      if (HasVideo())
+        delegate_->DidPlayerSizeChange(delegate_id_, NaturalSize());
       delegate_->DidPlay(
           delegate_id_, HasVideo(), has_audio,
           media::DurationToMediaContentType(GetPipelineMediaDuration()));
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/media/blink/webmediaplayer_impl_unittest.cc
index efbeaf22..3f57153 100644
--- a/media/blink/webmediaplayer_impl_unittest.cc
+++ b/media/blink/webmediaplayer_impl_unittest.cc
@@ -158,6 +158,10 @@
     DCHECK_EQ(player_id_, player_id);
   }
 
+  void DidPlayerSizeChange(int player_id, const gfx::Size& size) override {
+    DCHECK_EQ(player_id_, player_id);
+  }
+
   bool IsFrameHidden() override { return is_hidden_; }
 
   bool IsFrameClosed() override { return is_closed_; }
diff --git a/media/filters/vpx_video_decoder.cc b/media/filters/vpx_video_decoder.cc
index 0229c6ca..53a2192 100644
--- a/media/filters/vpx_video_decoder.cc
+++ b/media/filters/vpx_video_decoder.cc
@@ -120,7 +120,7 @@
 // not to since current day CPUs tend to be multi-core and we measured
 // performance benefits on older machines such as P4s with hyperthreading.
 static const int kDecodeThreads = 2;
-static const int kMaxDecodeThreads = 16;
+static const int kMaxDecodeThreads = 32;
 
 // Returns the number of threads.
 static int GetThreadCount(const VideoDecoderConfig& config) {
@@ -134,9 +134,14 @@
       // For VP9 decode when using the default thread count, increase the number
       // of decode threads to equal the maximum number of tiles possible for
       // higher resolution streams.
-      if (config.coded_size().width() >= 2048)
+      const int width = config.coded_size().width();
+      if (width >= 8192)
+        decode_threads = 32;
+      else if (width >= 4096)
+        decode_threads = 16;
+      else if (width >= 2048)
         decode_threads = 8;
-      else if (config.coded_size().width() >= 1024)
+      else if (width >= 1024)
         decode_threads = 4;
     }
 
diff --git a/mojo/edk/system/BUILD.gn b/mojo/edk/system/BUILD.gn
index 8dd8cf8..1d6bb17 100644
--- a/mojo/edk/system/BUILD.gn
+++ b/mojo/edk/system/BUILD.gn
@@ -150,6 +150,7 @@
     "core_test_base.cc",
     "core_test_base.h",
     "core_unittest.cc",
+    "handle_table_unittest.cc",
     "message_pipe_unittest.cc",
     "options_validation_unittest.cc",
     "platform_handle_dispatcher_unittest.cc",
diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc
index b8c66b5..0513c42 100644
--- a/mojo/edk/system/core.cc
+++ b/mojo/edk/system/core.cc
@@ -18,6 +18,7 @@
 #include "base/rand_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "base/trace_event/memory_dump_manager.h"
 #include "mojo/edk/embedder/embedder.h"
 #include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/embedder/platform_shared_buffer.h"
@@ -126,7 +127,11 @@
 
 }  // namespace
 
-Core::Core() {}
+Core::Core() {
+  handles_.reset(new HandleTable);
+  base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
+      handles_.get(), "MojoHandleTable", nullptr);
+}
 
 Core::~Core() {
   if (node_controller_ && node_controller_->io_task_runner()) {
@@ -139,6 +144,8 @@
                              base::Bind(&Core::PassNodeControllerToIOThread,
                                         base::Passed(&node_controller_)));
   }
+  base::trace_event::MemoryDumpManager::GetInstance()
+      ->UnregisterAndDeleteDumpProviderSoon(std::move(handles_));
 }
 
 void Core::SetIOTaskRunner(scoped_refptr<base::TaskRunner> io_task_runner) {
@@ -153,8 +160,8 @@
 }
 
 scoped_refptr<Dispatcher> Core::GetDispatcher(MojoHandle handle) {
-  base::AutoLock lock(handles_.GetLock());
-  return handles_.GetDispatcher(handle);
+  base::AutoLock lock(handles_->GetLock());
+  return handles_->GetDispatcher(handle);
 }
 
 void Core::SetDefaultProcessErrorCallback(
@@ -214,8 +221,8 @@
 }
 
 MojoHandle Core::AddDispatcher(scoped_refptr<Dispatcher> dispatcher) {
-  base::AutoLock lock(handles_.GetLock());
-  return handles_.AddDispatcher(dispatcher);
+  base::AutoLock lock(handles_->GetLock());
+  return handles_->AddDispatcher(dispatcher);
 }
 
 bool Core::AddDispatchersFromTransit(
@@ -223,8 +230,8 @@
     MojoHandle* handles) {
   bool failed = false;
   {
-    base::AutoLock lock(handles_.GetLock());
-    if (!handles_.AddDispatchersFromTransit(dispatchers, handles))
+    base::AutoLock lock(handles_->GetLock());
+    if (!handles_->AddDispatchersFromTransit(dispatchers, handles))
       failed = true;
   }
   if (failed) {
@@ -249,9 +256,9 @@
 MojoResult Core::PassWrappedPlatformHandle(
     MojoHandle wrapper_handle,
     ScopedPlatformHandle* platform_handle) {
-  base::AutoLock lock(handles_.GetLock());
+  base::AutoLock lock(handles_->GetLock());
   scoped_refptr<Dispatcher> d;
-  MojoResult result = handles_.GetAndRemoveDispatcher(wrapper_handle, &d);
+  MojoResult result = handles_->GetAndRemoveDispatcher(wrapper_handle, &d);
   if (result != MOJO_RESULT_OK)
     return result;
   if (d->GetType() == Dispatcher::Type::PLATFORM_HANDLE) {
@@ -300,15 +307,15 @@
   scoped_refptr<Dispatcher> dispatcher;
   MojoResult result = MOJO_RESULT_OK;
   {
-    base::AutoLock lock(handles_.GetLock());
+    base::AutoLock lock(handles_->GetLock());
     // Get the dispatcher and check it before removing it from the handle table
     // to ensure that the dispatcher is of the correct type. This ensures we
     // don't close and remove the wrong type of dispatcher.
-    dispatcher = handles_.GetDispatcher(mojo_handle);
+    dispatcher = handles_->GetDispatcher(mojo_handle);
     if (!dispatcher || dispatcher->GetType() != Dispatcher::Type::SHARED_BUFFER)
       return MOJO_RESULT_INVALID_ARGUMENT;
 
-    result = handles_.GetAndRemoveDispatcher(mojo_handle, &dispatcher);
+    result = handles_->GetAndRemoveDispatcher(mojo_handle, &dispatcher);
     if (result != MOJO_RESULT_OK)
       return result;
   }
@@ -366,8 +373,8 @@
   RequestContext request_context;
   scoped_refptr<Dispatcher> dispatcher;
   {
-    base::AutoLock lock(handles_.GetLock());
-    MojoResult rv = handles_.GetAndRemoveDispatcher(handle, &dispatcher);
+    base::AutoLock lock(handles_->GetLock());
+    MojoResult rv = handles_->GetAndRemoveDispatcher(handle, &dispatcher);
     if (rv != MOJO_RESULT_OK)
       return rv;
   }
@@ -463,10 +470,10 @@
 
   std::vector<Dispatcher::DispatcherInTransit> dispatchers;
   {
-    base::AutoLock lock(handles_.GetLock());
-    MojoResult rv = handles_.BeginTransit(handles, num_handles, &dispatchers);
+    base::AutoLock lock(handles_->GetLock());
+    MojoResult rv = handles_->BeginTransit(handles, num_handles, &dispatchers);
     if (rv != MOJO_RESULT_OK) {
-      handles_.CancelTransit(dispatchers);
+      handles_->CancelTransit(dispatchers);
       return rv;
     }
   }
@@ -477,12 +484,12 @@
       num_bytes, dispatchers.data(), num_handles, &message);
 
   {
-    base::AutoLock lock(handles_.GetLock());
+    base::AutoLock lock(handles_->GetLock());
     if (rv == MOJO_RESULT_OK) {
-      handles_.CompleteTransitAndClose(dispatchers);
+      handles_->CompleteTransitAndClose(dispatchers);
       *message_handle = reinterpret_cast<MojoMessageHandle>(message.release());
     } else {
-      handles_.CancelTransit(dispatchers);
+      handles_->CancelTransit(dispatchers);
     }
   }
 
@@ -547,8 +554,8 @@
     scoped_refptr<Dispatcher> unused;
     unused->Close();
 
-    base::AutoLock lock(handles_.GetLock());
-    handles_.GetAndRemoveDispatcher(*message_pipe_handle0, &unused);
+    base::AutoLock lock(handles_->GetLock());
+    handles_->GetAndRemoveDispatcher(*message_pipe_handle0, &unused);
     return MOJO_RESULT_RESOURCE_EXHAUSTED;
   }
 
@@ -657,9 +664,11 @@
 
   bool valid_handles = true;
   {
-    base::AutoLock lock(handles_.GetLock());
-    MojoResult result0 = handles_.GetAndRemoveDispatcher(handle0, &dispatcher0);
-    MojoResult result1 = handles_.GetAndRemoveDispatcher(handle1, &dispatcher1);
+    base::AutoLock lock(handles_->GetLock());
+    MojoResult result0 =
+        handles_->GetAndRemoveDispatcher(handle0, &dispatcher0);
+    MojoResult result1 =
+        handles_->GetAndRemoveDispatcher(handle1, &dispatcher1);
     if (result0 != MOJO_RESULT_OK || result1 != MOJO_RESULT_OK ||
         dispatcher0->GetType() != Dispatcher::Type::MESSAGE_PIPE ||
         dispatcher1->GetType() != Dispatcher::Type::MESSAGE_PIPE)
@@ -754,8 +763,8 @@
       *data_pipe_consumer_handle == MOJO_HANDLE_INVALID) {
     if (*data_pipe_producer_handle != MOJO_HANDLE_INVALID) {
       scoped_refptr<Dispatcher> unused;
-      base::AutoLock lock(handles_.GetLock());
-      handles_.GetAndRemoveDispatcher(*data_pipe_producer_handle, &unused);
+      base::AutoLock lock(handles_->GetLock());
+      handles_->GetAndRemoveDispatcher(*data_pipe_producer_handle, &unused);
     }
     producer->Close();
     consumer->Close();
@@ -993,8 +1002,8 @@
   scoped_refptr<Dispatcher> dispatcher;
   MojoResult result = MOJO_RESULT_OK;
   {
-    base::AutoLock lock(handles_.GetLock());
-    result = handles_.GetAndRemoveDispatcher(mojo_handle, &dispatcher);
+    base::AutoLock lock(handles_->GetLock());
+    result = handles_->GetAndRemoveDispatcher(mojo_handle, &dispatcher);
     if (result != MOJO_RESULT_OK)
       return result;
   }
@@ -1024,8 +1033,8 @@
 }
 
 void Core::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) {
-  base::AutoLock lock(handles_.GetLock());
-  handles_.GetActiveHandlesForTest(handles);
+  base::AutoLock lock(handles_->GetLock());
+  handles_->GetActiveHandlesForTest(handles);
 }
 
 // static
diff --git a/mojo/edk/system/core.h b/mojo/edk/system/core.h
index 47552557..a92d0b4 100644
--- a/mojo/edk/system/core.h
+++ b/mojo/edk/system/core.h
@@ -299,7 +299,7 @@
   // but cannot be associated with a specific process.
   ProcessErrorCallback default_process_error_callback_;
 
-  HandleTable handles_;
+  std::unique_ptr<HandleTable> handles_;
 
   base::Lock mapping_table_lock_;  // Protects |mapping_table_|.
   MappingTable mapping_table_;
diff --git a/mojo/edk/system/handle_table.cc b/mojo/edk/system/handle_table.cc
index d4793bb..5a9d87d 100644
--- a/mojo/edk/system/handle_table.cc
+++ b/mojo/edk/system/handle_table.cc
@@ -32,21 +32,16 @@
     case Dispatcher::Type::PLATFORM_HANDLE:
       return "platform_handle";
   }
+  NOTREACHED();
   return "unknown";
 }
 
-const char* kDumpProviderName = "MojoHandleTable";
-
 }  // namespace
 
 HandleTable::HandleTable() {
-  base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
-      this, kDumpProviderName, nullptr);
 }
 
 HandleTable::~HandleTable() {
-  base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
-      this, kDumpProviderName, nullptr);
 }
 
 base::Lock& HandleTable::GetLock() {
@@ -181,7 +176,6 @@
     }
   }
 
-  pmd->CreateAllocatorDump("mojo");
   for (const auto& entry : handle_count) {
     base::trace_event::MemoryAllocatorDump* inner_dump =
         pmd->CreateAllocatorDump(std::string("mojo/") +
diff --git a/mojo/edk/system/handle_table.h b/mojo/edk/system/handle_table.h
index 62c5add..38741b0 100644
--- a/mojo/edk/system/handle_table.h
+++ b/mojo/edk/system/handle_table.h
@@ -10,16 +10,19 @@
 #include <vector>
 
 #include "base/containers/hash_tables.h"
+#include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/synchronization/lock.h"
 #include "base/trace_event/memory_dump_provider.h"
 #include "mojo/edk/system/dispatcher.h"
+#include "mojo/edk/system/system_impl_export.h"
 #include "mojo/public/c/system/types.h"
 
 namespace mojo {
 namespace edk {
 
-class HandleTable : public base::trace_event::MemoryDumpProvider {
+class MOJO_SYSTEM_IMPL_EXPORT HandleTable
+    : public base::trace_event::MemoryDumpProvider {
  public:
   HandleTable();
   ~HandleTable() override;
@@ -55,6 +58,8 @@
   void GetActiveHandlesForTest(std::vector<MojoHandle> *handles);
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(HandleTableTest, OnMemoryDump);
+
   // MemoryDumpProvider implementation.
   bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
                     base::trace_event::ProcessMemoryDump* pmd) override;
diff --git a/mojo/edk/system/handle_table_unittest.cc b/mojo/edk/system/handle_table_unittest.cc
new file mode 100644
index 0000000..15bace01
--- /dev/null
+++ b/mojo/edk/system/handle_table_unittest.cc
@@ -0,0 +1,76 @@
+// Copyright 2017 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 "mojo/edk/system/handle_table.h"
+
+#include <memory>
+
+#include "base/synchronization/lock.h"
+#include "base/trace_event/memory_allocator_dump.h"
+#include "base/trace_event/memory_dump_request_args.h"
+#include "base/trace_event/process_memory_dump.h"
+#include "base/trace_event/trace_event_argument.h"
+#include "mojo/edk/system/dispatcher.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace edk {
+namespace {
+
+class FakeMessagePipeDispatcher : public Dispatcher {
+ public:
+  FakeMessagePipeDispatcher() {}
+
+  Type GetType() const override { return Type::MESSAGE_PIPE; }
+
+  MojoResult Close() override { return MOJO_RESULT_OK; }
+
+ private:
+  ~FakeMessagePipeDispatcher() override {}
+  DISALLOW_COPY_AND_ASSIGN(FakeMessagePipeDispatcher);
+};
+
+void CheckNameAndValue(base::trace_event::ProcessMemoryDump* pmd,
+                       const std::string& name,
+                       const std::string& value) {
+  base::trace_event::MemoryAllocatorDump* mad = pmd->GetAllocatorDump(name);
+  ASSERT_TRUE(mad);
+
+  std::unique_ptr<base::Value> dict_value =
+      mad->attributes_for_testing()->ToBaseValue();
+  ASSERT_TRUE(dict_value->is_dict());
+
+  base::DictionaryValue* dict;
+  ASSERT_TRUE(dict_value->GetAsDictionary(&dict));
+
+  base::DictionaryValue* inner_dict;
+  ASSERT_TRUE(dict->GetDictionary("object_count", &inner_dict));
+
+  std::string output;
+  ASSERT_TRUE(inner_dict->GetString("value", &output));
+  EXPECT_EQ(value, output);
+}
+
+}  // namespace
+
+TEST(HandleTableTest, OnMemoryDump) {
+  HandleTable ht;
+
+  {
+    base::AutoLock auto_lock(ht.GetLock());
+    scoped_refptr<mojo::edk::Dispatcher> dispatcher(
+        new FakeMessagePipeDispatcher);
+    ht.AddDispatcher(dispatcher);
+  }
+
+  base::trace_event::MemoryDumpArgs args;
+  base::trace_event::ProcessMemoryDump pmd(nullptr, args);
+  ht.OnMemoryDump(args, &pmd);
+
+  CheckNameAndValue(&pmd, "mojo/message_pipe", "1");
+  CheckNameAndValue(&pmd, "mojo/data_pipe_consumer", "0");
+}
+
+}  // namespace edk
+}  // namespace mojo
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 3ee51c9..b60dd606 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -5497,7 +5497,13 @@
       "//testing/perf",
       "//url",
     ]
-
+    data = [
+      # Needed for isolate script to execute.
+      "//testing/scripts/common.py",
+      "//testing/xvfb.py",
+      "//testing/scripts/run_gtest_perf_test.py",
+      "//tools/perf/generate_legacy_perf_dashboard_json.py",
+    ]
     if (enable_websockets) {
       sources += [ "websockets/websocket_frame_perftest.cc" ]
     }
diff --git a/net/cookies/cookie_monster_perftest.cc b/net/cookies/cookie_monster_perftest.cc
index eb9ce7b9..ff951336 100644
--- a/net/cookies/cookie_monster_perftest.cc
+++ b/net/cookies/cookie_monster_perftest.cc
@@ -25,7 +25,7 @@
 
 const int kNumCookies = 20000;
 const char kCookieLine[] = "A  = \"b=;\\\"\"  ;secure;;;";
-const char kGoogleURL[] = "http://www.google.izzle";
+const char kGoogleURL[] = "http://www.foo.com";
 
 int CountInString(const std::string& str, char c) {
   return std::count(str.begin(), str.end(), c);
@@ -305,7 +305,7 @@
   std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
 
   // Import will happen on first access.
-  GURL gurl("www.google.com");
+  GURL gurl("www.foo.com");
   CookieOptions options;
   base::PerfTimeLogger timer("Cookie_monster_import_from_store");
   getCookiesCallback.GetCookies(cm.get(), gurl);
@@ -319,7 +319,7 @@
   std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
   base::PerfTimeLogger timer("Cookie_monster_get_key");
   for (int i = 0; i < kNumCookies; i++)
-    cm->GetKey("www.google.com");
+    cm->GetKey("www.foo.com");
   timer.Done();
 }
 
@@ -376,7 +376,7 @@
         test_case.num_cookies, test_case.num_old_cookies, 0, 0,
         CookieMonster::kSafeFromGlobalPurgeDays * 2);
 
-    GURL gurl("http://google.com");
+    GURL gurl("http://foo.com");
     std::string cookie_line("z=3");
     // Trigger the Garbage collection we're allowed.
     setCookieCallback.SetCookie(cm.get(), gurl, cookie_line);
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc
index da46fd9..3cd57005 100644
--- a/net/cookies/cookie_monster_unittest.cc
+++ b/net/cookies/cookie_monster_unittest.cc
@@ -122,8 +122,8 @@
   using CookieStoreTest<T>::SetCookie;
 
  protected:
-  using CookieStoreTest<T>::http_www_google_;
-  using CookieStoreTest<T>::https_www_google_;
+  using CookieStoreTest<T>::http_www_foo_;
+  using CookieStoreTest<T>::https_www_foo_;
 
   CookieList GetAllCookiesForURLWithOptions(CookieMonster* cm,
                                             const GURL& url,
@@ -297,9 +297,8 @@
       std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
       for (int i = 0; i < more_than_enough_cookies; ++i) {
         std::string cookie = base::StringPrintf("a%03d=b", i);
-        EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), cookie));
-        std::string cookies =
-            this->GetCookies(cm.get(), http_www_google_.url());
+        EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), cookie));
+        std::string cookies = this->GetCookies(cm.get(), http_www_foo_.url());
         // Make sure we find it in the cookies.
         EXPECT_NE(cookies.find(cookie), std::string::npos);
         // Count the number of cookies.
@@ -310,17 +309,16 @@
     // Add a bunch of cookies on multiple hosts within a single eTLD.
     // Should keep at least kDomainMaxCookies - kDomainPurgeCookies
     // between them.  We shouldn't go above kDomainMaxCookies for both together.
-    GURL url_google_specific(http_www_google_.Format("http://www.gmail.%D"));
+    GURL url_google_specific(http_www_foo_.Format("http://www.gmail.%D"));
     {
       std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
       for (int i = 0; i < more_than_enough_cookies; ++i) {
         std::string cookie_general = base::StringPrintf("a%03d=b", i);
-        EXPECT_TRUE(
-            SetCookie(cm.get(), http_www_google_.url(), cookie_general));
+        EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), cookie_general));
         std::string cookie_specific = base::StringPrintf("c%03d=b", i);
         EXPECT_TRUE(SetCookie(cm.get(), url_google_specific, cookie_specific));
         std::string cookies_general =
-            this->GetCookies(cm.get(), http_www_google_.url());
+            this->GetCookies(cm.get(), http_www_foo_.url());
         EXPECT_NE(cookies_general.find(cookie_general), std::string::npos);
         std::string cookies_specific =
             this->GetCookies(cm.get(), url_google_specific);
@@ -332,7 +330,7 @@
       // After all this, there should be at least
       // kDomainMaxCookies - kDomainPurgeCookies for both URLs.
       std::string cookies_general =
-          this->GetCookies(cm.get(), http_www_google_.url());
+          this->GetCookies(cm.get(), http_www_foo_.url());
       std::string cookies_specific =
           this->GetCookies(cm.get(), url_google_specific);
       int total_cookies = (CountInString(cookies_general, '=') +
@@ -355,7 +353,7 @@
     return COOKIE_PRIORITY_DEFAULT;
   }
 
-  // Instantiates a CookieMonster, adds multiple cookies (to http_www_google_)
+  // Instantiates a CookieMonster, adds multiple cookies (to http_www_foo_)
   // with priorities specified by |coded_priority_str|, and tests priority-aware
   // domain cookie eviction.
   //
@@ -407,7 +405,7 @@
             base::StringPrintf("a%d=b;priority=%s;%s", next_cookie_id,
                                CookiePriorityToString(priority).c_str(),
                                is_secure ? "secure" : "");
-        EXPECT_TRUE(SetCookie(cm, https_www_google_.url(), cookie));
+        EXPECT_TRUE(SetCookie(cm, https_www_foo_.url(), cookie));
         cookie_data.push_back(std::make_pair(is_secure, priority));
         id_list[is_secure][priority].push_back(next_cookie_id);
       }
@@ -418,7 +416,7 @@
     std::vector<int> surviving_id_list[2][3];
 
     // Parse the list of cookies
-    std::string cookie_str = this->GetCookies(cm, https_www_google_.url());
+    std::string cookie_str = this->GetCookies(cm, https_www_foo_.url());
     size_t num_nonsecure = 0;
     size_t num_secure = 0;
     for (const std::string& token : base::SplitString(
@@ -509,7 +507,7 @@
           cookie = base::StringPrintf("a%d=b; Secure", next_cookie_id);
         else
           cookie = base::StringPrintf("a%d=b", next_cookie_id);
-        EXPECT_TRUE(SetCookie(cm.get(), https_www_google_.url(), cookie));
+        EXPECT_TRUE(SetCookie(cm.get(), https_www_foo_.url(), cookie));
         ++next_cookie_id;
       }
     }
@@ -995,21 +993,20 @@
 };
 
 TEST_F(DeferredCookieTaskTest, DeferredGetCookies) {
-  DeclareLoadedCookie(http_www_google_.url(),
+  DeclareLoadedCookie(http_www_foo_.url(),
                       "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
                       Time::Now() + TimeDelta::FromDays(3));
 
   MockGetCookiesCallback get_cookies_callback;
 
-  BeginWithForDomainKey(
-      http_www_google_.domain(),
-      GetCookiesAction(&cookie_monster(), http_www_google_.url(),
-                       &get_cookies_callback));
+  BeginWithForDomainKey(http_www_foo_.domain(),
+                        GetCookiesAction(&cookie_monster(), http_www_foo_.url(),
+                                         &get_cookies_callback));
 
   WaitForLoadCall();
 
   EXPECT_CALL(get_cookies_callback, Run("X=1"))
-      .WillOnce(GetCookiesAction(&cookie_monster(), http_www_google_.url(),
+      .WillOnce(GetCookiesAction(&cookie_monster(), http_www_foo_.url(),
                                  &get_cookies_callback));
   base::RunLoop loop;
   EXPECT_CALL(get_cookies_callback, Run("X=1")).WillOnce(QuitRunLoop(&loop));
@@ -1021,16 +1018,15 @@
 TEST_F(DeferredCookieTaskTest, DeferredSetCookie) {
   MockSetCookiesCallback set_cookies_callback;
 
-  BeginWithForDomainKey(
-      http_www_google_.domain(),
-      SetCookieAction(&cookie_monster(), http_www_google_.url(), "A=B",
-                      &set_cookies_callback));
+  BeginWithForDomainKey(http_www_foo_.domain(),
+                        SetCookieAction(&cookie_monster(), http_www_foo_.url(),
+                                        "A=B", &set_cookies_callback));
 
   WaitForLoadCall();
 
   EXPECT_CALL(set_cookies_callback, Run(true))
-      .WillOnce(SetCookieAction(&cookie_monster(), http_www_google_.url(),
-                                "X=Y", &set_cookies_callback));
+      .WillOnce(SetCookieAction(&cookie_monster(), http_www_foo_.url(), "X=Y",
+                                &set_cookies_callback));
   base::RunLoop loop;
   EXPECT_CALL(set_cookies_callback, Run(true)).WillOnce(QuitRunLoop(&loop));
 
@@ -1041,11 +1037,11 @@
 TEST_F(DeferredCookieTaskTest, DeferredSetAllCookies) {
   MockSetCookiesCallback set_cookies_callback;
   CookieList list;
-  list.push_back(CanonicalCookie("A", "B", "." + http_www_google_.domain(), "/",
+  list.push_back(CanonicalCookie("A", "B", "." + http_www_foo_.domain(), "/",
                                  base::Time::Now(), base::Time(), base::Time(),
                                  false, true, CookieSameSite::DEFAULT_MODE,
                                  COOKIE_PRIORITY_DEFAULT));
-  list.push_back(CanonicalCookie("C", "D", "." + http_www_google_.domain(), "/",
+  list.push_back(CanonicalCookie("C", "D", "." + http_www_foo_.domain(), "/",
                                  base::Time::Now(), base::Time(), base::Time(),
                                  false, true, CookieSameSite::DEFAULT_MODE,
                                  COOKIE_PRIORITY_DEFAULT));
@@ -1069,15 +1065,15 @@
   MockClosure delete_cookie_callback;
 
   BeginWithForDomainKey(
-      http_www_google_.domain(),
-      DeleteCookieAction(&cookie_monster(), http_www_google_.url(), "A",
+      http_www_foo_.domain(),
+      DeleteCookieAction(&cookie_monster(), http_www_foo_.url(), "A",
                          &delete_cookie_callback));
 
   WaitForLoadCall();
 
   EXPECT_CALL(delete_cookie_callback, Run())
-      .WillOnce(DeleteCookieAction(&cookie_monster(), http_www_google_.url(),
-                                   "X", &delete_cookie_callback));
+      .WillOnce(DeleteCookieAction(&cookie_monster(), http_www_foo_.url(), "X",
+                                   &delete_cookie_callback));
   base::RunLoop loop;
   EXPECT_CALL(delete_cookie_callback, Run()).WillOnce(QuitRunLoop(&loop));
 
@@ -1088,7 +1084,7 @@
 TEST_F(DeferredCookieTaskTest, DeferredSetCookieWithDetails) {
   MockSetCookiesCallback set_cookies_callback;
 
-  CookiesInputInfo cookie_info = {www_google_foo_.url(),
+  CookiesInputInfo cookie_info = {www_foo_foo_.url(),
                                   "A",
                                   "B",
                                   std::string(),
@@ -1099,13 +1095,13 @@
                                   CookieSameSite::DEFAULT_MODE,
                                   COOKIE_PRIORITY_DEFAULT};
   BeginWithForDomainKey(
-      http_www_google_.domain(),
+      http_www_foo_.domain(),
       SetCookieWithDetailsAction(&cookie_monster(), cookie_info,
                                  &set_cookies_callback));
 
   WaitForLoadCall();
 
-  CookiesInputInfo cookie_info_exp = {www_google_foo_.url(),
+  CookiesInputInfo cookie_info_exp = {www_foo_foo_.url(),
                                       "A",
                                       "B",
                                       std::string(),
@@ -1126,7 +1122,7 @@
 }
 
 TEST_F(DeferredCookieTaskTest, DeferredGetAllCookies) {
-  DeclareLoadedCookie(http_www_google_.url(),
+  DeclareLoadedCookie(http_www_foo_.url(),
                       "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
                       Time::Now() + TimeDelta::FromDays(3));
 
@@ -1148,23 +1144,22 @@
 }
 
 TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlCookies) {
-  DeclareLoadedCookie(http_www_google_.url(),
+  DeclareLoadedCookie(http_www_foo_.url(),
                       "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
                       Time::Now() + TimeDelta::FromDays(3));
 
   MockGetCookieListCallback get_cookie_list_callback;
 
   BeginWithForDomainKey(
-      http_www_google_.domain(),
-      GetAllCookiesForUrlAction(&cookie_monster(), http_www_google_.url(),
+      http_www_foo_.domain(),
+      GetAllCookiesForUrlAction(&cookie_monster(), http_www_foo_.url(),
                                 &get_cookie_list_callback));
 
   WaitForLoadCall();
 
   EXPECT_CALL(get_cookie_list_callback, Run(testing::_))
-      .WillOnce(GetAllCookiesForUrlAction(&cookie_monster(),
-                                          http_www_google_.url(),
-                                          &get_cookie_list_callback));
+      .WillOnce(GetAllCookiesForUrlAction(
+          &cookie_monster(), http_www_foo_.url(), &get_cookie_list_callback));
   base::RunLoop loop;
   EXPECT_CALL(get_cookie_list_callback, Run(testing::_))
       .WillOnce(QuitRunLoop(&loop));
@@ -1174,23 +1169,22 @@
 }
 
 TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlWithOptionsCookies) {
-  DeclareLoadedCookie(http_www_google_.url(),
+  DeclareLoadedCookie(http_www_foo_.url(),
                       "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
                       Time::Now() + TimeDelta::FromDays(3));
 
   MockGetCookieListCallback get_cookie_list_callback;
 
-  BeginWithForDomainKey(http_www_google_.domain(),
-                        GetCookieListForUrlWithOptionsAction(
-                            &cookie_monster(), http_www_google_.url(),
-                            &get_cookie_list_callback));
+  BeginWithForDomainKey(
+      http_www_foo_.domain(),
+      GetCookieListForUrlWithOptionsAction(
+          &cookie_monster(), http_www_foo_.url(), &get_cookie_list_callback));
 
   WaitForLoadCall();
 
   EXPECT_CALL(get_cookie_list_callback, Run(testing::_))
       .WillOnce(GetCookieListForUrlWithOptionsAction(
-          &cookie_monster(), http_www_google_.url(),
-          &get_cookie_list_callback));
+          &cookie_monster(), http_www_foo_.url(), &get_cookie_list_callback));
   base::RunLoop loop;
   EXPECT_CALL(get_cookie_list_callback, Run(testing::_))
       .WillOnce(QuitRunLoop(&loop));
@@ -1261,7 +1255,7 @@
 TEST_F(DeferredCookieTaskTest, DeferredDeleteCanonicalCookie) {
   std::vector<std::unique_ptr<CanonicalCookie>> cookies;
   std::unique_ptr<CanonicalCookie> cookie = BuildCanonicalCookie(
-      http_www_google_.url(), "X=1; path=/", base::Time::Now());
+      http_www_foo_.url(), "X=1; path=/", base::Time::Now());
 
   MockDeleteCallback delete_cookie_callback;
 
@@ -1301,7 +1295,7 @@
 // the backing store and that new tasks received while the queued tasks are
 // being dispatched go to the end of the queue.
 TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) {
-  DeclareLoadedCookie(http_www_google_.url(),
+  DeclareLoadedCookie(http_www_foo_.url(),
                       "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
                       Time::Now() + TimeDelta::FromDays(3));
 
@@ -1311,17 +1305,17 @@
 
   EXPECT_CALL(*this, Begin())
       .WillOnce(testing::DoAll(
-          GetCookiesAction(&cookie_monster(), http_www_google_.url(),
+          GetCookiesAction(&cookie_monster(), http_www_foo_.url(),
                            &get_cookies_callback),
-          SetCookieAction(&cookie_monster(), http_www_google_.url(), "A=B",
+          SetCookieAction(&cookie_monster(), http_www_foo_.url(), "A=B",
                           &set_cookies_callback)));
   ExpectLoadCall();
-  ExpectLoadForKeyCall(http_www_google_.domain());
+  ExpectLoadForKeyCall(http_www_foo_.domain());
   Begin();
 
   WaitForLoadCall();
   EXPECT_CALL(get_cookies_callback, Run("X=1"))
-      .WillOnce(GetCookiesAction(&cookie_monster(), http_www_google_.url(),
+      .WillOnce(GetCookiesAction(&cookie_monster(), http_www_foo_.url(),
                                  &get_cookies_callback_deferred));
   EXPECT_CALL(set_cookies_callback, Run(true));
   base::RunLoop loop;
@@ -1338,22 +1332,21 @@
   CookieOptions options;
   options.set_include_httponly();
 
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), kValidCookieLine));
-  EXPECT_EQ("A=B", GetCookies(cm.get(), http_www_google_.url()));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), kValidCookieLine));
+  EXPECT_EQ("A=B", GetCookies(cm.get(), http_www_foo_.url()));
 
-  EXPECT_TRUE(SetCookieWithOptions(cm.get(), http_www_google_.url(),
+  EXPECT_TRUE(SetCookieWithOptions(cm.get(), http_www_foo_.url(),
                                    "C=D; httponly", options));
   EXPECT_EQ("A=B; C=D",
-            GetCookiesWithOptions(cm.get(), http_www_google_.url(), options));
+            GetCookiesWithOptions(cm.get(), http_www_foo_.url(), options));
 
   EXPECT_EQ(2, DeleteAll(cm.get()));
-  EXPECT_EQ("",
-            GetCookiesWithOptions(cm.get(), http_www_google_.url(), options));
+  EXPECT_EQ("", GetCookiesWithOptions(cm.get(), http_www_foo_.url(), options));
   EXPECT_EQ(0u, store->commands().size());
 
   // Create a persistent cookie.
   EXPECT_TRUE(SetCookie(
-      cm.get(), http_www_google_.url(),
+      cm.get(), http_www_foo_.url(),
       std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
   ASSERT_EQ(1u, store->commands().size());
   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type);
@@ -1362,8 +1355,7 @@
   ASSERT_EQ(2u, store->commands().size());
   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type);
 
-  EXPECT_EQ("",
-            GetCookiesWithOptions(cm.get(), http_www_google_.url(), options));
+  EXPECT_EQ("", GetCookiesWithOptions(cm.get(), http_www_foo_.url(), options));
 }
 
 TEST_F(CookieMonsterTest, TestCookieDeleteAllCreatedBetweenTimestamps) {
@@ -1376,15 +1368,15 @@
 
   // Create 5 cookies with different creation dates.
   EXPECT_TRUE(
-      cm->SetCookieWithCreationTime(http_www_google_.url(), "T-0=Now", now));
+      cm->SetCookieWithCreationTime(http_www_foo_.url(), "T-0=Now", now));
   EXPECT_TRUE(cm->SetCookieWithCreationTime(
-      http_www_google_.url(), "T-1=Yesterday", now - TimeDelta::FromDays(1)));
+      http_www_foo_.url(), "T-1=Yesterday", now - TimeDelta::FromDays(1)));
   EXPECT_TRUE(cm->SetCookieWithCreationTime(
-      http_www_google_.url(), "T-2=DayBefore", now - TimeDelta::FromDays(2)));
+      http_www_foo_.url(), "T-2=DayBefore", now - TimeDelta::FromDays(2)));
   EXPECT_TRUE(cm->SetCookieWithCreationTime(
-      http_www_google_.url(), "T-3=ThreeDays", now - TimeDelta::FromDays(3)));
-  EXPECT_TRUE(cm->SetCookieWithCreationTime(
-      http_www_google_.url(), "T-7=LastWeek", now - TimeDelta::FromDays(7)));
+      http_www_foo_.url(), "T-3=ThreeDays", now - TimeDelta::FromDays(3)));
+  EXPECT_TRUE(cm->SetCookieWithCreationTime(http_www_foo_.url(), "T-7=LastWeek",
+                                            now - TimeDelta::FromDays(7)));
 
   // Try to delete threedays and the daybefore.
   EXPECT_EQ(2, DeleteAllCreatedBetween(cm.get(), now - TimeDelta::FromDays(3),
@@ -1425,15 +1417,15 @@
 
   // Create 5 cookies with different creation dates.
   EXPECT_TRUE(
-      cm->SetCookieWithCreationTime(http_www_google_.url(), "T-0=Now", now));
+      cm->SetCookieWithCreationTime(http_www_foo_.url(), "T-0=Now", now));
   EXPECT_TRUE(cm->SetCookieWithCreationTime(
-      http_www_google_.url(), "T-1=Yesterday", now - TimeDelta::FromDays(1)));
+      http_www_foo_.url(), "T-1=Yesterday", now - TimeDelta::FromDays(1)));
   EXPECT_TRUE(cm->SetCookieWithCreationTime(
-      http_www_google_.url(), "T-2=DayBefore", now - TimeDelta::FromDays(2)));
+      http_www_foo_.url(), "T-2=DayBefore", now - TimeDelta::FromDays(2)));
   EXPECT_TRUE(cm->SetCookieWithCreationTime(
-      http_www_google_.url(), "T-3=ThreeDays", now - TimeDelta::FromDays(3)));
-  EXPECT_TRUE(cm->SetCookieWithCreationTime(
-      http_www_google_.url(), "T-7=LastWeek", now - TimeDelta::FromDays(7)));
+      http_www_foo_.url(), "T-3=ThreeDays", now - TimeDelta::FromDays(3)));
+  EXPECT_TRUE(cm->SetCookieWithCreationTime(http_www_foo_.url(), "T-7=LastWeek",
+                                            now - TimeDelta::FromDays(7)));
 
   // Try to delete threedays and the daybefore, but we should do nothing due
   // to the predicate.
@@ -1459,7 +1451,7 @@
                 cm.get(), now - TimeDelta::FromDays(2), now, true_predicate));
   // Check our cookie values.
   std::unique_ptr<CanonicalCookie> expected_cookie =
-      CanonicalCookie::Create(http_www_google_.url(), "T-1=Yesterday",
+      CanonicalCookie::Create(http_www_foo_.url(), "T-1=Yesterday",
                               now - TimeDelta::FromDays(1), CookieOptions());
   EXPECT_THAT(test_cookie, CookieEquals(*expected_cookie))
       << "Actual:\n"
@@ -1479,8 +1471,8 @@
                                                     false_predicate));
   EXPECT_EQ(1, DeleteAllCreatedBetweenWithPredicate(cm.get(), Time(), Time(),
                                                     true_predicate));
-  expected_cookie = CanonicalCookie::Create(http_www_google_.url(), "T-0=Now",
-                                            now, CookieOptions());
+  expected_cookie = CanonicalCookie::Create(http_www_foo_.url(), "T-0=Now", now,
+                                            CookieOptions());
   EXPECT_THAT(test_cookie, CookieEquals(*expected_cookie))
       << "Actual:\n"
       << test_cookie.DebugString() << "\nExpected:\n"
@@ -1499,12 +1491,12 @@
   std::unique_ptr<CookieMonster> cm(
       new CookieMonster(nullptr, nullptr, kLastAccessThreshold));
 
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=B"));
   const Time last_access_date(GetFirstCookieAccessDate(cm.get()));
 
   // Reading the cookie again immediately shouldn't update the access date,
   // since we're inside the threshold.
-  EXPECT_EQ("A=B", GetCookies(cm.get(), http_www_google_.url()));
+  EXPECT_EQ("A=B", GetCookies(cm.get(), http_www_foo_.url()));
   EXPECT_EQ(last_access_date, GetFirstCookieAccessDate(cm.get()));
 
   // Reading after a short wait will update the access date, if the cookie
@@ -1514,14 +1506,14 @@
   CookieOptions options;
   options.set_do_not_update_access_time();
   EXPECT_EQ("A=B",
-            GetCookiesWithOptions(cm.get(), http_www_google_.url(), options));
+            GetCookiesWithOptions(cm.get(), http_www_foo_.url(), options));
   EXPECT_EQ(last_access_date, GetFirstCookieAccessDate(cm.get()));
 
   // Getting all cookies for a URL doesn't update the accessed time either.
-  CookieList cookies = GetAllCookiesForURL(cm.get(), http_www_google_.url());
+  CookieList cookies = GetAllCookiesForURL(cm.get(), http_www_foo_.url());
   CookieList::iterator it = cookies.begin();
   ASSERT_TRUE(it != cookies.end());
-  EXPECT_EQ(http_www_google_.host(), it->Domain());
+  EXPECT_EQ(http_www_foo_.host(), it->Domain());
   EXPECT_EQ("A", it->Name());
   EXPECT_EQ("B", it->Value());
   EXPECT_EQ(last_access_date, GetFirstCookieAccessDate(cm.get()));
@@ -1530,7 +1522,7 @@
   // If the flag isn't set, the last accessed time should be updated.
   options = CookieOptions();
   EXPECT_EQ("A=B",
-            GetCookiesWithOptions(cm.get(), http_www_google_.url(), options));
+            GetCookiesWithOptions(cm.get(), http_www_foo_.url(), options));
   EXPECT_FALSE(last_access_date == GetFirstCookieAccessDate(cm.get()));
 }
 
@@ -1576,58 +1568,58 @@
   CookieOptions options;
   options.set_include_httponly();
 
-  EXPECT_TRUE(SetCookieWithOptions(cm.get(), http_www_google_.url(),
+  EXPECT_TRUE(SetCookieWithOptions(cm.get(), http_www_foo_.url(),
                                    "A=B; httponly", options));
-  EXPECT_TRUE(SetCookieWithOptions(cm.get(), http_www_google_.url(),
-                                   http_www_google_.Format("C=D; domain=.%D"),
+  EXPECT_TRUE(SetCookieWithOptions(cm.get(), http_www_foo_.url(),
+                                   http_www_foo_.Format("C=D; domain=.%D"),
                                    options));
   EXPECT_TRUE(SetCookieWithOptions(
-      cm.get(), https_www_google_.url(),
-      http_www_google_.Format("E=F; domain=.%D; secure"), options));
+      cm.get(), https_www_foo_.url(),
+      http_www_foo_.Format("E=F; domain=.%D; secure"), options));
 
   const Time last_access_date(GetFirstCookieAccessDate(cm.get()));
 
   base::PlatformThread::Sleep(kAccessDelay);
 
   // Check cookies for url.
-  CookieList cookies = GetAllCookiesForURL(cm.get(), http_www_google_.url());
+  CookieList cookies = GetAllCookiesForURL(cm.get(), http_www_foo_.url());
   CookieList::iterator it = cookies.begin();
 
   ASSERT_TRUE(it != cookies.end());
-  EXPECT_EQ(http_www_google_.host(), it->Domain());
+  EXPECT_EQ(http_www_foo_.host(), it->Domain());
   EXPECT_EQ("A", it->Name());
 
   ASSERT_TRUE(++it != cookies.end());
-  EXPECT_EQ(http_www_google_.Format(".%D"), it->Domain());
+  EXPECT_EQ(http_www_foo_.Format(".%D"), it->Domain());
   EXPECT_EQ("C", it->Name());
 
   ASSERT_TRUE(++it == cookies.end());
 
   // Check cookies for url excluding http-only cookies.
-  cookies = GetAllCookiesForURLWithOptions(cm.get(), http_www_google_.url(),
+  cookies = GetAllCookiesForURLWithOptions(cm.get(), http_www_foo_.url(),
                                            CookieOptions());
   it = cookies.begin();
 
   ASSERT_TRUE(it != cookies.end());
-  EXPECT_EQ(http_www_google_.Format(".%D"), it->Domain());
+  EXPECT_EQ(http_www_foo_.Format(".%D"), it->Domain());
   EXPECT_EQ("C", it->Name());
 
   ASSERT_TRUE(++it == cookies.end());
 
   // Test secure cookies.
-  cookies = GetAllCookiesForURL(cm.get(), https_www_google_.url());
+  cookies = GetAllCookiesForURL(cm.get(), https_www_foo_.url());
   it = cookies.begin();
 
   ASSERT_TRUE(it != cookies.end());
-  EXPECT_EQ(http_www_google_.host(), it->Domain());
+  EXPECT_EQ(http_www_foo_.host(), it->Domain());
   EXPECT_EQ("A", it->Name());
 
   ASSERT_TRUE(++it != cookies.end());
-  EXPECT_EQ(http_www_google_.Format(".%D"), it->Domain());
+  EXPECT_EQ(http_www_foo_.Format(".%D"), it->Domain());
   EXPECT_EQ("C", it->Name());
 
   ASSERT_TRUE(++it != cookies.end());
-  EXPECT_EQ(http_www_google_.Format(".%D"), it->Domain());
+  EXPECT_EQ(http_www_foo_.Format(".%D"), it->Domain());
   EXPECT_EQ("E", it->Name());
 
   ASSERT_TRUE(++it == cookies.end());
@@ -1640,14 +1632,14 @@
   std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
   CookieOptions options;
 
-  EXPECT_TRUE(SetCookieWithOptions(cm.get(), www_google_foo_.url(),
+  EXPECT_TRUE(SetCookieWithOptions(cm.get(), www_foo_foo_.url(),
                                    "A=B; path=/foo;", options));
-  EXPECT_TRUE(SetCookieWithOptions(cm.get(), www_google_bar_.url(),
+  EXPECT_TRUE(SetCookieWithOptions(cm.get(), www_foo_bar_.url(),
                                    "C=D; path=/bar;", options));
   EXPECT_TRUE(
-      SetCookieWithOptions(cm.get(), http_www_google_.url(), "E=F;", options));
+      SetCookieWithOptions(cm.get(), http_www_foo_.url(), "E=F;", options));
 
-  CookieList cookies = GetAllCookiesForURL(cm.get(), www_google_foo_.url());
+  CookieList cookies = GetAllCookiesForURL(cm.get(), www_foo_foo_.url());
   CookieList::iterator it = cookies.begin();
 
   ASSERT_TRUE(it != cookies.end());
@@ -1660,7 +1652,7 @@
 
   ASSERT_TRUE(++it == cookies.end());
 
-  cookies = GetAllCookiesForURL(cm.get(), www_google_bar_.url());
+  cookies = GetAllCookiesForURL(cm.get(), www_foo_bar_.url());
   it = cookies.begin();
 
   ASSERT_TRUE(it != cookies.end());
@@ -1677,18 +1669,15 @@
 TEST_F(CookieMonsterTest, CookieSorting) {
   std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
 
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "B=B1; path=/"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "B=B2; path=/foo"));
-  EXPECT_TRUE(
-      SetCookie(cm.get(), http_www_google_.url(), "B=B3; path=/foo/bar"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=A1; path=/"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=A2; path=/foo"));
-  EXPECT_TRUE(
-      SetCookie(cm.get(), http_www_google_.url(), "A=A3; path=/foo/bar"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=B1; path=/"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=B2; path=/foo"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=B3; path=/foo/bar"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=A1; path=/"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=A2; path=/foo"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=A3; path=/foo/bar"));
 
   // Re-set cookie which should not change sort order.
-  EXPECT_TRUE(
-      SetCookie(cm.get(), http_www_google_.url(), "B=B3; path=/foo/bar"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=B3; path=/foo/bar"));
 
   CookieList cookies = GetAllCookies(cm.get());
   ASSERT_EQ(6u, cookies.size());
@@ -1707,14 +1696,14 @@
 TEST_F(CookieMonsterTest, DeleteCookieByName) {
   std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
 
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=A1; path=/"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=A2; path=/foo"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=A3; path=/bar"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "B=B1; path=/"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "B=B2; path=/foo"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "B=B3; path=/bar"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=A1; path=/"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=A2; path=/foo"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=A3; path=/bar"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=B1; path=/"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=B2; path=/foo"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=B3; path=/bar"));
 
-  DeleteCookie(cm.get(), http_www_google_.AppendPath("foo/bar"), "A");
+  DeleteCookie(cm.get(), http_www_foo_.AppendPath("foo/bar"), "A");
 
   CookieList cookies = GetAllCookies(cm.get());
   size_t expected_size = 4;
@@ -1744,20 +1733,20 @@
   // dates. We expect only the most recent one to be preserved following
   // the import.
 
-  AddCookieToList(GURL("http://www.google.com"),
+  AddCookieToList(GURL("http://www.foo.com"),
                   "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
                   Time::Now() + TimeDelta::FromDays(3), &initial_cookies);
 
-  AddCookieToList(GURL("http://www.google.com"),
+  AddCookieToList(GURL("http://www.foo.com"),
                   "X=2; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
                   Time::Now() + TimeDelta::FromDays(1), &initial_cookies);
 
   // ===> This one is the WINNER (biggest creation time).  <====
-  AddCookieToList(GURL("http://www.google.com"),
+  AddCookieToList(GURL("http://www.foo.com"),
                   "X=3; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
                   Time::Now() + TimeDelta::FromDays(4), &initial_cookies);
 
-  AddCookieToList(GURL("http://www.google.com"),
+  AddCookieToList(GURL("http://www.foo.com"),
                   "X=4; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
                   Time::Now(), &initial_cookies);
 
@@ -1765,16 +1754,16 @@
   // dates. We expect only the most recent one to be preserved the import.
 
   // ===> This one is the WINNER (biggest creation time).  <====
-  AddCookieToList(GURL("http://www.google.com"),
+  AddCookieToList(GURL("http://www.foo.com"),
                   "X=a1; path=/2; expires=Mon, 18-Apr-22 22:50:14 GMT",
                   Time::Now() + TimeDelta::FromDays(9), &initial_cookies);
 
-  AddCookieToList(GURL("http://www.google.com"),
+  AddCookieToList(GURL("http://www.foo.com"),
                   "X=a2; path=/2; expires=Mon, 18-Apr-22 22:50:14 GMT",
                   Time::Now() + TimeDelta::FromDays(2), &initial_cookies);
 
   // Insert 1 cookie with name "Y" on path "/".
-  AddCookieToList(GURL("http://www.google.com"),
+  AddCookieToList(GURL("http://www.foo.com"),
                   "Y=a; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
                   Time::Now() + TimeDelta::FromDays(10), &initial_cookies);
 
@@ -1785,12 +1774,12 @@
 
   // Verify that duplicates were not imported for path "/".
   // (If this had failed, GetCookies() would have also returned X=1, X=2, X=4).
-  EXPECT_EQ("X=3; Y=a", GetCookies(cm.get(), GURL("http://www.google.com/")));
+  EXPECT_EQ("X=3; Y=a", GetCookies(cm.get(), GURL("http://www.foo.com/")));
 
   // Verify that same-named cookie on a different path ("/x2") didn't get
   // messed up.
   EXPECT_EQ("X=a1; X=3; Y=a",
-            GetCookies(cm.get(), GURL("http://www.google.com/2/x")));
+            GetCookies(cm.get(), GURL("http://www.foo.com/2/x")));
 
   // Verify that the PersistentCookieStore was told to kill its 4 duplicates.
   ASSERT_EQ(4u, store->commands().size());
@@ -1816,22 +1805,22 @@
   // two cookies remaining, but which two (other than that there should
   // be one from each set) will be random.
   std::vector<std::unique_ptr<CanonicalCookie>> initial_cookies;
-  AddCookieToList(GURL("http://www.google.com"), "X=1; path=/", now,
+  AddCookieToList(GURL("http://www.foo.com"), "X=1; path=/", now,
                   &initial_cookies);
-  AddCookieToList(GURL("http://www.google.com"), "X=2; path=/", now,
+  AddCookieToList(GURL("http://www.foo.com"), "X=2; path=/", now,
                   &initial_cookies);
-  AddCookieToList(GURL("http://www.google.com"), "X=3; path=/", now,
+  AddCookieToList(GURL("http://www.foo.com"), "X=3; path=/", now,
                   &initial_cookies);
-  AddCookieToList(GURL("http://www.google.com"), "X=4; path=/", now,
+  AddCookieToList(GURL("http://www.foo.com"), "X=4; path=/", now,
                   &initial_cookies);
 
-  AddCookieToList(GURL("http://www.google.com"), "Y=1; path=/", earlier,
+  AddCookieToList(GURL("http://www.foo.com"), "Y=1; path=/", earlier,
                   &initial_cookies);
-  AddCookieToList(GURL("http://www.google.com"), "Y=2; path=/", earlier,
+  AddCookieToList(GURL("http://www.foo.com"), "Y=2; path=/", earlier,
                   &initial_cookies);
-  AddCookieToList(GURL("http://www.google.com"), "Y=3; path=/", earlier,
+  AddCookieToList(GURL("http://www.foo.com"), "Y=3; path=/", earlier,
                   &initial_cookies);
-  AddCookieToList(GURL("http://www.google.com"), "Y=4; path=/", earlier,
+  AddCookieToList(GURL("http://www.foo.com"), "Y=4; path=/", earlier,
                   &initial_cookies);
 
   // Inject our initial cookies into the mock PersistentCookieStore.
@@ -1856,53 +1845,47 @@
   std::unique_ptr<CookieMonster> cm(
       new CookieMonster(store.get(), delegate.get()));
 
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "C=D"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "E=F"));
-  EXPECT_EQ("A=B; C=D; E=F", GetCookies(cm.get(), http_www_google_.url()));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=B"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "C=D"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "E=F"));
+  EXPECT_EQ("A=B; C=D; E=F", GetCookies(cm.get(), http_www_foo_.url()));
   ASSERT_EQ(3u, delegate->changes().size());
   EXPECT_FALSE(delegate->changes()[0].second);
-  EXPECT_EQ(http_www_google_.url().host(),
-            delegate->changes()[0].first.Domain());
+  EXPECT_EQ(http_www_foo_.url().host(), delegate->changes()[0].first.Domain());
   EXPECT_EQ("A", delegate->changes()[0].first.Name());
   EXPECT_EQ("B", delegate->changes()[0].first.Value());
-  EXPECT_EQ(http_www_google_.url().host(),
-            delegate->changes()[1].first.Domain());
+  EXPECT_EQ(http_www_foo_.url().host(), delegate->changes()[1].first.Domain());
   EXPECT_FALSE(delegate->changes()[1].second);
   EXPECT_EQ("C", delegate->changes()[1].first.Name());
   EXPECT_EQ("D", delegate->changes()[1].first.Value());
-  EXPECT_EQ(http_www_google_.url().host(),
-            delegate->changes()[2].first.Domain());
+  EXPECT_EQ(http_www_foo_.url().host(), delegate->changes()[2].first.Domain());
   EXPECT_FALSE(delegate->changes()[2].second);
   EXPECT_EQ("E", delegate->changes()[2].first.Name());
   EXPECT_EQ("F", delegate->changes()[2].first.Value());
   delegate->reset();
 
-  EXPECT_TRUE(
-      FindAndDeleteCookie(cm.get(), http_www_google_.url().host(), "C"));
-  EXPECT_EQ("A=B; E=F", GetCookies(cm.get(), http_www_google_.url()));
+  EXPECT_TRUE(FindAndDeleteCookie(cm.get(), http_www_foo_.url().host(), "C"));
+  EXPECT_EQ("A=B; E=F", GetCookies(cm.get(), http_www_foo_.url()));
   ASSERT_EQ(1u, delegate->changes().size());
-  EXPECT_EQ(http_www_google_.url().host(),
-            delegate->changes()[0].first.Domain());
+  EXPECT_EQ(http_www_foo_.url().host(), delegate->changes()[0].first.Domain());
   EXPECT_TRUE(delegate->changes()[0].second);
   EXPECT_EQ("C", delegate->changes()[0].first.Name());
   EXPECT_EQ("D", delegate->changes()[0].first.Value());
   delegate->reset();
 
   EXPECT_FALSE(FindAndDeleteCookie(cm.get(), "random.host", "E"));
-  EXPECT_EQ("A=B; E=F", GetCookies(cm.get(), http_www_google_.url()));
+  EXPECT_EQ("A=B; E=F", GetCookies(cm.get(), http_www_foo_.url()));
   EXPECT_EQ(0u, delegate->changes().size());
 
   // Insert a cookie "a" for path "/path1"
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(),
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(),
                         "a=val1; path=/path1; "
                         "expires=Mon, 18-Apr-22 22:50:13 GMT"));
   ASSERT_EQ(1u, store->commands().size());
   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type);
   ASSERT_EQ(1u, delegate->changes().size());
   EXPECT_FALSE(delegate->changes()[0].second);
-  EXPECT_EQ(http_www_google_.url().host(),
-            delegate->changes()[0].first.Domain());
+  EXPECT_EQ(http_www_foo_.url().host(), delegate->changes()[0].first.Domain());
   EXPECT_EQ("a", delegate->changes()[0].first.Name());
   EXPECT_EQ("val1", delegate->changes()[0].first.Value());
   delegate->reset();
@@ -1911,7 +1894,7 @@
   // overwrite the non-http-only version.
   CookieOptions allow_httponly;
   allow_httponly.set_include_httponly();
-  EXPECT_TRUE(SetCookieWithOptions(cm.get(), http_www_google_.url(),
+  EXPECT_TRUE(SetCookieWithOptions(cm.get(), http_www_foo_.url(),
                                    "a=val2; path=/path1; httponly; "
                                    "expires=Mon, 18-Apr-22 22:50:14 GMT",
                                    allow_httponly));
@@ -1919,13 +1902,11 @@
   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type);
   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[2].type);
   ASSERT_EQ(2u, delegate->changes().size());
-  EXPECT_EQ(http_www_google_.url().host(),
-            delegate->changes()[0].first.Domain());
+  EXPECT_EQ(http_www_foo_.url().host(), delegate->changes()[0].first.Domain());
   EXPECT_TRUE(delegate->changes()[0].second);
   EXPECT_EQ("a", delegate->changes()[0].first.Name());
   EXPECT_EQ("val1", delegate->changes()[0].first.Value());
-  EXPECT_EQ(http_www_google_.url().host(),
-            delegate->changes()[1].first.Domain());
+  EXPECT_EQ(http_www_foo_.url().host(), delegate->changes()[1].first.Domain());
   EXPECT_FALSE(delegate->changes()[1].second);
   EXPECT_EQ("a", delegate->changes()[1].first.Name());
   EXPECT_EQ("val2", delegate->changes()[1].first.Value());
@@ -1967,28 +1948,28 @@
 
   // SetCookie, SetCookieWithOptions, SetCookieWithDetails
 
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "SetCookie1=A"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "SetCookie2=A"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "SetCookie3=A"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "SetCookie1=A"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "SetCookie2=A"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "SetCookie3=A"));
 
-  EXPECT_TRUE(SetCookieWithOptions(cm.get(), http_www_google_.url(),
+  EXPECT_TRUE(SetCookieWithOptions(cm.get(), http_www_foo_.url(),
                                    "setCookieWithOptions1=A", options));
-  EXPECT_TRUE(SetCookieWithOptions(cm.get(), http_www_google_.url(),
+  EXPECT_TRUE(SetCookieWithOptions(cm.get(), http_www_foo_.url(),
                                    "setCookieWithOptions2=A", options));
-  EXPECT_TRUE(SetCookieWithOptions(cm.get(), http_www_google_.url(),
+  EXPECT_TRUE(SetCookieWithOptions(cm.get(), http_www_foo_.url(),
                                    "setCookieWithOptions3=A", options));
 
   EXPECT_TRUE(SetCookieWithDetails(
-      cm.get(), http_www_google_.url(), "setCookieWithDetails1", "A",
-      http_www_google_.Format(".%D"), "/", Time(), Time(), Time(), false, false,
+      cm.get(), http_www_foo_.url(), "setCookieWithDetails1", "A",
+      http_www_foo_.Format(".%D"), "/", Time(), Time(), Time(), false, false,
       CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
   EXPECT_TRUE(SetCookieWithDetails(
-      cm.get(), http_www_google_.url(), "setCookieWithDetails2", "A",
-      http_www_google_.Format(".%D"), "/", Time(), Time(), Time(), false, false,
+      cm.get(), http_www_foo_.url(), "setCookieWithDetails2", "A",
+      http_www_foo_.Format(".%D"), "/", Time(), Time(), Time(), false, false,
       CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
   EXPECT_TRUE(SetCookieWithDetails(
-      cm.get(), http_www_google_.url(), "setCookieWithDetails3", "A",
-      http_www_google_.Format(".%D"), "/", Time(), Time(), Time(), false, false,
+      cm.get(), http_www_foo_.url(), "setCookieWithDetails3", "A",
+      http_www_foo_.Format(".%D"), "/", Time(), Time(), Time(), false, false,
       CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
 
   // Now we check
@@ -2020,7 +2001,7 @@
   std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
 
   // This test is really only interesting if GetKey() actually does something.
-  EXPECT_EQ("google.com", cm->GetKey("www.google.com"));
+  EXPECT_EQ("foo.com", cm->GetKey("www.foo.com"));
   EXPECT_EQ("google.izzie", cm->GetKey("www.google.izzie"));
   EXPECT_EQ("google.izzie", cm->GetKey(".google.izzie"));
   EXPECT_EQ("bbc.co.uk", cm->GetKey("bbc.co.uk"));
@@ -2049,12 +2030,12 @@
   base::Time expires(base::Time::Now() + base::TimeDelta::FromSeconds(100));
 
   const CookiesInputInfo input_info[] = {
-      {GURL("http://a.b.google.com"), "a", "1", "", "/path/to/cookie", expires,
+      {GURL("http://a.b.foo.com"), "a", "1", "", "/path/to/cookie", expires,
        false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT},
-      {GURL("https://www.google.com"), "b", "2", ".google.com",
-       "/path/from/cookie", expires + TimeDelta::FromSeconds(10), true, true,
+      {GURL("https://www.foo.com"), "b", "2", ".foo.com", "/path/from/cookie",
+       expires + TimeDelta::FromSeconds(10), true, true,
        CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT},
-      {GURL("https://google.com"), "c", "3", "", "/another/path/to/cookie",
+      {GURL("https://foo.com"), "c", "3", "", "/another/path/to/cookie",
        base::Time::Now() + base::TimeDelta::FromSeconds(100), true, false,
        CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT}};
   const int INPUT_DELETE = 1;
@@ -2111,22 +2092,21 @@
   // they're returned in the right order.
   std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
   EXPECT_TRUE(
-      SetCookie(cm.get(), GURL("http://d.c.b.a.google.com/aa/x.html"), "c=1"));
-  EXPECT_TRUE(SetCookie(cm.get(), GURL("http://b.a.google.com/aa/bb/cc/x.html"),
-                        "d=1; domain=b.a.google.com"));
-  EXPECT_TRUE(SetCookie(cm.get(), GURL("http://b.a.google.com/aa/bb/cc/x.html"),
-                        "a=4; domain=b.a.google.com"));
-  EXPECT_TRUE(SetCookie(cm.get(),
-                        GURL("http://c.b.a.google.com/aa/bb/cc/x.html"),
-                        "e=1; domain=c.b.a.google.com"));
-  EXPECT_TRUE(SetCookie(cm.get(),
-                        GURL("http://d.c.b.a.google.com/aa/bb/x.html"), "b=1"));
+      SetCookie(cm.get(), GURL("http://d.c.b.a.foo.com/aa/x.html"), "c=1"));
+  EXPECT_TRUE(SetCookie(cm.get(), GURL("http://b.a.foo.com/aa/bb/cc/x.html"),
+                        "d=1; domain=b.a.foo.com"));
+  EXPECT_TRUE(SetCookie(cm.get(), GURL("http://b.a.foo.com/aa/bb/cc/x.html"),
+                        "a=4; domain=b.a.foo.com"));
+  EXPECT_TRUE(SetCookie(cm.get(), GURL("http://c.b.a.foo.com/aa/bb/cc/x.html"),
+                        "e=1; domain=c.b.a.foo.com"));
+  EXPECT_TRUE(
+      SetCookie(cm.get(), GURL("http://d.c.b.a.foo.com/aa/bb/x.html"), "b=1"));
   EXPECT_TRUE(SetCookie(cm.get(), GURL("http://news.bbc.co.uk/midpath/x.html"),
                         "g=10"));
   {
     unsigned int i = 0;
     CookieList cookies(GetAllCookiesForURL(
-        cm.get(), GURL("http://d.c.b.a.google.com/aa/bb/cc/dd")));
+        cm.get(), GURL("http://d.c.b.a.foo.com/aa/bb/cc/dd")));
     ASSERT_EQ(5u, cookies.size());
     EXPECT_EQ("d", cookies[i++].Name());
     EXPECT_EQ("a", cookies[i++].Name());
@@ -2597,21 +2577,21 @@
   std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
   cm->SetPersistSessionCookies(true);
 
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "U=V; path=/"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "W=X; path=/foo"));
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "Y=Z; path=/"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "U=V; path=/"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "W=X; path=/foo"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "Y=Z; path=/"));
 
   CookieList list;
   list.push_back(CanonicalCookie(
-      "A", "B", "." + http_www_google_.url().host(), "/", base::Time::Now(),
+      "A", "B", "." + http_www_foo_.url().host(), "/", base::Time::Now(),
       base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
       COOKIE_PRIORITY_DEFAULT));
   list.push_back(CanonicalCookie(
-      "W", "X", "." + http_www_google_.url().host(), "/bar", base::Time::Now(),
+      "W", "X", "." + http_www_foo_.url().host(), "/bar", base::Time::Now(),
       base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
       COOKIE_PRIORITY_DEFAULT));
   list.push_back(CanonicalCookie(
-      "Y", "Z", "." + http_www_google_.url().host(), "/", base::Time::Now(),
+      "Y", "Z", "." + http_www_foo_.url().host(), "/", base::Time::Now(),
       base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
       COOKIE_PRIORITY_DEFAULT));
 
@@ -2646,51 +2626,51 @@
   base::Time creation_time = now - base::TimeDelta::FromSeconds(1);
 
   std::unique_ptr<CanonicalCookie> cookie1(base::MakeUnique<CanonicalCookie>(
-      "A", "B", "." + http_www_google_.url().host(), "/", creation_time,
+      "A", "B", "." + http_www_foo_.url().host(), "/", creation_time,
       base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
       COOKIE_PRIORITY_DEFAULT));
   std::unique_ptr<CanonicalCookie> cookie2(base::MakeUnique<CanonicalCookie>(
-      "C", "D", "." + http_www_google_.url().host(), "/", creation_time,
+      "C", "D", "." + http_www_foo_.url().host(), "/", creation_time,
       base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
       COOKIE_PRIORITY_DEFAULT));
   std::unique_ptr<CanonicalCookie> cookie3(base::MakeUnique<CanonicalCookie>(
-      "E", "F", "." + http_www_google_.url().host(), "/", creation_time,
+      "E", "F", "." + http_www_foo_.url().host(), "/", creation_time,
       base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
       COOKIE_PRIORITY_DEFAULT));
   std::unique_ptr<CanonicalCookie> cookie4(base::MakeUnique<CanonicalCookie>(
-      "G", "H", "." + http_www_google_.url().host(), "/", creation_time,
+      "G", "H", "." + http_www_foo_.url().host(), "/", creation_time,
       base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
       COOKIE_PRIORITY_DEFAULT));
   std::unique_ptr<CanonicalCookie> cookie4_with_new_value(
       base::MakeUnique<CanonicalCookie>(
-          "G", "iamnew", "." + http_www_google_.url().host(), "/",
-          creation_time, base::Time(), base::Time(), false, false,
+          "G", "iamnew", "." + http_www_foo_.url().host(), "/", creation_time,
+          base::Time(), base::Time(), false, false,
           CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
   std::unique_ptr<CanonicalCookie> cookie5(base::MakeUnique<CanonicalCookie>(
-      "I", "J", "." + http_www_google_.url().host(), "/", creation_time,
+      "I", "J", "." + http_www_foo_.url().host(), "/", creation_time,
       base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
       COOKIE_PRIORITY_DEFAULT));
   std::unique_ptr<CanonicalCookie> cookie5_with_new_creation_time(
       base::MakeUnique<CanonicalCookie>(
-          "I", "J", "." + http_www_google_.url().host(), "/", now, base::Time(),
+          "I", "J", "." + http_www_foo_.url().host(), "/", now, base::Time(),
           base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
           COOKIE_PRIORITY_DEFAULT));
   std::unique_ptr<CanonicalCookie> cookie6(base::MakeUnique<CanonicalCookie>(
-      "K", "L", "." + http_www_google_.url().host(), "/foo", creation_time,
+      "K", "L", "." + http_www_foo_.url().host(), "/foo", creation_time,
       base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
       COOKIE_PRIORITY_DEFAULT));
   std::unique_ptr<CanonicalCookie> cookie6_with_new_path(
       base::MakeUnique<CanonicalCookie>(
-          "K", "L", "." + http_www_google_.url().host(), "/bar", creation_time,
+          "K", "L", "." + http_www_foo_.url().host(), "/bar", creation_time,
           base::Time(), base::Time(), false, false,
           CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
   std::unique_ptr<CanonicalCookie> cookie7(base::MakeUnique<CanonicalCookie>(
-      "M", "N", "." + http_www_google_.url().host(), "/foo", creation_time,
+      "M", "N", "." + http_www_foo_.url().host(), "/foo", creation_time,
       base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
       COOKIE_PRIORITY_DEFAULT));
   std::unique_ptr<CanonicalCookie> cookie7_with_new_path(
       base::MakeUnique<CanonicalCookie>(
-          "M", "N", "." + http_www_google_.url().host(), "/bar", creation_time,
+          "M", "N", "." + http_www_foo_.url().host(), "/bar", creation_time,
           base::Time(), base::Time(), false, false,
           CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
 
@@ -2765,7 +2745,7 @@
   std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
   cm->SetPersistSessionCookies(true);
 
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "X=Y; path=/"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "X=Y; path=/"));
 
   ASSERT_EQ(0, store->flush_count());
   EXPECT_EQ(1, DeleteAll(cm.get()));
@@ -2793,7 +2773,7 @@
   EXPECT_EQ(samples1->TotalCount() + 1, samples2->TotalCount());
 
   // kValidCookieLine creates a session cookie.
-  ASSERT_TRUE(SetCookie(cm.get(), http_www_google_.url(), kValidCookieLine));
+  ASSERT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), kValidCookieLine));
 
   std::unique_ptr<base::HistogramSamples> samples3(
       expired_histogram->SnapshotSamples());
@@ -2804,7 +2784,7 @@
   std::string cookie_line =
       std::string(kValidCookieLine) + "; expires=Blarg arg arg";
   std::unique_ptr<CanonicalCookie> cookie(CanonicalCookie::Create(
-      http_www_google_.url(), cookie_line, Time::Now(), CookieOptions()));
+      http_www_foo_.url(), cookie_line, Time::Now(), CookieOptions()));
   ASSERT_FALSE(cookie->IsPersistent());
 }
 
@@ -2816,8 +2796,8 @@
   cm->SetPersistSessionCookies(true);
 
   // All cookies set with SetCookie are session cookies.
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B"));
-  EXPECT_EQ("A=B", GetCookies(cm.get(), http_www_google_.url()));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=B"));
+  EXPECT_EQ("A=B", GetCookies(cm.get(), http_www_foo_.url()));
 
   // The cookie was written to the backing store.
   EXPECT_EQ(1u, store->commands().size());
@@ -2826,8 +2806,8 @@
   EXPECT_EQ("B", store->commands()[0].cookie.Value());
 
   // Modify the cookie.
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=C"));
-  EXPECT_EQ("A=C", GetCookies(cm.get(), http_www_google_.url()));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=C"));
+  EXPECT_EQ("A=C", GetCookies(cm.get(), http_www_foo_.url()));
   EXPECT_EQ(3u, store->commands().size());
   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type);
   EXPECT_EQ("A", store->commands()[1].cookie.Name());
@@ -2837,8 +2817,8 @@
   EXPECT_EQ("C", store->commands()[2].cookie.Value());
 
   // Delete the cookie.
-  DeleteCookie(cm.get(), http_www_google_.url(), "A");
-  EXPECT_EQ("", GetCookies(cm.get(), http_www_google_.url()));
+  DeleteCookie(cm.get(), http_www_foo_.url(), "A");
+  EXPECT_EQ("", GetCookies(cm.get(), http_www_foo_.url()));
   EXPECT_EQ(4u, store->commands().size());
   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[3].type);
   EXPECT_EQ("A", store->commands()[3].cookie.Name());
@@ -2851,37 +2831,37 @@
   std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
 
   // Add a cookie.
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(),
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(),
                         "A=B; expires=Mon, 18-Apr-22 22:50:13 GMT"));
-  this->MatchCookieLines("A=B", GetCookies(cm.get(), http_www_google_.url()));
+  this->MatchCookieLines("A=B", GetCookies(cm.get(), http_www_foo_.url()));
   ASSERT_EQ(1u, store->commands().size());
   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type);
   // Remove it.
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B; max-age=0"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=B; max-age=0"));
   this->MatchCookieLines(std::string(),
-                         GetCookies(cm.get(), http_www_google_.url()));
+                         GetCookies(cm.get(), http_www_foo_.url()));
   ASSERT_EQ(2u, store->commands().size());
   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type);
 
   // Add a cookie.
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(),
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(),
                         "A=B; expires=Mon, 18-Apr-22 22:50:13 GMT"));
-  this->MatchCookieLines("A=B", GetCookies(cm.get(), http_www_google_.url()));
+  this->MatchCookieLines("A=B", GetCookies(cm.get(), http_www_foo_.url()));
   ASSERT_EQ(3u, store->commands().size());
   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[2].type);
   // Overwrite it.
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(),
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(),
                         "A=Foo; expires=Mon, 18-Apr-22 22:50:14 GMT"));
-  this->MatchCookieLines("A=Foo", GetCookies(cm.get(), http_www_google_.url()));
+  this->MatchCookieLines("A=Foo", GetCookies(cm.get(), http_www_foo_.url()));
   ASSERT_EQ(5u, store->commands().size());
   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[3].type);
   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[4].type);
 
   // Create some non-persistent cookies and check that they don't go to the
   // persistent storage.
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "B=Bar"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=Bar"));
   this->MatchCookieLines("A=Foo; B=Bar",
-                         GetCookies(cm.get(), http_www_google_.url()));
+                         GetCookies(cm.get(), http_www_foo_.url()));
   EXPECT_EQ(5u, store->commands().size());
 }
 
@@ -2933,23 +2913,21 @@
   histograms.ExpectTotalCount(cookie_source_histogram, 0);
 
   // Set a secure cookie on a cryptographic scheme.
-  EXPECT_TRUE(
-      SetCookie(cm.get(), https_www_google_.url(), "A=B; path=/; Secure"));
+  EXPECT_TRUE(SetCookie(cm.get(), https_www_foo_.url(), "A=B; path=/; Secure"));
   histograms.ExpectTotalCount(cookie_source_histogram, 1);
   histograms.ExpectBucketCount(
       cookie_source_histogram,
       CookieMonster::COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME, 1);
 
   // Set a non-secure cookie on a cryptographic scheme.
-  EXPECT_TRUE(SetCookie(cm.get(), https_www_google_.url(), "C=D; path=/;"));
+  EXPECT_TRUE(SetCookie(cm.get(), https_www_foo_.url(), "C=D; path=/;"));
   histograms.ExpectTotalCount(cookie_source_histogram, 2);
   histograms.ExpectBucketCount(
       cookie_source_histogram,
       CookieMonster::COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME, 1);
 
   // Set a secure cookie on a non-cryptographic scheme.
-  EXPECT_FALSE(
-      SetCookie(cm.get(), http_www_google_.url(), "D=E; path=/; Secure"));
+  EXPECT_FALSE(SetCookie(cm.get(), http_www_foo_.url(), "D=E; path=/; Secure"));
   histograms.ExpectTotalCount(cookie_source_histogram, 2);
   histograms.ExpectBucketCount(
       cookie_source_histogram,
@@ -2957,8 +2935,7 @@
 
   // Overwrite a secure cookie (set by a cryptographic scheme) on a
   // non-cryptographic scheme.
-  EXPECT_FALSE(
-      SetCookie(cm.get(), http_www_google_.url(), "A=B; path=/; Secure"));
+  EXPECT_FALSE(SetCookie(cm.get(), http_www_foo_.url(), "A=B; path=/; Secure"));
   histograms.ExpectTotalCount(cookie_source_histogram, 2);
   histograms.ExpectBucketCount(
       cookie_source_histogram,
@@ -2969,19 +2946,18 @@
 
   // Test that attempting to clear a secure cookie on a http:// URL does
   // nothing.
-  EXPECT_TRUE(
-      SetCookie(cm.get(), https_www_google_.url(), "F=G; path=/; Secure"));
+  EXPECT_TRUE(SetCookie(cm.get(), https_www_foo_.url(), "F=G; path=/; Secure"));
   histograms.ExpectTotalCount(cookie_source_histogram, 3);
-  std::string cookies1 = GetCookies(cm.get(), https_www_google_.url());
+  std::string cookies1 = GetCookies(cm.get(), https_www_foo_.url());
   EXPECT_NE(std::string::npos, cookies1.find("F=G"));
-  EXPECT_FALSE(SetCookie(cm.get(), http_www_google_.url(),
+  EXPECT_FALSE(SetCookie(cm.get(), http_www_foo_.url(),
                          "F=G; path=/; Expires=Thu, 01-Jan-1970 00:00:01 GMT"));
-  std::string cookies2 = GetCookies(cm.get(), https_www_google_.url());
+  std::string cookies2 = GetCookies(cm.get(), https_www_foo_.url());
   EXPECT_NE(std::string::npos, cookies2.find("F=G"));
   histograms.ExpectTotalCount(cookie_source_histogram, 3);
 
   // Set a non-secure cookie on a non-cryptographic scheme.
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "H=I; path=/"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "H=I; path=/"));
   histograms.ExpectTotalCount(cookie_source_histogram, 4);
   histograms.ExpectBucketCount(
       cookie_source_histogram,
@@ -2997,7 +2973,7 @@
   std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
 
   // Set a secure cookie from a secure origin
-  EXPECT_TRUE(SetCookie(cm.get(), https_www_google_.url(), "A=B; Secure"));
+  EXPECT_TRUE(SetCookie(cm.get(), https_www_foo_.url(), "A=B; Secure"));
   histograms.ExpectTotalCount(cookie_source_histogram, 1);
   histograms.ExpectBucketCount(cookie_source_histogram,
                                CookieMonster::COOKIE_DELETE_EQUIVALENT_ATTEMPT,
@@ -3005,12 +2981,12 @@
 
   // Set a new cookie with a different name from a variety of origins (including
   // the same one).
-  EXPECT_TRUE(SetCookie(cm.get(), https_www_google_.url(), "B=A;"));
+  EXPECT_TRUE(SetCookie(cm.get(), https_www_foo_.url(), "B=A;"));
   histograms.ExpectTotalCount(cookie_source_histogram, 2);
   histograms.ExpectBucketCount(cookie_source_histogram,
                                CookieMonster::COOKIE_DELETE_EQUIVALENT_ATTEMPT,
                                2);
-  EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "C=A;"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "C=A;"));
   histograms.ExpectTotalCount(cookie_source_histogram, 3);
   histograms.ExpectBucketCount(cookie_source_histogram,
                                CookieMonster::COOKIE_DELETE_EQUIVALENT_ATTEMPT,
@@ -3019,7 +2995,7 @@
   // Set a non-secure cookie from an insecure origin that matches the name of an
   // already existing cookie and additionally is equivalent to the existing
   // cookie. This should fail since it's trying to overwrite a secure cookie.
-  EXPECT_FALSE(SetCookie(cm.get(), http_www_google_.url(), "A=B;"));
+  EXPECT_FALSE(SetCookie(cm.get(), http_www_foo_.url(), "A=B;"));
   histograms.ExpectTotalCount(cookie_source_histogram, 6);
   histograms.ExpectBucketCount(cookie_source_histogram,
                                CookieMonster::COOKIE_DELETE_EQUIVALENT_ATTEMPT,
@@ -3038,7 +3014,7 @@
   // already existing cookie but is not equivalent. This should fail since it's
   // trying to shadow a secure cookie.
   EXPECT_FALSE(
-      SetCookie(cm.get(), http_www_google_.url(), "A=C; path=/some/path"));
+      SetCookie(cm.get(), http_www_foo_.url(), "A=C; path=/some/path"));
   histograms.ExpectTotalCount(cookie_source_histogram, 8);
   histograms.ExpectBucketCount(cookie_source_histogram,
                                CookieMonster::COOKIE_DELETE_EQUIVALENT_ATTEMPT,
@@ -3049,7 +3025,7 @@
 
   // Set a secure cookie from a secure origin that matches the name of an
   // already existing cookies and is equivalent.
-  EXPECT_TRUE(SetCookie(cm.get(), https_www_google_.url(), "A=D; secure"));
+  EXPECT_TRUE(SetCookie(cm.get(), https_www_foo_.url(), "A=D; secure"));
   histograms.ExpectTotalCount(cookie_source_histogram, 10);
   histograms.ExpectBucketCount(cookie_source_histogram,
                                CookieMonster::COOKIE_DELETE_EQUIVALENT_ATTEMPT,
@@ -3060,7 +3036,7 @@
 
   // Set a secure cookie from a secure origin that matches the name of an
   // already existing cookie and is not equivalent.
-  EXPECT_TRUE(SetCookie(cm.get(), https_www_google_.url(),
+  EXPECT_TRUE(SetCookie(cm.get(), https_www_foo_.url(),
                         "A=E; secure; path=/some/other/path"));
   histograms.ExpectTotalCount(cookie_source_histogram, 11);
   histograms.ExpectBucketCount(cookie_source_histogram,
@@ -3070,9 +3046,9 @@
 
 TEST_F(CookieMonsterTest, SetSecureCookies) {
   std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
-  GURL http_url("http://www.google.com");
-  GURL http_superdomain_url("http://google.com");
-  GURL https_url("https://www.google.com");
+  GURL http_url("http://www.foo.com");
+  GURL http_superdomain_url("http://foo.com");
+  GURL https_url("https://www.foo.com");
 
   // A non-secure cookie can be created from either a URL with a secure or
   // insecure scheme.
@@ -3120,13 +3096,13 @@
   // a secure cookie with the same name already exists, if the domain strings
   // domain-match, do not update the cookie.
   EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B; Secure"));
-  EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C; domain=google.com"));
-  EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C; domain=www.google.com"));
+  EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C; domain=foo.com"));
+  EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C; domain=www.foo.com"));
 
   // Since A=B was set above with no domain string, set a different cookie here
   // so the insecure examples aren't trying to overwrite the one above.
-  EXPECT_TRUE(SetCookie(cm.get(), https_url, "B=C; Secure; domain=google.com"));
-  EXPECT_FALSE(SetCookie(cm.get(), http_url, "B=D; domain=google.com"));
+  EXPECT_TRUE(SetCookie(cm.get(), https_url, "B=C; Secure; domain=foo.com"));
+  EXPECT_FALSE(SetCookie(cm.get(), http_url, "B=D; domain=foo.com"));
   EXPECT_FALSE(SetCookie(cm.get(), http_url, "B=D"));
   EXPECT_FALSE(SetCookie(cm.get(), http_superdomain_url, "B=D"));
 
@@ -3273,9 +3249,9 @@
 // accidentally. Regression test for https://crbug.com/569943.
 TEST_F(CookieMonsterTest, EquivalentCookies) {
   std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
-  GURL http_url("http://www.google.com");
-  GURL http_superdomain_url("http://google.com");
-  GURL https_url("https://www.google.com");
+  GURL http_url("http://www.foo.com");
+  GURL http_superdomain_url("http://foo.com");
+  GURL https_url("https://www.foo.com");
 
   // Tests that non-equivalent cookies because of the path attribute can be set
   // successfully.
@@ -3286,14 +3262,14 @@
   // Tests that non-equivalent cookies because of the domain attribute can be
   // set successfully.
   EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B; Secure"));
-  EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=C; domain=google.com"));
-  EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=D; domain=google.com"));
+  EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=C; domain=foo.com"));
+  EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=D; domain=foo.com"));
 }
 
 class CookieMonsterNotificationTest : public CookieMonsterTest {
  public:
   CookieMonsterNotificationTest()
-      : test_url_("http://www.google.com/foo"),
+      : test_url_("http://www.foo.com/foo"),
         store_(new MockPersistentCookieStore),
         monster_(new CookieMonster(store_.get(), nullptr)) {}
 
diff --git a/net/cookies/cookie_store_unittest.h b/net/cookies/cookie_store_unittest.h
index bc28a4f..8120bf0d 100644
--- a/net/cookies/cookie_store_unittest.h
+++ b/net/cookies/cookie_store_unittest.h
@@ -71,14 +71,14 @@
 class CookieStoreTest : public testing::Test {
  protected:
   CookieStoreTest()
-      : http_www_google_("http://www.google.izzle"),
-        https_www_google_("https://www.google.izzle"),
-        ftp_google_("ftp://ftp.google.izzle/"),
-        ws_www_google_("ws://www.google.izzle"),
-        wss_www_google_("wss://www.google.izzle"),
-        www_google_foo_("http://www.google.izzle/foo"),
-        www_google_bar_("http://www.google.izzle/bar"),
-        http_foo_com_("http://foo.com"),
+      : http_www_foo_("http://www.foo.com"),
+        https_www_foo_("https://www.foo.com"),
+        ftp_foo_("ftp://ftp.foo.com/"),
+        ws_www_foo_("ws://www.foo.com"),
+        wss_www_foo_("wss://www.foo.com"),
+        www_foo_foo_("http://www.foo.com/foo"),
+        www_foo_bar_("http://www.foo.com/bar"),
+        http_baz_com_("http://baz.com"),
         http_bar_com_("http://bar.com") {
     // This test may be used outside of the net test suite, and thus may not
     // have a message loop.
@@ -303,14 +303,14 @@
                          << "\" does not match \"" << line << "\"";
   }
 
-  const CookieURLHelper http_www_google_;
-  const CookieURLHelper https_www_google_;
-  const CookieURLHelper ftp_google_;
-  const CookieURLHelper ws_www_google_;
-  const CookieURLHelper wss_www_google_;
-  const CookieURLHelper www_google_foo_;
-  const CookieURLHelper www_google_bar_;
-  const CookieURLHelper http_foo_com_;
+  const CookieURLHelper http_www_foo_;
+  const CookieURLHelper https_www_foo_;
+  const CookieURLHelper ftp_foo_;
+  const CookieURLHelper ws_www_foo_;
+  const CookieURLHelper wss_www_foo_;
+  const CookieURLHelper www_foo_foo_;
+  const CookieURLHelper www_foo_bar_;
+  const CookieURLHelper http_baz_com_;
   const CookieURLHelper http_bar_com_;
 
   std::unique_ptr<base::WeakPtrFactory<base::MessageLoop>> weak_factory_;
@@ -340,45 +340,45 @@
       base::Time::Now() + base::TimeDelta::FromHours(1);
 
   EXPECT_TRUE(this->SetCookieWithDetails(
-      cs, this->www_google_foo_.url(), "A", "B", std::string(), "/foo",
+      cs, this->www_foo_foo_.url(), "A", "B", std::string(), "/foo",
       one_hour_ago, one_hour_from_now, base::Time(), false, false,
       CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
   // Note that for the creation time to be set exactly, without modification,
   // it must be different from the one set by the line above.
   EXPECT_TRUE(this->SetCookieWithDetails(
-      cs, this->www_google_bar_.url(), "C", "D", this->www_google_bar_.domain(),
+      cs, this->www_foo_bar_.url(), "C", "D", this->www_foo_bar_.domain(),
       "/bar", two_hours_ago, base::Time(), one_hour_ago, false, true,
       CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
   // Because of strict secure cookies, a cookie made by an HTTP URL should fail
   // to create a cookie with a the secure attribute.
   EXPECT_FALSE(this->SetCookieWithDetails(
-      cs, this->http_www_google_.url(), "E", "F", std::string(), std::string(),
+      cs, this->http_www_foo_.url(), "E", "F", std::string(), std::string(),
       base::Time(), base::Time(), base::Time(), true, false,
       CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
   EXPECT_TRUE(this->SetCookieWithDetails(
-      cs, this->https_www_google_.url(), "E", "F", std::string(), std::string(),
+      cs, this->https_www_foo_.url(), "E", "F", std::string(), std::string(),
       base::Time(), base::Time(), base::Time(), true, false,
       CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
 
   // Test that malformed attributes fail to set the cookie.
   EXPECT_FALSE(this->SetCookieWithDetails(
-      cs, this->www_google_foo_.url(), " A", "B", std::string(), "/foo",
+      cs, this->www_foo_foo_.url(), " A", "B", std::string(), "/foo",
       base::Time(), base::Time(), base::Time(), false, false,
       CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
   EXPECT_FALSE(this->SetCookieWithDetails(
-      cs, this->www_google_foo_.url(), "A;", "B", std::string(), "/foo",
+      cs, this->www_foo_foo_.url(), "A;", "B", std::string(), "/foo",
       base::Time(), base::Time(), base::Time(), false, false,
       CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
   EXPECT_FALSE(this->SetCookieWithDetails(
-      cs, this->www_google_foo_.url(), "A=", "B", std::string(), "/foo",
+      cs, this->www_foo_foo_.url(), "A=", "B", std::string(), "/foo",
       base::Time(), base::Time(), base::Time(), false, false,
       CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
   EXPECT_FALSE(this->SetCookieWithDetails(
-      cs, this->www_google_foo_.url(), "A", "B", "google.ozzzzzzle", "foo",
+      cs, this->www_foo_foo_.url(), "A", "B", "foo.ozzzzzzle", "foo",
       base::Time(), base::Time(), base::Time(), false, false,
       CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
   EXPECT_FALSE(this->SetCookieWithDetails(
-      cs, this->www_google_foo_.url(), "A=", "B", std::string(), "foo",
+      cs, this->www_foo_foo_.url(), "A=", "B", std::string(), "foo",
       base::Time(), base::Time(), base::Time(), false, false,
       CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
 
@@ -393,13 +393,13 @@
   options.set_do_not_update_access_time();
 
   CookieList cookies =
-      this->GetCookieListWithOptions(cs, this->www_google_foo_.url(), options);
+      this->GetCookieListWithOptions(cs, this->www_foo_foo_.url(), options);
   CookieList::iterator it = cookies.begin();
 
   ASSERT_TRUE(it != cookies.end());
   EXPECT_EQ("A", it->Name());
   EXPECT_EQ("B", it->Value());
-  EXPECT_EQ(this->www_google_foo_.host(), it->Domain());
+  EXPECT_EQ(this->www_foo_foo_.host(), it->Domain());
   EXPECT_EQ("/foo", it->Path());
   EXPECT_EQ(one_hour_ago, it->CreationDate());
   EXPECT_TRUE(it->IsPersistent());
@@ -417,7 +417,7 @@
   // Verify that the cookie was set as 'httponly' by passing in a CookieOptions
   // that excludes them and getting an empty result.
   if (TypeParam::supports_http_only) {
-    cookies = this->GetCookieListWithOptions(cs, this->www_google_bar_.url(),
+    cookies = this->GetCookieListWithOptions(cs, this->www_foo_bar_.url(),
                                              CookieOptions());
     it = cookies.begin();
     ASSERT_TRUE(it == cookies.end());
@@ -425,13 +425,13 @@
 
   // Get the cookie using the wide open |options|:
   cookies =
-      this->GetCookieListWithOptions(cs, this->www_google_bar_.url(), options);
+      this->GetCookieListWithOptions(cs, this->www_foo_bar_.url(), options);
   it = cookies.begin();
 
   ASSERT_TRUE(it != cookies.end());
   EXPECT_EQ("C", it->Name());
   EXPECT_EQ("D", it->Value());
-  EXPECT_EQ(this->www_google_bar_.Format(".%D"), it->Domain());
+  EXPECT_EQ(this->www_foo_bar_.Format(".%D"), it->Domain());
   EXPECT_EQ("/bar", it->Path());
   EXPECT_EQ(two_hours_ago, it->CreationDate());
   EXPECT_FALSE(it->IsPersistent());
@@ -443,15 +443,15 @@
 
   EXPECT_TRUE(++it == cookies.end());
 
-  cookies = this->GetCookieListWithOptions(cs, this->https_www_google_.url(),
-                                           options);
+  cookies =
+      this->GetCookieListWithOptions(cs, this->https_www_foo_.url(), options);
   it = cookies.begin();
 
   ASSERT_TRUE(it != cookies.end());
   EXPECT_EQ("E", it->Name());
   EXPECT_EQ("F", it->Value());
   EXPECT_EQ("/", it->Path());
-  EXPECT_EQ(this->https_www_google_.host(), it->Domain());
+  EXPECT_EQ(this->https_www_foo_.host(), it->Domain());
   // Cookie should have its creation time set, and be in a reasonable range.
   EXPECT_LE((base::Time::Now() - it->CreationDate()).magnitude().InMinutes(),
             2);
@@ -468,9 +468,9 @@
 // Test enforcement around setting secure cookies.
 TYPED_TEST_P(CookieStoreTest, SetCookieWithDetailsSecureEnforcement) {
   CookieStore* cs = this->GetCookieStore();
-  GURL http_url(this->http_www_google_.url());
+  GURL http_url(this->http_www_foo_.url());
   std::string http_domain(http_url.host());
-  GURL https_url(this->https_www_google_.url());
+  GURL https_url(this->https_www_foo_.url());
   std::string https_domain(https_url.host());
 
   // Confirm that setting the secure attribute on an HTTP URL fails, but
@@ -535,52 +535,50 @@
 
 TYPED_TEST_P(CookieStoreTest, DomainTest) {
   CookieStore* cs = this->GetCookieStore();
-  EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "A=B"));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
   this->MatchCookieLines("A=B",
-                         this->GetCookies(cs, this->http_www_google_.url()));
-  EXPECT_TRUE(
-      this->SetCookie(cs, this->http_www_google_.url(),
-                      this->http_www_google_.Format("C=D; domain=.%D")));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
+                              this->http_www_foo_.Format("C=D; domain=.%D")));
   this->MatchCookieLines("A=B; C=D",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
 
   // Verify that A=B was set as a host cookie rather than a domain
   // cookie -- should not be accessible from a sub sub-domain.
   this->MatchCookieLines(
       "C=D", this->GetCookies(
-                 cs, GURL(this->http_www_google_.Format("http://foo.www.%D"))));
+                 cs, GURL(this->http_www_foo_.Format("http://foo.www.%D"))));
 
   // Test and make sure we find domain cookies on the same domain.
   EXPECT_TRUE(
-      this->SetCookie(cs, this->http_www_google_.url(),
-                      this->http_www_google_.Format("E=F; domain=.www.%D")));
+      this->SetCookie(cs, this->http_www_foo_.url(),
+                      this->http_www_foo_.Format("E=F; domain=.www.%D")));
   this->MatchCookieLines("A=B; C=D; E=F",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
 
   // Test setting a domain= that doesn't start w/ a dot, should
   // treat it as a domain cookie, as if there was a pre-pended dot.
   EXPECT_TRUE(
-      this->SetCookie(cs, this->http_www_google_.url(),
-                      this->http_www_google_.Format("G=H; domain=www.%D")));
+      this->SetCookie(cs, this->http_www_foo_.url(),
+                      this->http_www_foo_.Format("G=H; domain=www.%D")));
   this->MatchCookieLines("A=B; C=D; E=F; G=H",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
 
   // Test domain enforcement, should fail on a sub-domain or something too deep.
-  EXPECT_FALSE(
-      this->SetCookie(cs, this->http_www_google_.url(),
-                      this->http_www_google_.Format("I=J; domain=.%R")));
+  EXPECT_FALSE(this->SetCookie(cs, this->http_www_foo_.url(),
+                               this->http_www_foo_.Format("I=J; domain=.%R")));
   this->MatchCookieLines(
       std::string(),
-      this->GetCookies(cs, GURL(this->http_www_google_.Format("http://a.%R"))));
-  EXPECT_FALSE(this->SetCookie(
-      cs, this->http_www_google_.url(),
-      this->http_www_google_.Format("K=L; domain=.bla.www.%D")));
+      this->GetCookies(cs, GURL(this->http_www_foo_.Format("http://a.%R"))));
+  EXPECT_FALSE(
+      this->SetCookie(cs, this->http_www_foo_.url(),
+                      this->http_www_foo_.Format("K=L; domain=.bla.www.%D")));
   this->MatchCookieLines(
       "C=D; E=F; G=H",
-      this->GetCookies(
-          cs, GURL(this->http_www_google_.Format("http://bla.www.%D"))));
+      this->GetCookies(cs,
+                       GURL(this->http_www_foo_.Format("http://bla.www.%D"))));
   this->MatchCookieLines("A=B; C=D; E=F; G=H",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
 }
 
 // FireFox recognizes domains containing trailing periods as valid.
@@ -588,19 +586,19 @@
 TYPED_TEST_P(CookieStoreTest, DomainWithTrailingDotTest) {
   CookieStore* cs = this->GetCookieStore();
   if (TypeParam::preserves_trailing_dots) {
-    EXPECT_FALSE(this->SetCookie(cs, this->http_www_google_.url(),
-                                 "a=1; domain=.www.google.izzle."));
-    EXPECT_FALSE(this->SetCookie(cs, this->http_www_google_.url(),
-                                 "b=2; domain=.www.google.izzle.."));
+    EXPECT_FALSE(this->SetCookie(cs, this->http_www_foo_.url(),
+                                 "a=1; domain=.www.foo.com."));
+    EXPECT_FALSE(this->SetCookie(cs, this->http_www_foo_.url(),
+                                 "b=2; domain=.www.foo.com.."));
     this->MatchCookieLines(std::string(),
-                           this->GetCookies(cs, this->http_www_google_.url()));
+                           this->GetCookies(cs, this->http_www_foo_.url()));
   } else {
-    EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
-                                "a=1; domain=.www.google.izzle."));
-    EXPECT_FALSE(this->SetCookie(cs, this->http_www_google_.url(),
-                                 "b=2; domain=.www.google.izzle.."));
+    EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
+                                "a=1; domain=.www.foo.com."));
+    EXPECT_FALSE(this->SetCookie(cs, this->http_www_foo_.url(),
+                                 "b=2; domain=.www.foo.com.."));
     this->MatchCookieLines("a=1",
-                           this->GetCookies(cs, this->http_www_google_.url()));
+                           this->GetCookies(cs, this->http_www_foo_.url()));
   }
 }
 
@@ -705,11 +703,11 @@
 // it as setting a domain cookie.
 TYPED_TEST_P(CookieStoreTest, DomainWithoutLeadingDotSameDomain) {
   CookieStore* cs = this->GetCookieStore();
-  GURL url("http://www.google.com");
-  EXPECT_TRUE(this->SetCookie(cs, url, "a=1; domain=www.google.com"));
+  GURL url("http://www.foo.com");
+  EXPECT_TRUE(this->SetCookie(cs, url, "a=1; domain=www.foo.com"));
   this->MatchCookieLines("a=1", this->GetCookies(cs, url));
-  this->MatchCookieLines(
-      "a=1", this->GetCookies(cs, GURL("http://sub.www.google.com")));
+  this->MatchCookieLines("a=1",
+                         this->GetCookies(cs, GURL("http://sub.www.foo.com")));
   this->MatchCookieLines(
       std::string(), this->GetCookies(cs, GURL("http://something-else.com")));
 }
@@ -717,9 +715,9 @@
 // Test that the domain specified in cookie string is treated case-insensitive
 TYPED_TEST_P(CookieStoreTest, CaseInsensitiveDomainTest) {
   CookieStore* cs = this->GetCookieStore();
-  GURL url("http://www.google.com");
-  EXPECT_TRUE(this->SetCookie(cs, url, "a=1; domain=.GOOGLE.COM"));
-  EXPECT_TRUE(this->SetCookie(cs, url, "b=2; domain=.wWw.gOOgLE.coM"));
+  GURL url("http://www.foo.com");
+  EXPECT_TRUE(this->SetCookie(cs, url, "a=1; domain=.FOO.COM"));
+  EXPECT_TRUE(this->SetCookie(cs, url, "b=2; domain=.wWw.fOO.cOM"));
   this->MatchCookieLines("a=1; b=2", this->GetCookies(cs, url));
 }
 
@@ -793,7 +791,7 @@
 
 TYPED_TEST_P(CookieStoreTest, TestSubdomainSettingCookiesOnKnownTLD) {
   CookieStore* cs = this->GetCookieStore();
-  GURL url("http://google.com");
+  GURL url("http://foo.com");
   EXPECT_FALSE(this->SetCookie(cs, url, "a=1; domain=.com"));
   EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=com"));
   this->MatchCookieLines(std::string(), this->GetCookies(cs, url));
@@ -801,7 +799,7 @@
 
 TYPED_TEST_P(CookieStoreTest, TestSubdomainSettingCookiesOnKnownDottedTLD) {
   CookieStore* cs = this->GetCookieStore();
-  GURL url("http://google.co.uk");
+  GURL url("http://foo.co.uk");
   EXPECT_FALSE(this->SetCookie(cs, url, "a=1; domain=.co.uk"));
   EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.uk"));
   this->MatchCookieLines(std::string(), this->GetCookies(cs, url));
@@ -841,27 +839,27 @@
 }
 
 // Test reading/writing cookies when the domain ends with a period,
-// as in "www.google.com."
+// as in "www.foo.com."
 TYPED_TEST_P(CookieStoreTest, TestHostEndsWithDot) {
   CookieStore* cs = this->GetCookieStore();
-  GURL url("http://www.google.com");
-  GURL url_with_dot("http://www.google.com.");
+  GURL url("http://www.foo.com");
+  GURL url_with_dot("http://www.foo.com.");
   EXPECT_TRUE(this->SetCookie(cs, url, "a=1"));
   this->MatchCookieLines("a=1", this->GetCookies(cs, url));
 
   // Do not share cookie space with the dot version of domain.
   // Note: this is not what FireFox does, but it _is_ what IE+Safari do.
   if (TypeParam::preserves_trailing_dots) {
-    EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.www.google.com."));
+    EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.www.foo.com."));
     this->MatchCookieLines("a=1", this->GetCookies(cs, url));
-    EXPECT_TRUE(this->SetCookie(cs, url_with_dot, "b=2; domain=.google.com."));
+    EXPECT_TRUE(this->SetCookie(cs, url_with_dot, "b=2; domain=.foo.com."));
     this->MatchCookieLines("b=2", this->GetCookies(cs, url_with_dot));
   } else {
-    EXPECT_TRUE(this->SetCookie(cs, url, "b=2; domain=.www.google.com."));
+    EXPECT_TRUE(this->SetCookie(cs, url, "b=2; domain=.www.foo.com."));
     this->MatchCookieLines("a=1 b=2", this->GetCookies(cs, url));
     // Setting this cookie should fail, since the trailing dot on the domain
     // isn't preserved, and then the domain mismatches the URL.
-    EXPECT_FALSE(this->SetCookie(cs, url_with_dot, "b=2; domain=.google.com."));
+    EXPECT_FALSE(this->SetCookie(cs, url_with_dot, "b=2; domain=.foo.com."));
   }
 
   // Make sure there weren't any side effects.
@@ -877,7 +875,7 @@
     return;
 
   CookieStore* cs = this->GetCookieStore();
-  EXPECT_FALSE(this->SetCookie(cs, this->ftp_google_.url(), kValidCookieLine));
+  EXPECT_FALSE(this->SetCookie(cs, this->ftp_foo_.url(), kValidCookieLine));
 }
 
 TYPED_TEST_P(CookieStoreTest, InvalidScheme_Read) {
@@ -885,21 +883,21 @@
     return;
 
   const std::string kValidDomainCookieLine =
-      this->http_www_google_.Format("A=B; path=/; domain=%D");
+      this->http_www_foo_.Format("A=B; path=/; domain=%D");
 
   CookieStore* cs = this->GetCookieStore();
-  EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
-                              kValidDomainCookieLine));
+  EXPECT_TRUE(
+      this->SetCookie(cs, this->http_www_foo_.url(), kValidDomainCookieLine));
   this->MatchCookieLines(std::string(),
-                         this->GetCookies(cs, this->ftp_google_.url()));
-  EXPECT_EQ(0U, this->GetCookieListWithOptions(cs, this->ftp_google_.url(),
+                         this->GetCookies(cs, this->ftp_foo_.url()));
+  EXPECT_EQ(0U, this->GetCookieListWithOptions(cs, this->ftp_foo_.url(),
                                                CookieOptions())
                     .size());
 }
 
 TYPED_TEST_P(CookieStoreTest, PathTest) {
   CookieStore* cs = this->GetCookieStore();
-  std::string url("http://www.google.izzle");
+  std::string url("http://www.foo.com");
   EXPECT_TRUE(this->SetCookie(cs, GURL(url), "A=B; path=/wee"));
   this->MatchCookieLines("A=B", this->GetCookies(cs, GURL(url + "/wee")));
   this->MatchCookieLines("A=B", this->GetCookies(cs, GURL(url + "/wee/")));
@@ -951,133 +949,129 @@
   options.set_include_httponly();
 
   // Create a httponly cookie.
-  EXPECT_TRUE(this->SetCookieWithOptions(cs, this->http_www_google_.url(),
+  EXPECT_TRUE(this->SetCookieWithOptions(cs, this->http_www_foo_.url(),
                                          "A=B; httponly", options));
 
   // Check httponly read protection.
   this->MatchCookieLines(std::string(),
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
   this->MatchCookieLines("A=B", this->GetCookiesWithOptions(
-                                    cs, this->http_www_google_.url(), options));
+                                    cs, this->http_www_foo_.url(), options));
 
   // Check httponly overwrite protection.
-  EXPECT_FALSE(this->SetCookie(cs, this->http_www_google_.url(), "A=C"));
+  EXPECT_FALSE(this->SetCookie(cs, this->http_www_foo_.url(), "A=C"));
   this->MatchCookieLines(std::string(),
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
   this->MatchCookieLines("A=B", this->GetCookiesWithOptions(
-                                    cs, this->http_www_google_.url(), options));
-  EXPECT_TRUE(this->SetCookieWithOptions(cs, this->http_www_google_.url(),
-                                         "A=C", options));
+                                    cs, this->http_www_foo_.url(), options));
+  EXPECT_TRUE(this->SetCookieWithOptions(cs, this->http_www_foo_.url(), "A=C",
+                                         options));
   this->MatchCookieLines("A=C",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
 
   // Check httponly create protection.
-  EXPECT_FALSE(
-      this->SetCookie(cs, this->http_www_google_.url(), "B=A; httponly"));
+  EXPECT_FALSE(this->SetCookie(cs, this->http_www_foo_.url(), "B=A; httponly"));
   this->MatchCookieLines("A=C", this->GetCookiesWithOptions(
-                                    cs, this->http_www_google_.url(), options));
-  EXPECT_TRUE(this->SetCookieWithOptions(cs, this->http_www_google_.url(),
+                                    cs, this->http_www_foo_.url(), options));
+  EXPECT_TRUE(this->SetCookieWithOptions(cs, this->http_www_foo_.url(),
                                          "B=A; httponly", options));
   this->MatchCookieLines(
       "A=C; B=A",
-      this->GetCookiesWithOptions(cs, this->http_www_google_.url(), options));
+      this->GetCookiesWithOptions(cs, this->http_www_foo_.url(), options));
   this->MatchCookieLines("A=C",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
 }
 
 TYPED_TEST_P(CookieStoreTest, TestCookieDeletion) {
   CookieStore* cs = this->GetCookieStore();
 
   // Create a session cookie.
-  EXPECT_TRUE(
-      this->SetCookie(cs, this->http_www_google_.url(), kValidCookieLine));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), kValidCookieLine));
   this->MatchCookieLines("A=B",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
   // Delete it via Max-Age.
-  EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
                               std::string(kValidCookieLine) + "; max-age=0"));
-  this->MatchCookieLineWithTimeout(cs, this->http_www_google_.url(),
+  this->MatchCookieLineWithTimeout(cs, this->http_www_foo_.url(),
                                    std::string());
 
   // Create a session cookie.
-  EXPECT_TRUE(
-      this->SetCookie(cs, this->http_www_google_.url(), kValidCookieLine));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), kValidCookieLine));
   this->MatchCookieLines("A=B",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
   // Delete it via Expires.
-  EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
                               std::string(kValidCookieLine) +
                                   "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
   this->MatchCookieLines(std::string(),
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
 
   // Create a persistent cookie.
   EXPECT_TRUE(this->SetCookie(
-      cs, this->http_www_google_.url(),
+      cs, this->http_www_foo_.url(),
       std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
 
   this->MatchCookieLines("A=B",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
   // Delete it via Max-Age.
-  EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
                               std::string(kValidCookieLine) + "; max-age=0"));
-  this->MatchCookieLineWithTimeout(cs, this->http_www_google_.url(),
+  this->MatchCookieLineWithTimeout(cs, this->http_www_foo_.url(),
                                    std::string());
 
   // Create a persistent cookie.
   EXPECT_TRUE(this->SetCookie(
-      cs, this->http_www_google_.url(),
+      cs, this->http_www_foo_.url(),
       std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
   this->MatchCookieLines("A=B",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
   // Delete it via Expires.
-  EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
                               std::string(kValidCookieLine) +
                                   "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
   this->MatchCookieLines(std::string(),
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
 
   // Create a persistent cookie.
   EXPECT_TRUE(this->SetCookie(
-      cs, this->http_www_google_.url(),
+      cs, this->http_www_foo_.url(),
       std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
   this->MatchCookieLines("A=B",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
   // Check that it is not deleted with significant enough clock skew.
   base::Time server_time;
   EXPECT_TRUE(base::Time::FromString("Sun, 17-Apr-1977 22:50:13 GMT",
                                      &server_time));
   EXPECT_TRUE(this->SetCookieWithServerTime(
-      cs, this->http_www_google_.url(),
+      cs, this->http_www_foo_.url(),
       std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-1977 22:50:13 GMT",
       server_time));
   this->MatchCookieLines("A=B",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
 
   // Create a persistent cookie.
   EXPECT_TRUE(this->SetCookie(
-      cs, this->http_www_google_.url(),
+      cs, this->http_www_foo_.url(),
       std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
   this->MatchCookieLines("A=B",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
   // Delete it via Expires, with a unix epoch of 0.
-  EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
                               std::string(kValidCookieLine) +
                                   "; expires=Thu, 1-Jan-1970 00:00:00 GMT"));
   this->MatchCookieLines(std::string(),
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
 }
 
 TYPED_TEST_P(CookieStoreTest, TestDeleteAll) {
   CookieStore* cs = this->GetCookieStore();
 
   // Set a session cookie.
-  EXPECT_TRUE(
-      this->SetCookie(cs, this->http_www_google_.url(), kValidCookieLine));
-  EXPECT_EQ("A=B", this->GetCookies(cs, this->http_www_google_.url()));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), kValidCookieLine));
+  EXPECT_EQ("A=B", this->GetCookies(cs, this->http_www_foo_.url()));
 
   // Set a persistent cookie.
-  EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
                               "C=D; expires=Mon, 18-Apr-22 22:50:13 GMT"));
 
   EXPECT_EQ(2u, this->GetAllCookies(cs).size());
@@ -1099,35 +1093,35 @@
                                 base::TimeDelta::FromDays(30);
 
   // Add a cookie.
-  EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "A=B"));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
   // Check that the cookie is in the store.
   this->MatchCookieLines("A=B",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
 
   // Remove cookies in empty intervals.
   EXPECT_EQ(0, this->DeleteCreatedBetween(cs, last_month, last_minute));
   EXPECT_EQ(0, this->DeleteCreatedBetween(cs, next_minute, next_month));
   // Check that the cookie is still there.
   this->MatchCookieLines("A=B",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
 
   // Remove the cookie with an interval defined by two dates.
   EXPECT_EQ(1, this->DeleteCreatedBetween(cs, last_minute, next_minute));
   // Check that the cookie disappeared.
   this->MatchCookieLines(std::string(),
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
 
   // Add another cookie.
-  EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "C=D"));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
   // Check that the cookie is in the store.
   this->MatchCookieLines("C=D",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
 
   // Remove the cookie with a null ending time.
   EXPECT_EQ(1, this->DeleteCreatedBetween(cs, last_minute, base::Time()));
   // Check that the cookie disappeared.
   this->MatchCookieLines(std::string(),
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
 }
 
 namespace {
@@ -1145,10 +1139,10 @@
   std::string desired_value("B");
 
   // These 3 cookies match the time range and host.
-  EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "A=B"));
-  EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "C=D"));
-  EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "Y=Z"));
-  EXPECT_TRUE(this->SetCookie(cs, this->https_www_google_.url(), "E=B"));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "C=D"));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "Y=Z"));
+  EXPECT_TRUE(this->SetCookie(cs, this->https_www_foo_.url(), "E=B"));
 
   // Delete cookies.
   EXPECT_EQ(2,  // Deletes A=B, E=B
@@ -1158,7 +1152,7 @@
 
   // Check that we deleted the right ones.
   this->MatchCookieLines("C=D;Y=Z",
-                         this->GetCookies(cs, this->https_www_google_.url()));
+                         this->GetCookies(cs, this->https_www_foo_.url()));
 
   // Now check that using a null predicate will do nothing.
   EXPECT_EQ(0, this->DeleteAllCreatedBetweenWithPredicate(
@@ -1170,50 +1164,48 @@
                    cs, last_month, last_minute,
                    base::Bind(&CookieHasValue, desired_value)));
   this->MatchCookieLines("C=D;Y=Z",
-                         this->GetCookies(cs, this->https_www_google_.url()));
+                         this->GetCookies(cs, this->https_www_foo_.url()));
   // Same thing, but with a good time range.
   EXPECT_EQ(1, this->DeleteAllCreatedBetweenWithPredicate(
                    cs, now, base::Time::Max(),
                    base::Bind(&CookieHasValue, desired_value)));
   this->MatchCookieLines("Y=Z",
-                         this->GetCookies(cs, this->https_www_google_.url()));
+                         this->GetCookies(cs, this->https_www_foo_.url()));
 }
 
 TYPED_TEST_P(CookieStoreTest, TestSecure) {
   CookieStore* cs = this->GetCookieStore();
 
-  EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "A=B"));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B"));
   this->MatchCookieLines("A=B",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
   this->MatchCookieLines("A=B",
-                         this->GetCookies(cs, this->https_www_google_.url()));
+                         this->GetCookies(cs, this->https_www_foo_.url()));
 
-  EXPECT_TRUE(
-      this->SetCookie(cs, this->https_www_google_.url(), "A=B; secure"));
+  EXPECT_TRUE(this->SetCookie(cs, this->https_www_foo_.url(), "A=B; secure"));
   // The secure should overwrite the non-secure.
   this->MatchCookieLines(std::string(),
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
   this->MatchCookieLines("A=B",
-                         this->GetCookies(cs, this->https_www_google_.url()));
+                         this->GetCookies(cs, this->https_www_foo_.url()));
 
-  EXPECT_TRUE(
-      this->SetCookie(cs, this->https_www_google_.url(), "D=E; secure"));
+  EXPECT_TRUE(this->SetCookie(cs, this->https_www_foo_.url(), "D=E; secure"));
   this->MatchCookieLines(std::string(),
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
   this->MatchCookieLines("A=B; D=E",
-                         this->GetCookies(cs, this->https_www_google_.url()));
+                         this->GetCookies(cs, this->https_www_foo_.url()));
 
-  EXPECT_TRUE(this->SetCookie(cs, this->https_www_google_.url(), "A=B"));
+  EXPECT_TRUE(this->SetCookie(cs, this->https_www_foo_.url(), "A=B"));
   // The non-secure should overwrite the secure.
   this->MatchCookieLines("A=B",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
   this->MatchCookieLines("D=E; A=B",
-                         this->GetCookies(cs, this->https_www_google_.url()));
+                         this->GetCookies(cs, this->https_www_foo_.url()));
 }
 
 // Formerly NetUtilTest.CookieTest back when we used wininet's cookie handling.
 TYPED_TEST_P(CookieStoreTest, NetUtilCookieTest) {
-  const GURL test_url("http://mojo.jojo.google.izzle/");
+  const GURL test_url("http://mojo.jojo.foo.com/");
 
   CookieStore* cs = this->GetCookieStore();
 
@@ -1232,17 +1224,17 @@
 }
 
 TYPED_TEST_P(CookieStoreTest, OverwritePersistentCookie) {
-  GURL url_google("http://www.google.com/");
+  GURL url_foo("http://www.foo.com/");
   GURL url_chromium("http://chromium.org");
   CookieStore* cs = this->GetCookieStore();
 
   // Insert a cookie "a" for path "/path1"
-  EXPECT_TRUE(this->SetCookie(cs, url_google,
+  EXPECT_TRUE(this->SetCookie(cs, url_foo,
                               "a=val1; path=/path1; "
                               "expires=Mon, 18-Apr-22 22:50:13 GMT"));
 
   // Insert a cookie "b" for path "/path1"
-  EXPECT_TRUE(this->SetCookie(cs, url_google,
+  EXPECT_TRUE(this->SetCookie(cs, url_foo,
                               "b=val1; path=/path1; "
                               "expires=Mon, 18-Apr-22 22:50:14 GMT"));
 
@@ -1250,19 +1242,19 @@
   // overwrite the non-http-only version.
   CookieOptions allow_httponly;
   allow_httponly.set_include_httponly();
-  EXPECT_TRUE(this->SetCookieWithOptions(cs, url_google,
+  EXPECT_TRUE(this->SetCookieWithOptions(cs, url_foo,
                                          "b=val2; path=/path1; httponly; "
                                          "expires=Mon, 18-Apr-22 22:50:14 GMT",
                                          allow_httponly));
 
   // Insert a cookie "a" for path "/path1". This should overwrite.
-  EXPECT_TRUE(this->SetCookie(cs, url_google,
+  EXPECT_TRUE(this->SetCookie(cs, url_foo,
                               "a=val33; path=/path1; "
                               "expires=Mon, 18-Apr-22 22:50:14 GMT"));
 
   // Insert a cookie "a" for path "/path2". This should NOT overwrite
   // cookie "a", since the path is different.
-  EXPECT_TRUE(this->SetCookie(cs, url_google,
+  EXPECT_TRUE(this->SetCookie(cs, url_foo,
                               "a=val9; path=/path2; "
                               "expires=Mon, 18-Apr-22 22:50:14 GMT"));
 
@@ -1275,14 +1267,14 @@
 
   if (TypeParam::supports_http_only) {
     this->MatchCookieLines(
-        "a=val33", this->GetCookies(cs, GURL("http://www.google.com/path1")));
+        "a=val33", this->GetCookies(cs, GURL("http://www.foo.com/path1")));
   } else {
     this->MatchCookieLines(
         "a=val33; b=val2",
-        this->GetCookies(cs, GURL("http://www.google.com/path1")));
+        this->GetCookies(cs, GURL("http://www.foo.com/path1")));
   }
   this->MatchCookieLines(
-      "a=val9", this->GetCookies(cs, GURL("http://www.google.com/path2")));
+      "a=val9", this->GetCookies(cs, GURL("http://www.foo.com/path2")));
   this->MatchCookieLines(
       "a=val99", this->GetCookies(cs, GURL("http://chromium.org/path1")));
 }
@@ -1293,29 +1285,27 @@
   // Cookies should be sorted by path length and creation time, as per RFC6265.
   CookieStore* cs = this->GetCookieStore();
   EXPECT_TRUE(
-      this->SetCookie(cs, GURL("http://d.c.b.a.google.com/aa/x.html"), "c=1"));
-  EXPECT_TRUE(this->SetCookie(cs, GURL("http://b.a.google.com/aa/bb/cc/x.html"),
-                              "d=1; domain=b.a.google.com"));
+      this->SetCookie(cs, GURL("http://d.c.b.a.foo.com/aa/x.html"), "c=1"));
+  EXPECT_TRUE(this->SetCookie(cs, GURL("http://b.a.foo.com/aa/bb/cc/x.html"),
+                              "d=1; domain=b.a.foo.com"));
   base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
       TypeParam::creation_time_granularity_in_ms));
-  EXPECT_TRUE(this->SetCookie(cs, GURL("http://b.a.google.com/aa/bb/cc/x.html"),
-                              "a=4; domain=b.a.google.com"));
+  EXPECT_TRUE(this->SetCookie(cs, GURL("http://b.a.foo.com/aa/bb/cc/x.html"),
+                              "a=4; domain=b.a.foo.com"));
   base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
       TypeParam::creation_time_granularity_in_ms));
-  EXPECT_TRUE(this->SetCookie(cs,
-                              GURL("http://c.b.a.google.com/aa/bb/cc/x.html"),
-                              "e=1; domain=c.b.a.google.com"));
-  EXPECT_TRUE(this->SetCookie(
-      cs, GURL("http://d.c.b.a.google.com/aa/bb/x.html"), "b=1"));
+  EXPECT_TRUE(this->SetCookie(cs, GURL("http://c.b.a.foo.com/aa/bb/cc/x.html"),
+                              "e=1; domain=c.b.a.foo.com"));
+  EXPECT_TRUE(
+      this->SetCookie(cs, GURL("http://d.c.b.a.foo.com/aa/bb/x.html"), "b=1"));
   EXPECT_TRUE(this->SetCookie(cs, GURL("http://news.bbc.co.uk/midpath/x.html"),
                               "g=10"));
-  EXPECT_EQ(
-      "d=1; a=4; e=1; b=1; c=1",
-      this->GetCookies(cs, GURL("http://d.c.b.a.google.com/aa/bb/cc/dd")));
+  EXPECT_EQ("d=1; a=4; e=1; b=1; c=1",
+            this->GetCookies(cs, GURL("http://d.c.b.a.foo.com/aa/bb/cc/dd")));
 
   CookieOptions options;
   CookieList cookies = this->GetCookieListWithOptions(
-      cs, GURL("http://d.c.b.a.google.com/aa/bb/cc/dd"), options);
+      cs, GURL("http://d.c.b.a.foo.com/aa/bb/cc/dd"), options);
   CookieList::const_iterator it = cookies.begin();
 
   ASSERT_TRUE(it != cookies.end());
@@ -1341,9 +1331,8 @@
 TYPED_TEST_P(CookieStoreTest, GetAllCookiesAsync) {
   CookieStore* cs = this->GetCookieStore();
 
-  EXPECT_TRUE(
-      this->SetCookie(cs, this->http_www_google_.url(), "A=B; path=/a"));
-  EXPECT_TRUE(this->SetCookie(cs, this->http_foo_com_.url(), "C=D;/"));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B; path=/a"));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_baz_com_.url(), "C=D;/"));
   EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "E=F; path=/bar"));
 
   // Check cookies for url.
@@ -1357,13 +1346,13 @@
   EXPECT_EQ("F", it->Value());
 
   ASSERT_TRUE(++it != cookies.end());
-  EXPECT_EQ(this->http_www_google_.host(), it->Domain());
+  EXPECT_EQ(this->http_www_foo_.host(), it->Domain());
   EXPECT_EQ("/a", it->Path());
   EXPECT_EQ("A", it->Name());
   EXPECT_EQ("B", it->Value());
 
   ASSERT_TRUE(++it != cookies.end());
-  EXPECT_EQ(this->http_foo_com_.host(), it->Domain());
+  EXPECT_EQ(this->http_baz_com_.host(), it->Domain());
   EXPECT_EQ("/", it->Path());
   EXPECT_EQ("C", it->Name());
   EXPECT_EQ("D", it->Value());
@@ -1374,20 +1363,18 @@
 TYPED_TEST_P(CookieStoreTest, DeleteCookieAsync) {
   CookieStore* cs = this->GetCookieStore();
 
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=A1; path=/"));
   EXPECT_TRUE(
-      this->SetCookie(cs, this->http_www_google_.url(), "A=A1; path=/"));
+      this->SetCookie(cs, this->http_www_foo_.url(), "A=A2; path=/foo"));
   EXPECT_TRUE(
-      this->SetCookie(cs, this->http_www_google_.url(), "A=A2; path=/foo"));
+      this->SetCookie(cs, this->http_www_foo_.url(), "A=A3; path=/bar"));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "B=B1; path=/"));
   EXPECT_TRUE(
-      this->SetCookie(cs, this->http_www_google_.url(), "A=A3; path=/bar"));
+      this->SetCookie(cs, this->http_www_foo_.url(), "B=B2; path=/foo"));
   EXPECT_TRUE(
-      this->SetCookie(cs, this->http_www_google_.url(), "B=B1; path=/"));
-  EXPECT_TRUE(
-      this->SetCookie(cs, this->http_www_google_.url(), "B=B2; path=/foo"));
-  EXPECT_TRUE(
-      this->SetCookie(cs, this->http_www_google_.url(), "B=B3; path=/bar"));
+      this->SetCookie(cs, this->http_www_foo_.url(), "B=B3; path=/bar"));
 
-  this->DeleteCookie(cs, this->http_www_google_.AppendPath("foo/bar"), "A");
+  this->DeleteCookie(cs, this->http_www_foo_.AppendPath("foo/bar"), "A");
 
   CookieList cookies = this->GetAllCookies(cs);
   size_t expected_size = 4;
@@ -1402,60 +1389,57 @@
   CookieStore* cs = this->GetCookieStore();
 
   // Set two cookies with the same name, and make sure both are set.
-  EXPECT_TRUE(
-      this->SetCookie(cs, this->http_www_google_.url(), "A=B;Path=/foo"));
-  EXPECT_TRUE(
-      this->SetCookie(cs, this->http_www_google_.url(), "A=C;Path=/bar"));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=B;Path=/foo"));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=C;Path=/bar"));
   EXPECT_EQ(2u, this->GetAllCookies(cs).size());
-  EXPECT_EQ("A=B", this->GetCookies(cs, this->www_google_foo_.url()));
-  EXPECT_EQ("A=C", this->GetCookies(cs, this->www_google_bar_.url()));
+  EXPECT_EQ("A=B", this->GetCookies(cs, this->www_foo_foo_.url()));
+  EXPECT_EQ("A=C", this->GetCookies(cs, this->www_foo_bar_.url()));
 
   // Delete the "/foo" cookie, and make sure only it was deleted.
   CookieList cookies = this->GetCookieListWithOptions(
-      cs, this->www_google_foo_.url(), CookieOptions());
+      cs, this->www_foo_foo_.url(), CookieOptions());
   ASSERT_EQ(1u, cookies.size());
   EXPECT_EQ(1, this->DeleteCanonicalCookie(cs, cookies[0]));
   EXPECT_EQ(1u, this->GetAllCookies(cs).size());
-  EXPECT_EQ("", this->GetCookies(cs, this->www_google_foo_.url()));
-  EXPECT_EQ("A=C", this->GetCookies(cs, this->www_google_bar_.url()));
+  EXPECT_EQ("", this->GetCookies(cs, this->www_foo_foo_.url()));
+  EXPECT_EQ("A=C", this->GetCookies(cs, this->www_foo_bar_.url()));
 
   // Deleting the "/foo" cookie again should fail.
   EXPECT_EQ(0, this->DeleteCanonicalCookie(cs, cookies[0]));
 
   // Try to delete the "/bar" cookie after overwriting it with a new cookie.
-  cookies = this->GetCookieListWithOptions(cs, this->www_google_bar_.url(),
+  cookies = this->GetCookieListWithOptions(cs, this->www_foo_bar_.url(),
                                            CookieOptions());
   ASSERT_EQ(1u, cookies.size());
-  EXPECT_TRUE(
-      this->SetCookie(cs, this->http_www_google_.url(), "A=D;Path=/bar"));
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), "A=D;Path=/bar"));
   EXPECT_EQ(0, this->DeleteCanonicalCookie(cs, cookies[0]));
   EXPECT_EQ(1u, this->GetAllCookies(cs).size());
-  EXPECT_EQ("A=D", this->GetCookies(cs, this->www_google_bar_.url()));
+  EXPECT_EQ("A=D", this->GetCookies(cs, this->www_foo_bar_.url()));
 
   // Delete the new "/bar" cookie.
-  cookies = this->GetCookieListWithOptions(cs, this->www_google_bar_.url(),
+  cookies = this->GetCookieListWithOptions(cs, this->www_foo_bar_.url(),
                                            CookieOptions());
   ASSERT_EQ(1u, cookies.size());
   EXPECT_EQ(1, this->DeleteCanonicalCookie(cs, cookies[0]));
   EXPECT_EQ(0u, this->GetAllCookies(cs).size());
-  EXPECT_EQ("", this->GetCookies(cs, this->www_google_bar_.url()));
+  EXPECT_EQ("", this->GetCookies(cs, this->www_foo_bar_.url()));
 }
 
 TYPED_TEST_P(CookieStoreTest, DeleteSessionCookie) {
   CookieStore* cs = this->GetCookieStore();
   // Create a session cookie and a persistent cookie.
-  EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
+  EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(),
                               std::string(kValidCookieLine)));
   EXPECT_TRUE(this->SetCookie(
-      cs, this->http_www_google_.url(),
-      this->http_www_google_.Format("C=D; path=/; domain=%D;"
-                                    "expires=Mon, 18-Apr-22 22:50:13 GMT")));
+      cs, this->http_www_foo_.url(),
+      this->http_www_foo_.Format("C=D; path=/; domain=%D;"
+                                 "expires=Mon, 18-Apr-22 22:50:13 GMT")));
   this->MatchCookieLines("A=B; C=D",
-                         this->GetCookies(cs, this->http_www_google_.url()));
+                         this->GetCookies(cs, this->http_www_foo_.url()));
   // Delete the session cookie.
   this->DeleteSessionCookies(cs);
   // Check that the session cookie has been deleted but not the persistent one.
-  EXPECT_EQ("C=D", this->GetCookies(cs, this->http_www_google_.url()));
+  EXPECT_EQ("C=D", this->GetCookies(cs, this->http_www_foo_.url()));
 }
 
 REGISTER_TYPED_TEST_CASE_P(CookieStoreTest,
diff --git a/net/cookies/cookie_util_unittest.cc b/net/cookies/cookie_util_unittest.cc
index 384527a0..d261ec7 100644
--- a/net/cookies/cookie_util_unittest.cc
+++ b/net/cookies/cookie_util_unittest.cc
@@ -45,11 +45,7 @@
   const struct {
     const char* str;
     const bool is_host_only;
-  } tests[] = {
-    { "",               true },
-    { "www.google.com", true },
-    { ".google.com",    false }
-  };
+  } tests[] = {{"", true}, {"www.foo.com", true}, {".foo.com", false}};
 
   for (size_t i = 0; i < arraysize(tests); ++i) {
     EXPECT_EQ(tests[i].is_host_only,
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index 4851b2f..85a19f4 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -210,8 +210,7 @@
       cookie_store_set_by_client_(false),
       net_log_(nullptr),
       pac_quick_check_enabled_(true),
-      pac_sanitize_url_policy_(ProxyService::SanitizeUrlPolicy::SAFE),
-      socket_performance_watcher_factory_(nullptr) {
+      pac_sanitize_url_policy_(ProxyService::SanitizeUrlPolicy::SAFE) {
 }
 
 URLRequestContextBuilder::~URLRequestContextBuilder() {}
@@ -236,6 +235,11 @@
   session_context->channel_id_service = request_context->channel_id_service();
   session_context->network_quality_provider =
       request_context->network_quality_estimator();
+  if (request_context->network_quality_estimator()) {
+    session_context->socket_performance_watcher_factory =
+        request_context->network_quality_estimator()
+            ->GetSocketPerformanceWatcherFactory();
+  }
 }
 
 void URLRequestContextBuilder::EnableHttpCache(const HttpCacheParams& params) {
@@ -424,11 +428,6 @@
     network_session_context.proxy_delegate = proxy_delegate_.get();
     storage->set_proxy_delegate(std::move(proxy_delegate_));
   }
-  if (socket_performance_watcher_factory_) {
-    network_session_context.socket_performance_watcher_factory =
-        socket_performance_watcher_factory_;
-    DCHECK(network_session_context.network_quality_provider);
-  }
 
   storage->set_http_network_session(base::MakeUnique<HttpNetworkSession>(
       http_network_session_params_, network_session_context));
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h
index a67f6aa8..c37eb21e 100644
--- a/net/url_request/url_request_context_builder.h
+++ b/net/url_request/url_request_context_builder.h
@@ -53,7 +53,6 @@
 class HttpServerProperties;
 class NetworkQualityEstimator;
 class ProxyConfigService;
-class SocketPerformanceWatcherFactory;
 class URLRequestContext;
 class URLRequestInterceptor;
 
@@ -278,11 +277,6 @@
     throttling_enabled_ = throttling_enabled;
   }
 
-  void set_socket_performance_watcher_factory(
-      SocketPerformanceWatcherFactory* socket_performance_watcher_factory) {
-    socket_performance_watcher_factory_ = socket_performance_watcher_factory;
-  }
-
   void set_ct_verifier(std::unique_ptr<CTVerifier> ct_verifier);
 
   void SetCertVerifier(std::unique_ptr<CertVerifier> cert_verifier);
@@ -376,10 +370,6 @@
   std::unique_ptr<HttpServerProperties> http_server_properties_;
   std::map<std::string, std::unique_ptr<URLRequestJobFactory::ProtocolHandler>>
       protocol_handlers_;
-  // SocketPerformanceWatcherFactory to be used by this context builder.
-  // Not owned by the context builder. Once it is set to a non-null value, it
-  // is guaranteed to be non-null during the lifetime of |this|.
-  SocketPerformanceWatcherFactory* socket_performance_watcher_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(URLRequestContextBuilder);
 };
diff --git a/remoting/host/input_injector_win.cc b/remoting/host/input_injector_win.cc
index 8f2b7fa1..b7d31bb 100644
--- a/remoting/host/input_injector_win.cc
+++ b/remoting/host/input_injector_win.cc
@@ -354,7 +354,7 @@
   if (scancode == ui::KeycodeConverter::InvalidNativeKeycode())
     return;
 
-  if (event.has_lock_states() && !IsLockKey(scancode)) {
+  if (event.has_lock_states() && event.pressed() && !IsLockKey(scancode)) {
     SetLockStates(event.lock_states());
   }
 
diff --git a/remoting/host/input_injector_x11.cc b/remoting/host/input_injector_x11.cc
index df871ca..71b501b5 100644
--- a/remoting/host/input_injector_x11.cc
+++ b/remoting/host/input_injector_x11.cc
@@ -122,6 +122,9 @@
     // Enables or disables keyboard auto-repeat globally.
     void SetAutoRepeatEnabled(bool enabled);
 
+    // Check if the given scan code is caps lock or num lock.
+    bool IsLockKey(KeyCode keycode);
+
     // Sets the keyboard lock states to those provided.
     void SetLockStates(uint32_t states);
 
@@ -280,7 +283,7 @@
       XTestFakeKeyEvent(display_, keycode, False, CurrentTime);
     }
 
-    if (event.has_lock_states()) {
+    if (event.has_lock_states() && !IsLockKey(keycode)) {
       SetLockStates(event.lock_states());
     }
 
@@ -355,6 +358,18 @@
   XChangeKeyboardControl(display_, KBAutoRepeatMode, &control);
 }
 
+bool InputInjectorX11::Core::IsLockKey(KeyCode keycode) {
+  XkbStateRec state;
+  KeySym keysym;
+  if (XkbGetState(display_, XkbUseCoreKbd, &state) == Success &&
+      XkbLookupKeySym(display_, keycode, XkbStateMods(&state), nullptr,
+                      &keysym) == True) {
+    return keysym == XK_Caps_Lock || keysym == XK_Num_Lock;
+  } else {
+    return false;
+  }
+}
+
 void InputInjectorX11::Core::SetLockStates(uint32_t states) {
   unsigned int caps_lock_mask = XkbKeysymToModifiers(display_, XK_Caps_Lock);
   unsigned int num_lock_mask = XkbKeysymToModifiers(display_, XK_Num_Lock);
diff --git a/services/preferences/persistent_pref_store_impl.cc b/services/preferences/persistent_pref_store_impl.cc
index 3054526..8df4fe6 100644
--- a/services/preferences/persistent_pref_store_impl.cc
+++ b/services/preferences/persistent_pref_store_impl.cc
@@ -129,7 +129,9 @@
     observer_->OnPrefsChanged(std::move(updates));
   }
 
-  void CommitPendingWrite() override { pref_store_->CommitPendingWrite(); }
+  void CommitPendingWrite(CommitPendingWriteCallback done_callback) override {
+    pref_store_->CommitPendingWrite(std::move(done_callback));
+  }
   void SchedulePendingLossyWrites() override {
     pref_store_->SchedulePendingLossyWrites();
   }
@@ -248,8 +250,9 @@
   return backing_pref_store_->GetValue(key, value);
 }
 
-void PersistentPrefStoreImpl::CommitPendingWrite() {
-  backing_pref_store_->CommitPendingWrite();
+void PersistentPrefStoreImpl::CommitPendingWrite(
+    base::OnceClosure done_callback) {
+  backing_pref_store_->CommitPendingWrite(std::move(done_callback));
 }
 
 void PersistentPrefStoreImpl::SchedulePendingLossyWrites() {
diff --git a/services/preferences/persistent_pref_store_impl.h b/services/preferences/persistent_pref_store_impl.h
index f2e73d2..6c3ec98 100644
--- a/services/preferences/persistent_pref_store_impl.h
+++ b/services/preferences/persistent_pref_store_impl.h
@@ -10,6 +10,7 @@
 #include <unordered_map>
 #include <vector>
 
+#include "base/callback.h"
 #include "base/macros.h"
 #include "services/preferences/public/interfaces/preferences.mojom.h"
 #include "services/preferences/public/interfaces/tracked_preference_validation_delegate.mojom.h"
@@ -39,7 +40,7 @@
   void SetValues(std::vector<mojom::PrefUpdatePtr> updates);
   bool GetValue(const std::string& key, const base::Value** value) const;
 
-  void CommitPendingWrite();
+  void CommitPendingWrite(base::OnceClosure done_callback);
   void SchedulePendingLossyWrites();
   void ClearMutableValues();
 
diff --git a/services/preferences/persistent_pref_store_impl_unittest.cc b/services/preferences/persistent_pref_store_impl_unittest.cc
index c8fac3a..1c4e0b3 100644
--- a/services/preferences/persistent_pref_store_impl_unittest.cc
+++ b/services/preferences/persistent_pref_store_impl_unittest.cc
@@ -32,7 +32,12 @@
 
 class PersistentPrefStoreMock : public InMemoryPrefStore {
  public:
-  MOCK_METHOD0(CommitPendingWrite, void());
+  void CommitPendingWrite(base::OnceClosure callback) override {
+    CommitPendingWriteMock();
+    InMemoryPrefStore::CommitPendingWrite(std::move(callback));
+  }
+
+  MOCK_METHOD0(CommitPendingWriteMock, void());
   MOCK_METHOD0(SchedulePendingLossyWrites, void());
   MOCK_METHOD0(ClearMutableValues, void());
 
@@ -303,10 +308,8 @@
   auto backing_store = make_scoped_refptr(new PersistentPrefStoreMock);
   CreateImpl(backing_store);
   base::RunLoop run_loop;
-  EXPECT_CALL(*backing_store, CommitPendingWrite())
-      .Times(2)
-      .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
-  pref_store()->CommitPendingWrite();
+  EXPECT_CALL(*backing_store, CommitPendingWriteMock()).Times(2);
+  pref_store()->CommitPendingWrite(run_loop.QuitClosure());
   run_loop.Run();
 }
 
@@ -316,7 +319,7 @@
   base::RunLoop run_loop;
   EXPECT_CALL(*backing_store, SchedulePendingLossyWrites())
       .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
-  EXPECT_CALL(*backing_store, CommitPendingWrite()).Times(1);
+  EXPECT_CALL(*backing_store, CommitPendingWriteMock()).Times(1);
   pref_store()->SchedulePendingLossyWrites();
   run_loop.Run();
 }
@@ -327,7 +330,7 @@
   base::RunLoop run_loop;
   EXPECT_CALL(*backing_store, ClearMutableValues())
       .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
-  EXPECT_CALL(*backing_store, CommitPendingWrite()).Times(1);
+  EXPECT_CALL(*backing_store, CommitPendingWriteMock()).Times(1);
   pref_store()->ClearMutableValues();
   run_loop.Run();
 }
diff --git a/services/preferences/pref_store_consistency_unittest.cc b/services/preferences/pref_store_consistency_unittest.cc
index ef53f4c0..ade786d 100644
--- a/services/preferences/pref_store_consistency_unittest.cc
+++ b/services/preferences/pref_store_consistency_unittest.cc
@@ -153,7 +153,7 @@
       std::move(stop_).Run();
     }
   }
-  void CommitPendingWrite() override {}
+  void CommitPendingWrite(base::OnceClosure) override {}
   void SchedulePendingLossyWrites() override {}
   void ClearMutableValues() override {}
 
diff --git a/services/preferences/public/cpp/persistent_pref_store_client.cc b/services/preferences/public/cpp/persistent_pref_store_client.cc
index 69d3c8cc..e13d1c9 100644
--- a/services/preferences/public/cpp/persistent_pref_store_client.cc
+++ b/services/preferences/public/cpp/persistent_pref_store_client.cc
@@ -249,11 +249,12 @@
   pref_registry_ = nullptr;
 }
 
-void PersistentPrefStoreClient::CommitPendingWrite() {
+void PersistentPrefStoreClient::CommitPendingWrite(
+    base::OnceClosure done_callback) {
   DCHECK(pref_store_);
   if (!pending_writes_.empty())
     FlushPendingWrites();
-  pref_store_->CommitPendingWrite();
+  pref_store_->CommitPendingWrite(std::move(done_callback));
 }
 
 void PersistentPrefStoreClient::SchedulePendingLossyWrites() {
@@ -270,7 +271,7 @@
   if (!pref_store_)
     return;
 
-  CommitPendingWrite();
+  CommitPendingWrite(base::OnceClosure());
 }
 
 void PersistentPrefStoreClient::OnConnect(
diff --git a/services/preferences/public/cpp/persistent_pref_store_client.h b/services/preferences/public/cpp/persistent_pref_store_client.h
index b6edff0d..9cee6fd 100644
--- a/services/preferences/public/cpp/persistent_pref_store_client.h
+++ b/services/preferences/public/cpp/persistent_pref_store_client.h
@@ -60,7 +60,7 @@
   PrefReadError GetReadError() const override;
   PrefReadError ReadPrefs() override;
   void ReadPrefsAsync(ReadErrorDelegate* error_delegate) override;
-  void CommitPendingWrite() override;
+  void CommitPendingWrite(base::OnceClosure done_callback) override;
   void SchedulePendingLossyWrites() override;
   void ClearMutableValues() override;
 
diff --git a/services/preferences/public/cpp/tests/persistent_pref_store_client_unittest.cc b/services/preferences/public/cpp/tests/persistent_pref_store_client_unittest.cc
index 0ff2499b..c8360989 100644
--- a/services/preferences/public/cpp/tests/persistent_pref_store_client_unittest.cc
+++ b/services/preferences/public/cpp/tests/persistent_pref_store_client_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "base/values.h"
 #include "components/prefs/pref_notifier_impl.h"
 #include "components/prefs/pref_registry_simple.h"
@@ -90,7 +91,12 @@
 
   void RequestValue(const std::string& key,
                     const std::vector<std::string>& path) override {}
-  void CommitPendingWrite() override {}
+
+  void CommitPendingWrite(CommitPendingWriteCallback callback) override {
+    base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                     std::move(callback));
+  }
+
   void SchedulePendingLossyWrites() override {}
   void ClearMutableValues() override {}
 
diff --git a/services/preferences/public/interfaces/preferences.mojom b/services/preferences/public/interfaces/preferences.mojom
index 19fe94e4..2e60d86c 100644
--- a/services/preferences/public/interfaces/preferences.mojom
+++ b/services/preferences/public/interfaces/preferences.mojom
@@ -160,7 +160,7 @@
   RequestValue(string key, array<string> sub_pref_path);
 
   // These mirror the C++ PersistentPrefStore methods.
-  CommitPendingWrite();
+  CommitPendingWrite() => ();
   SchedulePendingLossyWrites();
   ClearMutableValues();
 };
diff --git a/services/preferences/tracked/segregated_pref_store.cc b/services/preferences/tracked/segregated_pref_store.cc
index af7349e..ced018e 100644
--- a/services/preferences/tracked/segregated_pref_store.cc
+++ b/services/preferences/tracked/segregated_pref_store.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/barrier_closure.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "base/values.h"
@@ -160,9 +161,12 @@
   selected_pref_store_->ReadPrefsAsync(NULL);
 }
 
-void SegregatedPrefStore::CommitPendingWrite() {
-  default_pref_store_->CommitPendingWrite();
-  selected_pref_store_->CommitPendingWrite();
+void SegregatedPrefStore::CommitPendingWrite(base::OnceClosure done_callback) {
+  base::RepeatingClosure done_callback_wrapper =
+      done_callback ? base::BarrierClosure(2, std::move(done_callback))
+                    : base::RepeatingClosure();
+  default_pref_store_->CommitPendingWrite(done_callback_wrapper);
+  selected_pref_store_->CommitPendingWrite(done_callback_wrapper);
 }
 
 void SegregatedPrefStore::SchedulePendingLossyWrites() {
diff --git a/services/preferences/tracked/segregated_pref_store.h b/services/preferences/tracked/segregated_pref_store.h
index 3621e49a..a2b714a 100644
--- a/services/preferences/tracked/segregated_pref_store.h
+++ b/services/preferences/tracked/segregated_pref_store.h
@@ -72,7 +72,7 @@
   PrefReadError GetReadError() const override;
   PrefReadError ReadPrefs() override;
   void ReadPrefsAsync(ReadErrorDelegate* error_delegate) override;
-  void CommitPendingWrite() override;
+  void CommitPendingWrite(base::OnceClosure done_callback) override;
   void SchedulePendingLossyWrites() override;
 
   void ClearMutableValues() override;
diff --git a/services/preferences/tracked/segregated_pref_store_unittest.cc b/services/preferences/tracked/segregated_pref_store_unittest.cc
index a237f38..d109036 100644
--- a/services/preferences/tracked/segregated_pref_store_unittest.cc
+++ b/services/preferences/tracked/segregated_pref_store_unittest.cc
@@ -13,6 +13,8 @@
 #include "base/callback.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/values.h"
 #include "components/prefs/persistent_pref_store.h"
 #include "components/prefs/pref_store_observer_mock.h"
@@ -54,9 +56,13 @@
   Data* data_;
 };
 
-}  // namespace
+enum class CommitPendingWriteMode {
+  WITHOUT_CALLBACK,
+  WITH_CALLBACK,
+};
 
-class SegregatedPrefStoreTest : public testing::Test {
+class SegregatedPrefStoreTest
+    : public testing::TestWithParam<CommitPendingWriteMode> {
  public:
   SegregatedPrefStoreTest()
       : read_error_delegate_data_(false,
@@ -87,6 +93,8 @@
     return std::move(read_error_delegate_);
   }
 
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+
   PrefStoreObserverMock observer_;
 
   scoped_refptr<TestingPrefStore> default_store_;
@@ -99,7 +107,9 @@
   std::unique_ptr<MockReadErrorDelegate> read_error_delegate_;
 };
 
-TEST_F(SegregatedPrefStoreTest, StoreValues) {
+}  // namespace
+
+TEST_P(SegregatedPrefStoreTest, StoreValues) {
   ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
             segregated_store_->ReadPrefs());
 
@@ -122,7 +132,14 @@
   ASSERT_FALSE(selected_store_->committed());
   ASSERT_FALSE(default_store_->committed());
 
-  segregated_store_->CommitPendingWrite();
+  if (GetParam() == CommitPendingWriteMode::WITHOUT_CALLBACK) {
+    segregated_store_->CommitPendingWrite(base::OnceClosure());
+    base::RunLoop().RunUntilIdle();
+  } else {
+    base::RunLoop run_loop;
+    segregated_store_->CommitPendingWrite(run_loop.QuitClosure());
+    run_loop.Run();
+  }
 
   ASSERT_TRUE(selected_store_->committed());
   ASSERT_TRUE(default_store_->committed());
@@ -302,3 +319,12 @@
   ASSERT_TRUE(values->Get(kSharedPref, &value));
   EXPECT_TRUE(base::Value(kValue1).Equals(value));
 }
+
+INSTANTIATE_TEST_CASE_P(
+    WithoutCallback,
+    SegregatedPrefStoreTest,
+    ::testing::Values(CommitPendingWriteMode::WITHOUT_CALLBACK));
+INSTANTIATE_TEST_CASE_P(
+    WithCallback,
+    SegregatedPrefStoreTest,
+    ::testing::Values(CommitPendingWriteMode::WITH_CALLBACK));
diff --git a/services/service_manager/embedder/main.cc b/services/service_manager/embedder/main.cc
index e661492..7b49811 100644
--- a/services/service_manager/embedder/main.cc
+++ b/services/service_manager/embedder/main.cc
@@ -234,14 +234,6 @@
 int RunServiceManager(MainDelegate* delegate) {
   NonEmbedderProcessInit();
 
-#if defined(OS_WIN)
-  // Route stdio to parent console (if any) or create one.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableLogging)) {
-    base::RouteStdioToConsole(true);
-  }
-#endif
-
   base::MessageLoop message_loop(base::MessageLoop::TYPE_UI);
 
   base::SequencedWorkerPool::EnableWithRedirectionToTaskSchedulerForProcess();
@@ -441,6 +433,14 @@
     return exit_code;
   }
 
+#if defined(OS_WIN)
+  // Route stdio to parent console (if any) or create one.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableLogging)) {
+    base::RouteStdioToConsole(true);
+  }
+#endif
+
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           ::switches::kTraceToConsole)) {
     base::trace_event::TraceConfig trace_config =
diff --git a/services/ui/BUILD.gn b/services/ui/BUILD.gn
index 96bb81c..4dded45c 100644
--- a/services/ui/BUILD.gn
+++ b/services/ui/BUILD.gn
@@ -81,6 +81,10 @@
   if (use_ozone) {
     deps += [ "//ui/ozone:ozone" ]
   }
+
+  if (use_ozone && is_chromeos) {
+    deps += [ "//services/ui/public/cpp/input_devices:input_device_controller" ]
+  }
 }
 
 repack("resources_strings") {
diff --git a/services/ui/manifest.json b/services/ui/manifest.json
index c73413b..a939fe3 100644
--- a/services/ui/manifest.json
+++ b/services/ui/manifest.json
@@ -42,6 +42,9 @@
         "ime_registrar": [
           "ui::mojom::IMERegistrar"
         ],
+        "input_device_controller": [
+          "ui::mojom::InputDeviceController"
+        ],
         "user_access_manager": [
           "ui::mojom::UserAccessManager"
         ],
diff --git a/services/ui/public/cpp/input_devices/BUILD.gn b/services/ui/public/cpp/input_devices/BUILD.gn
index 5fc4f27..fa8f255 100644
--- a/services/ui/public/cpp/input_devices/BUILD.gn
+++ b/services/ui/public/cpp/input_devices/BUILD.gn
@@ -2,6 +2,8 @@
 # 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")
+
 source_set("input_devices") {
   sources = [
     "input_device_client.cc",
@@ -18,3 +20,30 @@
     "//services/ui/public/interfaces/input_devices",
   ]
 }
+
+if (is_chromeos && use_ozone) {
+  source_set("input_device_controller") {
+    sources = [
+      "input_device_controller.cc",
+      "input_device_controller.h",
+    ]
+
+    deps = [
+      "//base",
+      "//services/service_manager/public/cpp",
+      "//ui/events:dom_keycode_converter",
+      "//ui/ozone",
+    ]
+
+    public_deps = [
+      "//services/ui/public/interfaces/input_devices",
+    ]
+
+    # This target is really an implementation detail of the ui service, but
+    # until Chrome is switched over to mus it needs to be visible to Chrome too.
+    visibility = [
+      "//chrome/browser",
+      "//services/ui:lib",
+    ]
+  }
+}
diff --git a/services/ui/public/cpp/input_devices/input_device_controller.cc b/services/ui/public/cpp/input_devices/input_device_controller.cc
new file mode 100644
index 0000000..084236ac
--- /dev/null
+++ b/services/ui/public/cpp/input_devices/input_device_controller.cc
@@ -0,0 +1,171 @@
+// Copyright 2017 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 "services/ui/public/cpp/input_devices/input_device_controller.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "services/service_manager/public/cpp/bind_source_info.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+#include "ui/events/devices/input_device.h"
+#include "ui/events/devices/touchscreen_device.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
+#include "ui/ozone/public/input_controller.h"
+#include "ui/ozone/public/ozone_platform.h"
+
+namespace ui {
+
+InputDeviceController::InputDeviceController() = default;
+
+InputDeviceController::~InputDeviceController() = default;
+
+void InputDeviceController::AddInterface(
+    service_manager::BinderRegistry* registry) {
+  // base::Unretained() is safe here as this class is tied to the life of
+  // Service, so that no requests should come in after this class is deleted.
+  registry->AddInterface<mojom::InputDeviceController>(
+      base::Bind(&InputDeviceController::BindInputDeviceControllerRequest,
+                 base::Unretained(this)));
+}
+
+void InputDeviceController::AddKeyboardDeviceObserver(
+    mojom::KeyboardDeviceObserverPtr observer) {
+  NotifyObserver(observer.get());
+  observers_.AddPtr(std::move(observer));
+}
+
+void InputDeviceController::GetHasTouchpad(GetHasTouchpadCallback callback) {
+  std::move(callback).Run(GetInputController()->HasTouchpad());
+}
+
+void InputDeviceController::GetHasMouse(GetHasMouseCallback callback) {
+  std::move(callback).Run(GetInputController()->HasMouse());
+}
+
+void InputDeviceController::SetCapsLockEnabled(bool enabled) {
+  GetInputController()->SetCapsLockEnabled(enabled);
+  NotifyObservers();
+}
+
+void InputDeviceController::SetNumLockEnabled(bool enabled) {
+  GetInputController()->SetNumLockEnabled(enabled);
+}
+
+void InputDeviceController::SetAutoRepeatEnabled(bool enabled) {
+  GetInputController()->SetAutoRepeatEnabled(enabled);
+  NotifyObservers();
+}
+
+void InputDeviceController::SetAutoRepeatRate(
+    base::TimeDelta auto_repeat_delay,
+    base::TimeDelta auto_repeat_interval) {
+  GetInputController()->SetAutoRepeatRate(auto_repeat_delay,
+                                          auto_repeat_interval);
+}
+
+void InputDeviceController::SetKeyboardLayoutByName(const std::string& name) {
+  GetInputController()->SetCurrentLayoutByName(name);
+}
+
+void InputDeviceController::SetTouchpadSensitivity(int32_t value) {
+  GetInputController()->SetTouchpadSensitivity(value);
+}
+
+void InputDeviceController::SetTapToClick(bool enabled) {
+  GetInputController()->SetTapToClick(enabled);
+}
+
+void InputDeviceController::SetThreeFingerClick(bool enabled) {
+  GetInputController()->SetThreeFingerClick(enabled);
+}
+
+void InputDeviceController::SetTapDragging(bool enabled) {
+  GetInputController()->SetTapDragging(enabled);
+}
+
+void InputDeviceController::SetNaturalScroll(bool enabled) {
+  GetInputController()->SetNaturalScroll(enabled);
+}
+
+void InputDeviceController::SetMouseSensitivity(int32_t value) {
+  GetInputController()->SetMouseSensitivity(value);
+}
+
+void InputDeviceController::SetPrimaryButtonRight(bool right) {
+  GetInputController()->SetPrimaryButtonRight(right);
+}
+
+void InputDeviceController::GetTouchDeviceStatus(
+    GetTouchDeviceStatusCallback callback) {
+  GetInputController()->GetTouchDeviceStatus(std::move(callback));
+}
+
+void InputDeviceController::GetTouchEventLog(
+    const base::FilePath& out_dir,
+    GetTouchEventLogCallback callback) {
+  GetInputController()->GetTouchEventLog(out_dir, std::move(callback));
+}
+
+void InputDeviceController::SetTapToClickPaused(bool state) {
+  GetInputController()->SetTapToClickPaused(state);
+}
+
+void InputDeviceController::SetInternalTouchpadEnabled(
+    bool enabled,
+    SetInternalTouchpadEnabledCallback callback) {
+  InputController* input_controller = GetInputController();
+  const bool value_changed =
+      input_controller->HasTouchpad() &&
+      (input_controller->IsInternalTouchpadEnabled() != enabled);
+  if (value_changed)
+    input_controller->SetInternalTouchpadEnabled(enabled);
+  std::move(callback).Run(value_changed);
+}
+
+void InputDeviceController::SetTouchscreensEnabled(bool enabled) {
+  GetInputController()->SetTouchscreensEnabled(enabled);
+}
+
+void InputDeviceController::SetInternalKeyboardFilter(
+    bool enable_filter,
+    const std::vector<uint32_t>& allowed_keys) {
+  std::vector<DomCode> dom_codes;
+  for (uint32_t key : allowed_keys) {
+    // NOTE: DomCodes and UsbKeycodes are the same thing.
+    const DomCode dom_code = KeycodeConverter::UsbKeycodeToDomCode(key);
+    if (dom_code != DomCode::NONE)
+      dom_codes.push_back(dom_code);
+  }
+  GetInputController()->SetInternalKeyboardFilter(enable_filter,
+                                                  std::move(dom_codes));
+}
+
+ui::InputController* InputDeviceController::GetInputController() {
+  return OzonePlatform::GetInstance()->GetInputController();
+}
+
+void InputDeviceController::NotifyObservers() {
+  observers_.ForAllPtrs([this](mojom::KeyboardDeviceObserver* observer) {
+    NotifyObserver(observer);
+  });
+}
+
+void InputDeviceController::NotifyObserver(
+    mojom::KeyboardDeviceObserver* observer) {
+  mojom::KeyboardDeviceStatePtr state = mojom::KeyboardDeviceState::New();
+  ui::InputController* input_controller = GetInputController();
+  state->is_caps_lock_enabled = input_controller->IsCapsLockEnabled();
+  state->is_auto_repeat_enabled = input_controller->IsAutoRepeatEnabled();
+  observer->OnKeyboardStateChanged(std::move(state));
+}
+
+void InputDeviceController::BindInputDeviceControllerRequest(
+    const service_manager::BindSourceInfo& source_info,
+    mojom::InputDeviceControllerRequest request) {
+  bindings_.AddBinding(this, std::move(request));
+}
+
+}  // namespace ui
diff --git a/services/ui/public/cpp/input_devices/input_device_controller.h b/services/ui/public/cpp/input_devices/input_device_controller.h
new file mode 100644
index 0000000..9164a1e
--- /dev/null
+++ b/services/ui/public/cpp/input_devices/input_device_controller.h
@@ -0,0 +1,83 @@
+// Copyright 2017 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 SERVICES_UI_PUBLIC_CPP_INPUT_DEVICES_INPUT_DEVICE_CONTROLLER_H_
+#define SERVICES_UI_PUBLIC_CPP_INPUT_DEVICES_INPUT_DEVICE_CONTROLLER_H_
+
+#include "base/macros.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "services/ui/public/interfaces/input_devices/input_device_controller.mojom.h"
+
+namespace service_manager {
+class BinderRegistry;
+struct BindSourceInfo;
+}
+
+namespace ui {
+
+class InputController;
+
+// Implementation of mojom::InputDeviceController that forwards to
+// ui::InputController.
+class InputDeviceController : public mojom::InputDeviceController {
+ public:
+  InputDeviceController();
+  ~InputDeviceController() override;
+
+  // Registers the interface provided by this class with |registry|.
+  void AddInterface(service_manager::BinderRegistry* registry);
+
+  // mojom::InputDeviceController::
+  void AddKeyboardDeviceObserver(
+      mojom::KeyboardDeviceObserverPtr observer) override;
+  void GetHasTouchpad(GetHasTouchpadCallback callback) override;
+  void GetHasMouse(GetHasMouseCallback callback) override;
+  void SetCapsLockEnabled(bool enabled) override;
+  void SetNumLockEnabled(bool enabled) override;
+  void SetAutoRepeatEnabled(bool enabled) override;
+  void SetAutoRepeatRate(base::TimeDelta auto_repeat_delay,
+                         base::TimeDelta auto_repeat_interval) override;
+  void SetKeyboardLayoutByName(const std::string& name) override;
+  void SetTouchpadSensitivity(int32_t value) override;
+  void SetTapToClick(bool enabled) override;
+  void SetThreeFingerClick(bool enabled) override;
+  void SetTapDragging(bool enabled) override;
+  void SetNaturalScroll(bool enabled) override;
+  void SetMouseSensitivity(int32_t value) override;
+  void SetPrimaryButtonRight(bool right) override;
+  void GetTouchDeviceStatus(GetTouchDeviceStatusCallback callback) override;
+  void GetTouchEventLog(const base::FilePath& out_dir,
+                        GetTouchEventLogCallback callback) override;
+  void SetTapToClickPaused(bool state) override;
+  void SetInternalTouchpadEnabled(
+      bool enabled,
+      SetInternalTouchpadEnabledCallback callback) override;
+  void SetTouchscreensEnabled(bool enabled) override;
+  void SetInternalKeyboardFilter(
+      bool enable_filter,
+      const std::vector<uint32_t>& allowed_keys) override;
+
+ private:
+  ui::InputController* GetInputController();
+
+  // Notifies all KeyboardDeviceObservers.
+  void NotifyObservers();
+
+  // Notifies a single KeyboardDeviceObserver.
+  void NotifyObserver(mojom::KeyboardDeviceObserver* observer);
+
+  void BindInputDeviceControllerRequest(
+      const service_manager::BindSourceInfo& source_info,
+      mojom::InputDeviceControllerRequest request);
+
+  mojo::BindingSet<mojom::InputDeviceController> bindings_;
+  mojo::InterfacePtrSet<mojom::KeyboardDeviceObserver> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(InputDeviceController);
+};
+
+}  // namespace ui
+
+#endif  // SERVICES_UI_PUBLIC_CPP_INPUT_DEVICES_INPUT_DEVICE_CONTROLLER_H_
diff --git a/services/ui/public/interfaces/input_devices/BUILD.gn b/services/ui/public/interfaces/input_devices/BUILD.gn
index 607333e..f4e7e5d 100644
--- a/services/ui/public/interfaces/input_devices/BUILD.gn
+++ b/services/ui/public/interfaces/input_devices/BUILD.gn
@@ -2,6 +2,7 @@
 # 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("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("input_devices") {
@@ -16,5 +17,9 @@
   if (is_chromeos) {
     sources += [ "touch_device_server.mojom" ]
     public_deps += [ "//ui/display/manager/chromeos/mojo:interfaces" ]
+    if (use_ozone) {
+      sources += [ "input_device_controller.mojom" ]
+      public_deps += [ "//mojo/common:common_custom_types" ]
+    }
   }
 }
diff --git a/services/ui/public/interfaces/input_devices/input_device_controller.mojom b/services/ui/public/interfaces/input_devices/input_device_controller.mojom
new file mode 100644
index 0000000..121b330
--- /dev/null
+++ b/services/ui/public/interfaces/input_devices/input_device_controller.mojom
@@ -0,0 +1,68 @@
+// Copyright 2017 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.
+
+module ui.mojom;
+
+import "mojo/common/file_path.mojom";
+import "mojo/common/time.mojom";
+import "ui/events/devices/mojo/input_devices.mojom";
+
+struct KeyboardDeviceState {
+  bool is_caps_lock_enabled;
+  bool is_auto_repeat_enabled;
+};
+
+// Notified when ever keyboard device state changes.
+interface KeyboardDeviceObserver {
+  // Called once when added, and subsequently any time the state changes.
+  OnKeyboardStateChanged(KeyboardDeviceState state);
+};
+
+// InputDeviceController is mojo wrapper for ui::InputController, see it for
+// details.
+interface InputDeviceController {
+  AddKeyboardDeviceObserver(KeyboardDeviceObserver observer);
+
+  GetHasTouchpad() => (bool has_touchpad);
+  GetHasMouse() => (bool has_mouse);
+
+  // Keyboard settings.
+  SetCapsLockEnabled(bool enabled);
+  SetNumLockEnabled(bool enabled);
+  SetAutoRepeatEnabled(bool enabled);
+  SetAutoRepeatRate(mojo.common.mojom.TimeDelta auto_repeat_delay,
+                    mojo.common.mojom.TimeDelta auto_repeat_interval);
+  SetKeyboardLayoutByName(string name);
+
+  // Touchpad settings.
+  SetTouchpadSensitivity(int32 value);
+  SetTapToClick(bool enabled);
+  SetThreeFingerClick(bool enabled);
+  SetTapDragging(bool enabled);
+  SetNaturalScroll(bool enabled);
+
+  // Mouse settings.
+  SetMouseSensitivity(int32 value);
+  SetPrimaryButtonRight(bool right);
+
+  // Touchscreen log settings.
+  GetTouchDeviceStatus() => (string status);
+  GetTouchEventLog(mojo.common.mojom.FilePath out_dir) =>
+      (array<mojo.common.mojom.FilePath> results);
+
+  // Temporarily enable/disable Tap-to-click. Used to enhance the user
+  // experience in some use cases (e.g., typing, watching video).
+  SetTapToClickPaused(bool state);
+
+  // Sets the state of the internal touchpad. |result| is true if the change
+  // was applied.
+  SetInternalTouchpadEnabled(bool enabled) => (bool result);
+
+  SetTouchscreensEnabled(bool enabled);
+
+  // If |enable_filter| is true, all keys on the internal keyboard except
+  // |allowed_keys| are disabled. |allowed_keys| is a list of DomCodes. Any
+  // invalid codes are mapped to NONE.
+  SetInternalKeyboardFilter(bool enable_filter, array<uint32> allowed_keys);
+};
diff --git a/services/ui/service.cc b/services/ui/service.cc
index 60f0a8d2..b18ee57 100644
--- a/services/ui/service.cc
+++ b/services/ui/service.cc
@@ -60,6 +60,10 @@
 #include "ui/ozone/public/ozone_platform.h"
 #endif
 
+#if defined(OS_CHROMEOS) && defined(USE_OZONE)
+#include "services/ui/public/cpp/input_devices/input_device_controller.h"
+#endif
+
 using mojo::InterfaceRequest;
 using ui::mojom::WindowServerTest;
 using ui::mojom::WindowTreeHostFactory;
@@ -98,6 +102,11 @@
   window_server_.reset();
 
 #if defined(USE_OZONE)
+#if defined(OS_CHROMEOS)
+  // InputDeviceController uses ozone.
+  input_device_controller_.reset();
+#endif
+
   OzonePlatform::Shutdown();
 #endif
 }
@@ -178,7 +187,7 @@
   params.single_process = false;
   ui::OzonePlatform::InitializeForUI(params);
 
-  // TODO(kylechar): We might not always want a US keyboard layout.
+  // Assume a client will change the layout to an appropriate configuration.
   ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine()
       ->SetCurrentLayoutByName("us");
   client_native_pixmap_factory_ = ui::CreateClientNativePixmapFactoryOzone();
@@ -186,6 +195,11 @@
       client_native_pixmap_factory_.get());
 
   DCHECK(gfx::ClientNativePixmapFactory::GetInstance());
+
+#if defined(OS_CHROMEOS)
+  input_device_controller_ = base::MakeUnique<InputDeviceController>();
+  input_device_controller_->AddInterface(&registry_);
+#endif
 #endif
 
 // TODO(rjkroege): Enter sandbox here before we start threads in GpuState
diff --git a/services/ui/service.h b/services/ui/service.h
index 6dd7d2f3..415080d 100644
--- a/services/ui/service.h
+++ b/services/ui/service.h
@@ -53,6 +53,7 @@
 
 namespace ui {
 
+class InputDeviceController;
 class PlatformEventSource;
 
 namespace ws {
@@ -162,6 +163,9 @@
   bool test_config_;
 #if defined(USE_OZONE)
   std::unique_ptr<gfx::ClientNativePixmapFactory> client_native_pixmap_factory_;
+#if defined(OS_CHROMEOS)
+  std::unique_ptr<InputDeviceController> input_device_controller_;
+#endif
 #endif
 
   // Manages display hardware and handles display management. May register Mojo
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 534b296..e059376 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -10680,6 +10680,35 @@
         },
         "test": "mus_browser_tests"
       }
+    ],
+    "isolated_scripts": [
+      {
+        "args": [
+          "--browser=exact",
+          "--browser-executable=./test_chrome",
+          "--xvfb"
+        ],
+        "isolate_name": "telemetry_perf_unittests",
+        "name": "telemetry_perf_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "hard_timeout": 960,
+          "shards": 12
+        }
+      },
+      {
+        "args": [
+          "--browser=exact",
+          "--browser-executable=./test_chrome",
+          "--jobs=1"
+        ],
+        "isolate_name": "telemetry_unittests",
+        "name": "telemetry_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 4
+        }
+      }
     ]
   },
   "Mojo Linux": {
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index 228fae0b..026b2e3 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -25652,6 +25652,26 @@
         }
       },
       {
+        "args": [],
+        "isolate_name": "load_library_perf_tests",
+        "name": "load_library_perf_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "102b:0534",
+              "id": "build150-m1",
+              "os": "Ubuntu-14.04",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 36000,
+          "hard_timeout": 10800,
+          "ignore_task_failure": false,
+          "io_timeout": 3600
+        }
+      },
+      {
         "args": [
           "loading.desktop",
           "-v",
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service b/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service
index 1ac711e..f74b188 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service
@@ -184,6 +184,24 @@
 Bug(none) external/wpt/credential-management/credentialscontainer-create-basics.https.html [ Timeout ]
 Bug(none) external/wpt/credential-management/idl.https.html [ Timeout ]
 Bug(none) external/wpt/css-font-display/font-display.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/background-image-alpha.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/background-image-multiple.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/background-image-tiled.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/invalid-image-constructor-error.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/invalid-image-paint-error.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/overdraw.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/paint-arguments.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/paint-function-arguments.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/paint2d-composite.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/paint2d-filter.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/paint2d-gradient.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/paint2d-image.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/paint2d-paths.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/paint2d-rects.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/paint2d-shadows.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/paint2d-transform.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/valid-image-after-load.html [ Timeout ]
+Bug(none) external/wpt/css-paint-api/valid-image-before-load.html [ Timeout ]
 Bug(none) external/wpt/css/css-grid-1/alignment/grid-content-distribution-018.html [ Timeout ]
 Bug(none) external/wpt/css/css-shapes-1/shape-outside/shape-box/shape-outside-box-003.html [ Timeout ]
 Bug(none) external/wpt/css/css-shapes-1/shape-outside/values/shape-outside-ellipse-004.html [ Timeout ]
@@ -1179,6 +1197,7 @@
 Bug(none) external/wpt/streams/writable-streams/reentrant-strategy.serviceworker.https.html [ Timeout ]
 Bug(none) external/wpt/streams/writable-streams/start.serviceworker.https.html [ Timeout ]
 Bug(none) external/wpt/streams/writable-streams/write.serviceworker.https.html [ Timeout ]
+Bug(none) external/wpt/url/failure.html [ Failure ]
 Bug(none) external/wpt/webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html [ Timeout ]
 Bug(none) external/wpt/webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html [ Timeout ]
 Bug(none) external/wpt/webaudio/the-audio-api/the-audioparam-interface/idl-test.html [ Timeout ]
@@ -1388,6 +1407,7 @@
 Bug(none) fast/js/nested-object-gc.html [ Timeout ]
 Bug(none) fast/js/with-scope-gc.html [ Timeout ]
 Bug(none) fast/loader/local-svg-parsed-as-svg.svg [ Timeout ]
+Bug(none) fast/loader/main-document-url-for-non-http-loads.html [ Failure ]
 Bug(none) fast/loader/reload-zero-byte-plugin.html [ Timeout ]
 Bug(none) fast/loader/sandboxed-plugin-crash.html [ Crash ]
 Bug(none) fast/loader/simultaneous-reloads-assert.html [ Failure ]
@@ -1554,7 +1574,7 @@
 Bug(none) http/tests/budget/reserve.html [ Timeout ]
 Bug(none) http/tests/cache/cached-main-resource.html [ Timeout ]
 Bug(none) http/tests/cache/history-only-cached-subresource-loads-max-age-https.html [ Timeout ]
-Bug(none) http/tests/cache/iframe-304-crash.html [ Timeout ]
+Bug(none) http/tests/cache/iframe-304-crash.html [ Failure Timeout ]
 Bug(none) http/tests/cache/network-error-during-revalidation.html [ Timeout ]
 Bug(none) http/tests/cache/post-redirect-get.php [ Timeout ]
 Bug(none) http/tests/cache/post-with-cached-subresources.php [ Timeout ]
@@ -1878,6 +1898,7 @@
 Bug(none) http/tests/fetch/workers/thorough/scheme-data-other-https.html [ Timeout ]
 Bug(none) http/tests/fetch/workers/thorough/scheme-data.html [ Timeout ]
 Bug(none) http/tests/fileapi/blob-url-in-subframe.html [ Timeout ]
+Bug(none) http/tests/history/post-replace-state-reload.html [ Failure ]
 Bug(none) http/tests/history/push-state-in-new-frame.html [ Timeout ]
 Bug(none) http/tests/htmlimports/import-cors-credentials.html [ Failure ]
 Bug(none) http/tests/https/verify-ssl-enabled.php [ Timeout ]
@@ -1890,6 +1911,7 @@
 Bug(none) http/tests/loading/pdf-commit-load-callbacks.html [ Crash Timeout ]
 Bug(none) http/tests/loading/preload-image-sizes-2x.html [ Failure ]
 Bug(none) http/tests/loading/preload-picture-sizes-2x.html [ Failure ]
+Bug(none) http/tests/loading/redirect-methods.html [ Failure ]
 Bug(none) http/tests/loading/redirect-with-no-location-crash.html [ Timeout ]
 Bug(none) http/tests/loading/text-content-type-with-binary-extension.html [ Failure ]
 Bug(none) http/tests/loading/window-open-onblur-reentrancy.html [ Timeout ]
@@ -2000,8 +2022,10 @@
 Bug(none) http/tests/misc/resource-timing-sizes-xhr-fetch.html [ Timeout ]
 Bug(none) http/tests/misc/tests-finishing-simultaneously.html [ Timeout ]
 Bug(none) http/tests/misc/webtiming-ssl.php [ Timeout ]
+Bug(none) http/tests/misc/window-dot-stop.html [ Failure ]
 Bug(none) http/tests/misc/xhtml.php [ Failure ]
 Bug(none) http/tests/navigation/image-load-in-unload-handler.html [ Failure ]
+Bug(none) http/tests/navigation/location-reload-after-post.php [ Failure ]
 Bug(none) http/tests/navigation/multiple-back-forward-entries.html [ Timeout ]
 Bug(none) http/tests/navigation/navigation-interrupted-by-fragment.html [ Timeout ]
 Bug(none) http/tests/navigation/onload-navigation-iframe-2.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 646192c..9caef2b6 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -998,66 +998,6 @@
 crbug.com/441840 external/wpt/css/css-shapes-1/shape-outside/values/shape-outside-polygon-004.html [ Failure ]
 crbug.com/441840 [ Linux Win ] external/wpt/css/css-shapes-1/shape-outside/values/shape-outside-shape-arguments-000.html [ Failure ]
 
-crbug.com/731696 images/color-profile-border-fade.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-background-image-cover.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-layer-filter.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-image-shape.html [ NeedsRebaseline ]
-crbug.com/731696 virtual/exotic-color-space/images/motion-jpeg-single-frame.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-image.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-image-canvas.html [ NeedsRebaseline ]
-crbug.com/731696 images/jpeg-with-color-profile.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-iframe.html [ NeedsRebaseline ]
-crbug.com/731696 virtual/gpu-rasterization/images/color-profile-background-image-space.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-animate-rotate.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-image-filter-all.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-animate.html [ NeedsRebaseline ]
-crbug.com/731696 virtual/gpu-rasterization/images/color-profile-svg.html [ NeedsRebaseline ]
-crbug.com/731696 virtual/gpu-rasterization/images/color-profile-image-canvas-svg.html [ NeedsRebaseline ]
-crbug.com/731696 virtual/exotic-color-space/images/color-profile-image-profile-match.html [ NeedsRebaseline ]
-crbug.com/731696 virtual/gpu-rasterization/images/color-profile-image-canvas-pattern.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-svg-fill-text.html [ NeedsRebaseline ]
-crbug.com/731696 images/webp-color-profile-lossy-alpha.html [ NeedsRebaseline ]
-crbug.com/731696 virtual/exotic-color-space/images/color-profile-image-canvas.html [ NeedsRebaseline ]
-crbug.com/731696 images/cHRM_color_spin.html [ NeedsRebaseline ]
-crbug.com/731696 images/webp-color-profile-lossless.html [ NeedsRebaseline ]
-crbug.com/731696 images/paletted-png-with-color-profile.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-clip.html [ NeedsRebaseline ]
-crbug.com/731696 virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb.html [ NeedsRebaseline ]
-crbug.com/731696 images/cross-fade-background-size.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-mask-image-svg.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-jpeg-with-color-profile.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-background-clip-text.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-image-canvas-svg.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-image-pseudo-content.html [ NeedsRebaseline ]
-crbug.com/731696 virtual/exotic-color-space/images/color-profile-drag-image.html [ NeedsRebaseline ]
-crbug.com/731696 virtual/exotic-color-space/images/color-profile-image-canvas-svg.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-layer.html [ NeedsRebaseline ]
-crbug.com/731696 virtual/exotic-color-space/images/jpeg-yuv-progressive-image.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-background-image-repeat.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-image-svg-resource-url.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-group.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-svg-foreign-object.html [ NeedsRebaseline ]
-crbug.com/731696 images/png-suite/test.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-background-image-cross-fade.html [ NeedsRebaseline ]
-crbug.com/731696 virtual/exotic-color-space/images/color-profile-image-canvas-pattern.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-image-canvas-pattern.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-filter.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-object.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-drag-image.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-border-image.html [ NeedsRebaseline ]
-crbug.com/731696 virtual/gpu-rasterization/images/cross-fade-background-size.html [ NeedsRebaseline ]
-crbug.com/731696 images/webp-color-profile-lossy.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-munsell-adobe-to-srgb.html [ NeedsRebaseline ]
-crbug.com/731696 virtual/gpu-rasterization/images/color-profile-drag-image.html [ NeedsRebaseline ]
-crbug.com/731696 images/png-with-color-profile.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-image-object-fit.html [ NeedsRebaseline ]
-crbug.com/731696 virtual/gpu-rasterization/images/color-profile-image-canvas.html [ NeedsRebaseline ]
-crbug.com/731696 virtual/gpu-rasterization/images/color-profile-svg-fill-text.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-background-image-cross-fade-png.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-border-radius.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-background-image-space.html [ NeedsRebaseline ]
-crbug.com/731696 images/color-profile-svg.html [ NeedsRebaseline ]
-
 crbug.com/306730 external/wpt/css/css-text-3/i18n/css3-text-line-break-jazh-136.html [ Failure ]
 crbug.com/306730 external/wpt/css/css-text-3/i18n/css3-text-line-break-jazh-137.html [ Failure ]
 crbug.com/306730 external/wpt/css/css-text-3/i18n/css3-text-line-break-jazh-142.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/common/css-paint-tests.js b/third_party/WebKit/LayoutTests/external/wpt/common/css-paint-tests.js
new file mode 100644
index 0000000..58a8e64
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/common/css-paint-tests.js
@@ -0,0 +1,18 @@
+// To make sure that we take the snapshot at the right time, we do double
+// requestAnimationFrame. In the second frame, we take a screenshot, that makes
+// sure that we already have a full frame.
+function importPaintWorkletAndTerminateTestAfterAsyncPaint(code) {
+    if (typeof paintWorklet == "undefined") {
+        takeScreenshot();
+    } else {
+        var blob = new Blob([code], {type: 'text/javascript'});
+        paintWorklet.addModule(URL.createObjectURL(blob)).then(function() {
+            requestAnimationFrame(function() {
+                requestAnimationFrame(function() {
+                    takeScreenshot();
+                });
+            });
+        });
+    }
+}
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-alpha-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-alpha-ref.html
new file mode 100644
index 0000000..519b359
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-alpha-ref.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+#background {
+  background-color: yellow;
+  display: inline-block;
+}
+
+.container {
+  font-size: 0px;
+}
+</style>
+</head>
+<body>
+
+<div id="background">
+  <div class="container">
+    <canvas id ="opaque" width="100" height="100"></canvas>
+  </div>
+  <div class="container">
+    <canvas id ="nonopaque" width="100" height="100"></canvas>
+  </div>
+</div>
+
+<script>
+function drawCanvas(canvasID, hasAlpha) {
+  var canvas = document.getElementById(canvasID);
+  var context = canvas.getContext("2d", {alpha: hasAlpha});
+  context.clearRect(0, 0, canvas.width, canvas.height);
+  context.strokeStyle = 'blue';
+  context.lineWidth = 4;
+  context.strokeRect(20, 20, 60, 60);
+};
+
+drawCanvas('opaque', false);
+drawCanvas('nonopaque', true);
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-alpha.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-alpha.html
new file mode 100644
index 0000000..ac69aa0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-alpha.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="background-image-alpha-ref.html">
+<style>
+.container {
+  width: 100px;
+  height: 100px;
+}
+
+#canvas-opaque {
+  background-image: paint(opaque);
+}
+
+#canvas-nonopaque {
+  background-image: paint(nonOpaque);
+}
+
+#background {
+  background-color: yellow;
+  display: inline-block;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="background">
+  <div id="canvas-opaque" class="container"></div>
+  <div id="canvas-nonopaque" class="container"></div>
+</div>
+
+<script id="code" type="text/worklet">
+registerPaint('opaque', class {
+    static get alpha() { return false; }
+    paint(ctx, geom) {
+        ctx.strokeStyle = 'blue';
+        ctx.lineWidth = 4;
+        ctx.strokeRect(20, 20, 60, 60);
+    }
+});
+
+registerPaint('nonOpaque', class {
+    static get alpha() { return true; }
+    paint(ctx, geom) {
+        ctx.strokeStyle = 'blue';
+        ctx.lineWidth = 4;
+        ctx.strokeRect(20, 20, 60, 60);
+    }
+});
+</script>
+
+<script>
+    importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-multiple-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-multiple-ref.html
new file mode 100644
index 0000000..536258b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-multiple-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="output" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+var colors = ['red', 'green', 'blue'];
+for (var i = 2; i >= 0; i--) {
+    ctx.fillStyle = colors[i];
+    ctx.fillRect(i * 20, i * 20, 40, 40);
+}
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-multiple.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-multiple.html
new file mode 100644
index 0000000..7fb57510
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-multiple.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="background-image-multiple-ref.html">
+<style>
+    #output {
+        width: 100px;
+        height: 100px;
+        background-image: paint(n0), paint(n1), paint(n2);
+    }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+var colors = ['red', 'green', 'blue'];
+
+for (let i = 0; i < 3; i++) {
+    registerPaint('n' + i, class {
+        paint(ctx, geom) {
+            ctx.fillStyle = colors[i];
+            ctx.fillRect(i * 20, i * 20, 40, 40);
+        }
+    });
+}
+</script>
+
+<script>
+    importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-tiled-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-tiled-ref.html
new file mode 100644
index 0000000..a0151d8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-tiled-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="one" width="100" height="100"></canvas>
+<canvas id ="two" width="100" height="100"></canvas>
+<script>
+function drawCircle(ctx, geom) {
+    var x = geom.width / 2;
+    var y = geom.height / 2;
+
+    ctx.fillStyle = 'green';
+    ctx.beginPath();
+    ctx.ellipse(x, y, x - 1, y - 1, 0, 0, 2 * Math.PI);
+    ctx.fill();
+}
+
+var ctx1 = document.getElementById('one').getContext('2d');
+drawCircle(ctx1, {width: 50, height: 50});
+ctx1.translate(50, 0);
+drawCircle(ctx1, {width: 50, height: 50});
+ctx1.resetTransform();
+ctx1.translate(0, 50);
+drawCircle(ctx1, {width: 100, height: 50});
+
+var ctx2 = document.getElementById('two').getContext('2d');
+for (var i = 0; i < 5; i++) {
+    drawCircle(ctx2, {width: 50, height: 20});
+    ctx2.translate(0, 20);
+}
+ctx2.resetTransform();
+ctx2.translate(50, 25);
+drawCircle(ctx2, {width: 50, height: 50});
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-tiled.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-tiled.html
new file mode 100644
index 0000000..95d8c12
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-tiled.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="background-image-tiled-ref.html">
+<style>
+    div {
+        display: inline-block;
+        width: 100px;
+        height: 100px;
+    }
+
+    #one {
+        background:
+            paint(ellipse) top left/50% 50% repeat-x,
+            paint(ellipse) bottom left/100% 50% no-repeat;
+    }
+
+    #two {
+        background:
+            paint(ellipse) top left/50% 20% repeat-y,
+            paint(ellipse) center right/50% 50% no-repeat;
+    }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="one"></div>
+<div id="two"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('ellipse', class {
+    paint(ctx, geom) {
+        var x = geom.width / 2;
+        var y = geom.height / 2;
+
+        ctx.fillStyle = 'green';
+        ctx.beginPath();
+        ctx.ellipse(x, y, x - 1, y - 1, 0, 0, 2 * Math.PI);
+        ctx.fill();
+    }
+});
+</script>
+
+<script>
+    importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-constructor-error-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-constructor-error-ref.html
new file mode 100644
index 0000000..b6a6dec6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-constructor-error-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div style="background: green; width: 100px; height: 100px"></div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-constructor-error.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-constructor-error.html
new file mode 100644
index 0000000..30a06eb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-constructor-error.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="invalid-image-constructor-error-ref.html">
+<style>
+    #output {
+        width: 100px;
+        height: 100px;
+        background-image: paint(error);
+        background-color: green;
+    }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('error', class {
+    constructor() { throw Error('failed!'); }
+    paint(ctx, geom) {
+        ctx.fillStyle = 'red';
+        ctx.fillRect(0, 0, geom.width, geom.height);
+    }
+});
+</script>
+
+<script>
+    importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-paint-error-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-paint-error-ref.html
new file mode 100644
index 0000000..b6a6dec6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-paint-error-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div style="background: green; width: 100px; height: 100px"></div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-paint-error.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-paint-error.html
new file mode 100644
index 0000000..6e117f8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-paint-error.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="invalid-image-paint-error-ref.html">
+<style>
+    #output {
+        width: 100px;
+        height: 100px;
+        background-image: paint(error);
+        background-color: green;
+    }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('error', class {
+    paint(ctx, geom) {
+        ctx.fillStyle = 'red';
+        ctx.fillRect(0, 0, geom.width, geom.height);
+        throw Error('failed!');
+    }
+});
+</script>
+
+<script>
+    importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-pending-script-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-pending-script-ref.html
new file mode 100644
index 0000000..b6a6dec6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-pending-script-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div style="background: green; width: 100px; height: 100px"></div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-pending-script.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-pending-script.html
new file mode 100644
index 0000000..c4cf755
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/invalid-image-pending-script.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="invalid-image-pending-script-ref.html">
+<style>
+    #output {
+        width: 100px;
+        height: 100px;
+        background-image: paint(invalid);
+        background-color: green;
+    }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="output"></div>
+<script>
+    importPaintWorkletAndTerminateTestAfterAsyncPaint("");
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/overdraw-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/overdraw-ref.html
new file mode 100644
index 0000000..b6a6dec6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/overdraw-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div style="background: green; width: 100px; height: 100px"></div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/overdraw.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/overdraw.html
new file mode 100644
index 0000000..f95eeb5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/overdraw.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<link rel="match" href="overdraw-ref.html">
+<style>
+    #output {
+        width: 100px;
+        height: 100px;
+        background-image: paint(green);
+        background-color: red;
+    }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('green', class {
+    paint(ctx, geom) {
+        ctx.fillStyle = 'green';
+        ctx.fillRect(-10, -10, geom.width + 20, geom.height + 20);
+    }
+});
+</script>
+
+<script>
+    importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint-arguments-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint-arguments-ref.html
new file mode 100644
index 0000000..3352acf6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint-arguments-ref.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+#background {
+  background-color: yellow;
+  display: inline-block;
+}
+
+.container {
+  font-size: 0px;
+}
+</style>
+</head>
+<body>
+
+<div id="background">
+  <div class="container">
+    <canvas id ="box-green" width="100" height="100"></canvas>
+  </div>
+  <div class="container">
+    <canvas id ="box-red" width="100" height="100"></canvas>
+  </div>
+</div>
+
+<script>
+function drawCanvas(canvasID, color) {
+  var canvas = document.getElementById(canvasID);
+  var context = canvas.getContext("2d", {alpha: true});
+  context.clearRect(0, 0, canvas.width, canvas.height);
+  context.strokeStyle = color;
+  context.lineWidth = 4;
+  context.strokeRect(20, 20, 60, 60);
+};
+
+drawCanvas('box-green', 'green');
+drawCanvas('box-red', 'red');
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint-arguments.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint-arguments.html
new file mode 100644
index 0000000..ce2eec3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint-arguments.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="paint-arguments-ref.html">
+<style>
+.container {
+  width: 100px;
+  height: 100px;
+}
+
+#canvas-box-green {
+  background-image: paint(box, green);
+}
+
+#canvas-box-red {
+  background-image: paint(box, red);
+}
+
+#background {
+  background-color: yellow;
+  display: inline-block;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+
+<div id="background">
+  <div id="canvas-box-green" class="container"></div>
+  <div id="canvas-box-red" class="container"></div>
+</div>
+
+<script id="code" type="text/worklet">
+registerPaint('box', class {
+    static get alpha() { return true; }
+    static get inputArguments() { return ['<color>']; }
+    paint(ctx, geom, properties, args) {
+        ctx.strokeStyle = args[0].toString();
+        ctx.lineWidth = 4;
+        ctx.strokeRect(20, 20, 60, 60);
+    }
+});
+
+</script>
+
+<script>
+  importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint-function-arguments-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint-function-arguments-ref.html
new file mode 100644
index 0000000..99adfd27
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint-function-arguments-ref.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+#background {
+  background-color: yellow;
+  display: inline-block;
+}
+
+.container {
+  font-size: 0px;
+}
+</style>
+</head>
+<body>
+
+<div id="background">
+  <div class="container">
+    <canvas id ="box-1" width="200" height="200"></canvas>
+  </div>
+  <div class="container">
+    <canvas id ="box-2" width="200" height="200"></canvas>
+  </div>
+</div>
+
+<script>
+function drawCanvas(canvasID, color, width) {
+  var canvas = document.getElementById(canvasID);
+  var context = canvas.getContext("2d", {alpha: true});
+  context.clearRect(0, 0, canvas.width, canvas.height);
+  context.strokeStyle = color;
+  context.lineWidth = width;
+  context.strokeRect(40, 40, 120, 120);
+};
+
+drawCanvas('box-1', 'rgb(50, 100, 150)', '5px');
+drawCanvas('box-2', 'rgb(150, 100, 50)', '10px');
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint-function-arguments.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint-function-arguments.html
new file mode 100644
index 0000000..6bae7ffe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint-function-arguments.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="paint-function-arguments-ref.html">
+<style>
+.container {
+  width: 200px;
+  height: 200px;
+}
+
+#canvas-box-1 {
+  background-image: paint(box, rgb(50, 100, 150), 5px);
+}
+
+#canvas-box-2 {
+  background-image: paint(box, rgb(150, 100, 50), 10px);
+}
+
+#background {
+  background-color: yellow;
+  display: inline-block;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+
+<div id="background">
+  <div id="canvas-box-1" class="container"></div>
+  <div id="canvas-box-2" class="container"></div>
+</div>
+
+<script id="code" type="text/worklet">
+registerPaint('box', class {
+    static get alpha() { return true; }
+    static get inputArguments() { return ['<color>', '<length>']; }
+    paint(ctx, geom, properties, args) {
+        ctx.strokeStyle = args[0].toString();
+        ctx.lineWidth = args[1].toString();
+        ctx.strokeRect(40, 40, 120, 120);
+    }
+});
+
+</script>
+
+<script>
+  importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-composite-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-composite-ref.html
new file mode 100644
index 0000000..3b75d52
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-composite-ref.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+    canvas { display: inline-block; }
+</style>
+</head>
+<body>
+<canvas id="source-over" width="80" height="80"></canvas>
+<canvas id="source-in" width="80" height="80"></canvas>
+<canvas id="source-out" width="80" height="80"></canvas>
+<canvas id="source-atop" width="80" height="80"></canvas>
+<br>
+<canvas id="destination-over" width="80" height="80"></canvas>
+<canvas id="destination-in" width="80" height="80"></canvas>
+<canvas id="destination-out" width="80" height="80"></canvas>
+<canvas id="destination-atop" width="80" height="80"></canvas>
+<br>
+<canvas id="lighter" width="80" height="80"></canvas>
+<canvas id="xor" width="80" height="80"></canvas>
+<script>
+var compositeOps = [
+    'source-over',
+    'source-in',
+    'source-out',
+    'source-atop',
+    'destination-over',
+    'destination-in',
+    'destination-out',
+    'destination-atop',
+    'lighter',
+    'xor'
+];
+
+for (var i = 0; i < compositeOps.length; i++) {
+    var op = compositeOps[i];
+    var ctx = document.getElementById(op).getContext('2d');
+    ctx.fillStyle = 'red';
+    ctx.fillRect(5, 5, 40, 40);
+
+    ctx.globalCompositeOperation = op;
+
+    ctx.fillStyle = 'deepskyblue';
+    ctx.beginPath();
+    ctx.arc(45,45,20,0,Math.PI*2,true);
+    ctx.fill();
+}
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-composite.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-composite.html
new file mode 100644
index 0000000..ba88f92
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-composite.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="paint2d-composite-ref.html">
+<style>
+    div {
+        display: inline-block;
+        width: 80px;
+        height: 80px;
+    }
+    #source-over { background-image: paint(source-over); }
+    #source-in { background-image: paint(source-in); }
+    #source-out { background-image: paint(source-out); }
+    #source-atop { background-image: paint(source-atop); }
+    #destination-over { background-image: paint(destination-over); }
+    #destination-in { background-image: paint(destination-in); }
+    #destination-out { background-image: paint(destination-out); }
+    #destination-atop { background-image: paint(destination-atop); }
+    #lighter { background-image: paint(lighter); }
+    #xor { background-image: paint(xor); }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="source-over"></div>
+<div id="source-in"></div>
+<div id="source-out"></div>
+<div id="source-atop"></div>
+<br>
+<div id="destination-over"></div>
+<div id="destination-in"></div>
+<div id="destination-out"></div>
+<div id="destination-atop"></div>
+<br>
+<div id="lighter"></div>
+<div id="xor"></div>
+
+<script id="code" type="text/worklet">
+var compositeOps = [
+    'source-over',
+    'source-in',
+    'source-out',
+    'source-atop',
+    'destination-over',
+    'destination-in',
+    'destination-out',
+    'destination-atop',
+    'lighter',
+    'xor'
+];
+
+function doPaint(ctx, op) {
+    ctx.fillStyle = 'red';
+    ctx.fillRect(5, 5, 40, 40);
+
+    ctx.globalCompositeOperation = op;
+
+    ctx.fillStyle = 'deepskyblue';
+    ctx.beginPath();
+    ctx.arc(45,45,20,0,Math.PI*2,true);
+    ctx.fill();
+}
+
+for (var i = 0; i < compositeOps.length; i++) {
+    let op = compositeOps[i];
+    registerPaint(op, class { paint(ctx, geom) { doPaint(ctx, op); } });
+}
+</script>
+
+<script>
+    importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-filter-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-filter-ref.html
new file mode 100644
index 0000000..4ca6383
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-filter-ref.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+    canvas { display: inline-block; }
+</style>
+</head>
+<body>
+<canvas id='output0' width='100' height='100'></canvas>
+<canvas id='output1' width='100' height='100'></canvas>
+<canvas id='output2' width='100' height='100'></canvas>
+<canvas id='output3' width='100' height='100'></canvas>
+<canvas id='output4' width='100' height='100'></canvas>
+<br>
+<canvas id='output5' width='100' height='100'></canvas>
+<canvas id='output6' width='100' height='100'></canvas>
+<canvas id='output7' width='100' height='100'></canvas>
+<canvas id='output8' width='100' height='100'></canvas>
+<canvas id='output9' width='100' height='100'></canvas>
+<br>
+<canvas id='output10' width='100' height='100'></canvas>
+<canvas id='output11' width='100' height='100'></canvas>
+<canvas id='output12' width='100' height='100'></canvas>
+<canvas id='output13' width='100' height='100'></canvas>
+<canvas id='output14' width='100' height='100'></canvas>
+
+<script>
+var paint = function(id, filter) {
+  var c = document.getElementById(id);
+  var ctx = c.getContext('2d');
+  ctx.filter = filter;
+  ctx.fillStyle = '#A00';
+  ctx.fillRect(0, 0, 15, 15);
+  ctx.fillStyle = '#0A0';
+  ctx.fillRect(15, 0, 15, 15);
+  ctx.fillStyle = '#00A';
+  ctx.fillRect(0, 15, 15, 15);
+  ctx.fillStyle = "#AA0";
+  ctx.fillRect(15, 15, 15, 15);
+  return ctx;
+};
+
+paint('output0', "none");
+paint('output1', "blur(10px)");
+paint('output2', "blur(0px)");
+paint('output3', "blur(16px)");
+paint('output4', "blur(0px)");
+paint('output5', "brightness(40%)");
+paint('output6', "contrast(20%)");
+paint('output7', "drop-shadow(0 0 5px green)");
+paint('output8', "grayscale(100%)");
+paint('output9', "invert(100%)");
+paint('output10', "opacity(50%)");
+paint('output11', "saturate(20%)");
+paint('output12', "sepia(100%)");
+paint('output13', "sepia(1) hue-rotate(200deg)");
+paint('output14', "url(#url)");
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-filter.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-filter.html
new file mode 100644
index 0000000..560b1b2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-filter.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="paint2d-filter-ref.html">
+<style>
+    div {
+        display: inline-block;
+        width: 100px;
+        height: 100px;
+    }
+    #filter-none { background-image: paint(filter-none); }
+    #filter-blur-10px { background-image: paint(filter-blur-10px); }
+    #filter-blur-50vh { background-image: paint(filter-blur-50vh); }
+    #filter-blur-1em { background-image: paint(filter-blur-1em); }
+    #filter-blur-2percent { background-image: paint(filter-blur-2percent); }
+    #filter-brightness { background-image: paint(filter-brightness); }
+    #filter-contrast { background-image: paint(filter-contrast); }
+    #filter-drop-shadow { background-image: paint(filter-drop-shadow); }
+    #filter-grayscale { background-image: paint(filter-grayscale); }
+    #filter-invert { background-image: paint(filter-invert); }
+    #filter-opacity { background-image: paint(filter-opacity); }
+    #filter-saturate { background-image: paint(filter-saturate); }
+    #filter-sepia { background-image: paint(filter-sepia); }
+    #filter-hue-rotate { background-image: paint(filter-hue-rotate); }
+    #filter-url { background-image: paint(filter-url); }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="filter-none"></div>
+<div id="filter-blur-10px"></div>
+<div id="filter-blur-50vh"></div>
+<div id="filter-blur-1em"></div>
+<div id="filter-blur-2percent"></div>
+<br>
+<div id="filter-brightness"></div>
+<div id="filter-contrast"></div>
+<div id="filter-drop-shadow"></div>
+<div id="filter-grayscale"></div>
+<div id="filter-invert"></div>
+<br>
+<div id="filter-opacity"></div>
+<div id="filter-saturate"></div>
+<div id="filter-sepia"></div>
+<div id="filter-hue-rotate"></div>
+<div id="filter-url"></div>
+
+<script id="code" type="text/worklet">
+var paintNames = [
+    'filter-none',
+    'filter-blur-10px',
+    'filter-blur-50vh',
+    'filter-blur-1em',
+    'filter-blur-2percent',
+    'filter-brightness',
+    'filter-contrast',
+    'filter-drop-shadow',
+    'filter-grayscale',
+    'filter-invert',
+    'filter-opacity',
+    'filter-saturate',
+    'filter-sepia',
+    'filter-hue-rotate',
+    'filter-url'
+];
+
+var filterOps = [
+    'none',
+    'blur(10px)',
+    'blur(50vh)',
+    'blur(1em)',
+    'blur(2%)',
+    'brightness(40%)',
+    'contrast(20%)',
+    'drop-shadow(0 0 5px green)',
+    'grayscale(100%)',
+    'invert(100%)',
+    'opacity(50%)',
+    'saturate(20%)',
+    'sepia(100%)',
+    'sepia(1) hue-rotate(200deg)',
+    'url(#url)'
+];
+
+function doPaint(ctx, op) {
+  ctx.filter = op;
+  ctx.fillStyle = '#A00';
+  ctx.fillRect(0, 0, 15, 15);
+  ctx.fillStyle = '#0A0';
+  ctx.fillRect(15, 0, 15, 15);
+  ctx.fillStyle = '#00A';
+  ctx.fillRect(0, 15, 15, 15);
+  ctx.fillStyle = "#AA0";
+  ctx.fillRect(15, 15, 15, 15);
+};
+
+for (var i = 0; i < filterOps.length; i++) {
+  let op = filterOps[i];
+  registerPaint(paintNames[i], class { paint(ctx, geom) { doPaint(ctx, op); } });
+}
+</script>
+
+<script>
+    importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-gradient-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-gradient-ref.html
new file mode 100644
index 0000000..a8064f59
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-gradient-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="output" width="200" height="100"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+var linearGradient = ctx.createLinearGradient(0, 0, 100, 100);
+linearGradient.addColorStop(0, 'blue');
+linearGradient.addColorStop(0.5, 'red');
+linearGradient.addColorStop(1, 'white');
+ctx.fillStyle = linearGradient;
+ctx.fillRect(0, 0, 100, 100);
+
+var radialGradient = ctx.createRadialGradient(150, 50, 0, 150, 50, 50);
+radialGradient.addColorStop(0, 'blue');
+radialGradient.addColorStop(0.5, 'red');
+radialGradient.addColorStop(1, 'white');
+ctx.fillStyle = radialGradient;
+ctx.fillRect(100, 0, 100, 100);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-gradient.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-gradient.html
new file mode 100644
index 0000000..b936430
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-gradient.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="paint2d-gradient-ref.html">
+<style>
+    #output {
+        width: 200px;
+        height: 100px;
+        background-image: paint(gradients);
+    }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('gradients', class {
+    paint(ctx, geom) {
+        var linearGradient = ctx.createLinearGradient(0, 0, 100, 100);
+        linearGradient.addColorStop(0, 'blue');
+        linearGradient.addColorStop(0.5, 'red');
+        linearGradient.addColorStop(1, 'white');
+        ctx.fillStyle = linearGradient;
+        ctx.fillRect(0, 0, 100, 100);
+
+        var radialGradient = ctx.createRadialGradient(150, 50, 0, 150, 50, 50);
+        radialGradient.addColorStop(0, 'blue');
+        radialGradient.addColorStop(0.5, 'red');
+        radialGradient.addColorStop(1, 'white');
+        ctx.fillStyle = radialGradient;
+        ctx.fillRect(100, 0, 100, 100);
+    }
+});
+</script>
+
+<script>
+    importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-image-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-image-ref.html
new file mode 100644
index 0000000..31c9f3f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-image-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<canvas id="canvas" width="300" height="300"></canvas>
+
+<script>
+    var canvas = document.getElementById("canvas");
+    var ctx = canvas.getContext("2d");
+    var img = new Image;
+    img.src = "resources/html5.png";
+    img.onload = function() {
+        ctx.drawImage(img, 0, 0);
+    };
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-image.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-image.html
new file mode 100644
index 0000000..5dc7ebf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-image.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="paint2d-image-ref.html">
+<style>
+    #output {
+        width: 300px;
+        height: 300px;
+        background-image: paint(image);
+        border-image: url("resources/html5.png");
+    }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+    registerPaint('image', class {
+        static get inputProperties() { return [ 'border-image-source' ]; };
+        paint(ctx, geom, styleMap) {
+            ctx.drawImage(styleMap.get('border-image-source'), 0, 0);
+        }
+    });
+</script>
+
+<script>
+    importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-paths-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-paths-ref.html
new file mode 100644
index 0000000..7557411b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-paths-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="output" width="300" height="400"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+ctx.beginPath();
+ctx.lineWidth = '10';
+ctx.strokeStyle = 'green';
+ctx.moveTo(15, 15);
+ctx.lineTo(135, 15);
+ctx.lineTo(70, 170);
+ctx.closePath();
+ctx.stroke();
+
+var path1 = new Path2D();
+path1.moveTo(250, 25);
+path1.bezierCurveTo(110, 150, 110, 300, 200, 200);
+ctx.strokeStyle = 'purple';
+ctx.setLineDash([ 10, 5 ]);
+ctx.stroke(path1);
+
+ctx.fillStyle = 'red';
+ctx.beginPath()
+ctx.arc(75, 325, 50, 0, Math.PI * 2, true);
+ctx.arc(75, 325, 20, 0, Math.PI * 2, true);
+ctx.fill('evenodd');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-paths.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-paths.html
new file mode 100644
index 0000000..55a01b4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-paths.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="paint2d-paths-ref.html">
+<style>
+    #output {
+        width: 300px;
+        height: 400px;
+        background-image: paint(paths);
+    }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('paths', class {
+    paint(ctx, geom) {
+        ctx.beginPath();
+        ctx.lineWidth = '10';
+        ctx.strokeStyle = 'green';
+        ctx.moveTo(15, 15);
+        ctx.lineTo(135, 15);
+        ctx.lineTo(70, 170);
+        ctx.closePath();
+        ctx.stroke();
+
+        var path1 = new Path2D();
+        path1.moveTo(250, 25);
+        path1.bezierCurveTo(110, 150, 110, 300, 200, 200);
+        ctx.strokeStyle = 'purple';
+        ctx.setLineDash([ 10, 5 ]);
+        ctx.stroke(path1);
+
+        ctx.fillStyle = 'red';
+        ctx.beginPath()
+        ctx.arc(75, 325, 50, 0, Math.PI * 2, true);
+        ctx.arc(75, 325, 20, 0, Math.PI * 2, true);
+        ctx.fill('evenodd');
+    }
+});
+</script>
+
+<script>
+    importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-rects-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-rects-ref.html
new file mode 100644
index 0000000..fae2de7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-rects-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="output" width="100" height="100" style="background: blue;"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = 'green';
+ctx.fillRect(0, 0, 100, 100);
+
+ctx.clearRect(40, 40, 20, 20);
+
+ctx.strokeStyle = 'red';
+ctx.lineWidth = 4;
+ctx.strokeRect(20, 20, 60, 60);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-rects.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-rects.html
new file mode 100644
index 0000000..24247da2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-rects.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="paint2d-rects-ref.html">
+<style>
+    #output {
+        width: 100px;
+        height: 100px;
+        background-image: paint(rects);
+        background-color: blue;
+    }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('rects', class {
+    paint(ctx, geom) {
+        ctx.fillStyle = 'green';
+        ctx.fillRect(0, 0, geom.width, geom.height);
+
+        ctx.clearRect(40, 40, 20, 20);
+
+        ctx.strokeStyle = 'red';
+        ctx.lineWidth = 4;
+        ctx.strokeRect(20, 20, 60, 60);
+    }
+});
+</script>
+
+<script>
+    importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-shadows-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-shadows-ref.html
new file mode 100644
index 0000000..268db49
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-shadows-ref.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="output" width="200" height="100"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+ctx.shadowColor = 'black';
+ctx.shadowOffsetY = 10;
+ctx.shadowOffsetX = 10;
+ctx.fillStyle = 'green'
+ctx.fillRect(10, 10, 50, 50);
+
+ctx.shadowColor = 'blue';
+ctx.shadowBlur = 10;
+ctx.shadowOffsetX = 5;
+ctx.shadowOffsetY = 5;
+ctx.fillStyle = 'green';
+ctx.fillRect(110, 10, 50, 50);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-shadows.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-shadows.html
new file mode 100644
index 0000000..ad0a1aac
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-shadows.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="paint2d-shadows-ref.html">
+<style>
+    #output {
+        width: 200px;
+        height: 100px;
+        background-image: paint(shadows);
+    }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('shadows', class {
+    paint(ctx, geom) {
+        ctx.shadowColor = 'black';
+        ctx.shadowOffsetY = 10;
+        ctx.shadowOffsetX = 10;
+        ctx.fillStyle = 'green'
+        ctx.fillRect(10, 10, 50, 50);
+
+        ctx.shadowColor = 'blue';
+        ctx.shadowBlur = 10;
+        ctx.shadowOffsetX = 5;
+        ctx.shadowOffsetY = 5;
+        ctx.fillStyle = 'green';
+        ctx.fillRect(110, 10, 50, 50);
+    }
+});
+</script>
+
+<script>
+    importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-transform-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-transform-ref.html
new file mode 100644
index 0000000..e863f36
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-transform-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="output" width="200" height="200"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = 'green';
+ctx.transform(1, 0.5, 0, 1, 20, 20);
+ctx.fillRect(0, 0, 50, 50);
+
+ctx.resetTransform();
+
+ctx.fillStyle = 'blue';
+ctx.translate(150, 60);
+ctx.rotate(60 * Math.PI / 180);
+ctx.scale(1.5, 1);
+ctx.fillRect(0, 0, 50, 50);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-transform.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-transform.html
new file mode 100644
index 0000000..f5b6aa84
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/paint2d-transform.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="paint2d-transform-ref.html">
+<style>
+    #output {
+        width: 200px;
+        height: 200px;
+        background-image: paint(transform);
+    }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('transform', class {
+    paint(ctx, geom) {
+        ctx.fillStyle = 'green';
+        ctx.transform(1, 0.5, 0, 1, 20, 20);
+        ctx.fillRect(0, 0, 50, 50);
+
+        ctx.resetTransform();
+
+        ctx.fillStyle = 'blue';
+        ctx.translate(150, 60);
+        ctx.rotate(60 * Math.PI / 180);
+        ctx.scale(1.5, 1);
+        ctx.fillRect(0, 0, 50, 50);
+    }
+});
+</script>
+
+<script>
+    importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/valid-image-after-load-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/valid-image-after-load-ref.html
new file mode 100644
index 0000000..b6a6dec6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/valid-image-after-load-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div style="background: green; width: 100px; height: 100px"></div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/valid-image-after-load.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/valid-image-after-load.html
new file mode 100644
index 0000000..b1ad0d2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/valid-image-after-load.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="valid-image-after-load-ref.html">
+<style>
+    #output {
+        width: 100px;
+        height: 100px;
+        background-color: red;
+    }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('green', class {
+    paint(ctx, geom) {
+        ctx.fillStyle = 'green';
+        ctx.fillRect(0, 0, geom.width, geom.height);
+    }
+});
+</script>
+
+<script>
+if (window.testRunner) {
+  testRunner.waitUntilDone();
+}
+
+var blob = new Blob([document.getElementById('code').textContent],
+                    {type: 'text/javascript'});
+var frame_cnt = 0;
+paintWorklet.addModule(URL.createObjectURL(blob)).then(function() {
+    var el = document.getElementById('output');
+    el.style.backgroundImage = 'paint(green)';
+    requestAnimationFrame(function() {
+        takeScreenshot(frame_cnt);
+    });
+});
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/valid-image-before-load-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/valid-image-before-load-ref.html
new file mode 100644
index 0000000..b6a6dec6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/valid-image-before-load-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div style="background: green; width: 100px; height: 100px"></div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/valid-image-before-load.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/valid-image-before-load.html
new file mode 100644
index 0000000..b4e6b0e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/valid-image-before-load.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="match" href="valid-image-before-load-ref.html">
+<style>
+    #output {
+        width: 100px;
+        height: 100px;
+        background-color: red;
+    }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('green', class {
+    paint(ctx, geom) {
+        ctx.fillStyle = 'green';
+        ctx.fillRect(0, 0, geom.width, geom.height);
+    }
+});
+</script>
+
+<script>
+if (window.testRunner) {
+  testRunner.waitUntilDone();
+}
+
+var el = document.getElementById('output');
+el.style.backgroundImage = 'paint(green)';
+
+var blob = new Blob([document.getElementById('code').textContent],
+                    {type: 'text/javascript'});
+var frame_cnt = 0;
+paintWorklet.addModule(URL.createObjectURL(blob)).then(function() {
+    requestAnimationFrame(function() {
+        takeScreenshot(frame_cnt);
+    });
+});
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/images/cHRM_color_spin-expected.png b/third_party/WebKit/LayoutTests/images/cHRM_color_spin-expected.png
deleted file mode 100644
index 5286dbfb..0000000
--- a/third_party/WebKit/LayoutTests/images/cHRM_color_spin-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/images/color-jpeg-with-color-profile-expected.png
deleted file mode 100644
index 8114e46..0000000
--- a/third_party/WebKit/LayoutTests/images/color-jpeg-with-color-profile-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-animate-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-animate-expected.png
deleted file mode 100644
index 21f9a15..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-animate-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-animate-rotate-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-animate-rotate-expected.png
deleted file mode 100644
index 5032ce8..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-animate-rotate-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-background-clip-text-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-background-clip-text-expected.png
deleted file mode 100644
index 7ee7d53..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-background-clip-text-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-background-image-cover-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-background-image-cover-expected.png
deleted file mode 100644
index 1a27a04c..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-background-image-cover-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-background-image-repeat-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-background-image-repeat-expected.png
deleted file mode 100644
index 6b1acac1..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-background-image-repeat-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-background-image-space-expected.png
deleted file mode 100644
index f54d8726..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-background-image-space-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-border-fade-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-border-fade-expected.png
deleted file mode 100644
index 16e97dde..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-border-fade-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-border-image-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-border-image-expected.png
deleted file mode 100644
index 36f2f36..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-border-image-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-clip-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-clip-expected.png
deleted file mode 100644
index ff07c6a..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-iframe-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-iframe-expected.png
deleted file mode 100644
index 2edb613..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-iframe-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-image-canvas-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-image-canvas-expected.png
deleted file mode 100644
index bbb07903..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-image-canvas-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-image-canvas-pattern-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-image-canvas-pattern-expected.png
deleted file mode 100644
index 13efa39..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-image-canvas-pattern-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-image-object-fit-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-image-object-fit-expected.png
deleted file mode 100644
index 3e4b818..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-image-object-fit-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-image-pseudo-content-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-image-pseudo-content-expected.png
deleted file mode 100644
index baa7551..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-image-pseudo-content-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-image-svg-resource-url-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-image-svg-resource-url-expected.png
deleted file mode 100644
index 341dc128..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-image-svg-resource-url-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-mask-image-svg-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-mask-image-svg-expected.png
deleted file mode 100644
index e5bda44..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-mask-image-svg-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-munsell-adobe-to-srgb-expected.txt b/third_party/WebKit/LayoutTests/images/color-profile-munsell-adobe-to-srgb-expected.txt
deleted file mode 100644
index 20ccc5c..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-munsell-adobe-to-srgb-expected.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-
-Color         Actual        Expected      dE
---------------------------------------------
-Dark Skin     115,80,65     115,80,64     1
-Light Skin    194,150,130   195,151,130   1
-Blue Sky      94,123,156    94,123,156    0
-Foliage       89,108,65     88,108,65     1
-Blue Flower   130,129,177   130,129,177   0
-Bluish Green  100,190,170   100,190,171   1
---------------------------------------------
-Orange        216,122,37    217,122,37    1
-Purplish Blue 72,91,165     72,91,165     0
-Moderate Red  193,85,98     194,84,98     1
-Purple        91,60,107     91,59,107     1
-Yellow Green  160,187,60    160,188,60    1
-Orange Yellow 230,163,42    230,163,42    0
---------------------------------------------
-Blue          47,60,153     46,60,153     1
-Green         71,149,70     71,150,69     1
-Red           176,45,56     177,44,56     1
-Yellow        239,200,27    238,200,27    1
-Magenta       186,82,147    187,82,148    1
-Cyan (*)      0,135,165     0,135,166     1
---------------------------------------------
-White         243,242,236   243,242,237   1
-Neutral 8     201,201,200   201,201,201   1
-Neutral 6.5   160,161,160   161,161,161   1
-Neutral 5     123,122,121   122,122,121   1
-Neutral 3.5   84,84,84      83,83,83      2
-Black         50,50,50      50,49,50      1
---------------------------------------------
-
-Result: total RMS color error: 0.98
- * Munsell Cyan is outside 255 sRGB gamut
-
-  
-
-
-
-
-
-
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-object-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-object-expected.png
deleted file mode 100644
index 1ee0a34..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-object-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-svg-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-svg-expected.png
deleted file mode 100644
index 5070f24..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-svg-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-svg-foreign-object-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-svg-foreign-object-expected.png
deleted file mode 100644
index e6d8a1d..0000000
--- a/third_party/WebKit/LayoutTests/images/color-profile-svg-foreign-object-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/paletted-png-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/images/paletted-png-with-color-profile-expected.png
index 23c1300..46dcb35 100644
--- a/third_party/WebKit/LayoutTests/images/paletted-png-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/images/paletted-png-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/webp-color-profile-lossless-expected.png b/third_party/WebKit/LayoutTests/images/webp-color-profile-lossless-expected.png
deleted file mode 100644
index 829f86b..0000000
--- a/third_party/WebKit/LayoutTests/images/webp-color-profile-lossless-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/webp-color-profile-lossy-alpha-expected.png b/third_party/WebKit/LayoutTests/images/webp-color-profile-lossy-alpha-expected.png
deleted file mode 100644
index c7c6b39..0000000
--- a/third_party/WebKit/LayoutTests/images/webp-color-profile-lossy-alpha-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/webp-color-profile-lossy-expected.png b/third_party/WebKit/LayoutTests/images/webp-color-profile-lossy-expected.png
deleted file mode 100644
index 37a31d5..0000000
--- a/third_party/WebKit/LayoutTests/images/webp-color-profile-lossy-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/cHRM_color_spin-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/cHRM_color_spin-expected.png
new file mode 100644
index 0000000..a05298a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/cHRM_color_spin-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-jpeg-with-color-profile-expected.png
new file mode 100644
index 0000000..977c381c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-jpeg-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-animate-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-animate-expected.png
new file mode 100644
index 0000000..c34bf0f7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-animate-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-animate-rotate-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-animate-rotate-expected.png
new file mode 100644
index 0000000..cc3f2d5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-animate-rotate-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-clip-text-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-clip-text-expected.png
new file mode 100644
index 0000000..12bc6570
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-clip-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-image-cover-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-image-cover-expected.png
new file mode 100644
index 0000000..04ef9c1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-image-cover-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-image-cross-fade-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-image-cross-fade-expected.png
new file mode 100644
index 0000000..3e8bf73
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-image-cross-fade-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-image-cross-fade-png-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-image-cross-fade-png-expected.png
new file mode 100644
index 0000000..3e8bf73
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-image-cross-fade-png-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-image-repeat-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-image-repeat-expected.png
new file mode 100644
index 0000000..7d888d9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-image-repeat-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-image-space-expected.png
new file mode 100644
index 0000000..c5d0b0f0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-background-image-space-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-border-fade-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-border-fade-expected.png
new file mode 100644
index 0000000..5ae5650
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-border-fade-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-border-image-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-border-image-expected.png
new file mode 100644
index 0000000..e9925129
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-border-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-border-radius-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-border-radius-expected.png
new file mode 100644
index 0000000..6bd21bd4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-border-radius-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-clip-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-clip-expected.png
new file mode 100644
index 0000000..91aac89
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-clip-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-drag-image-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-drag-image-expected.png
new file mode 100644
index 0000000..36809b99
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-drag-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-filter-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-filter-expected.png
new file mode 100644
index 0000000..1dca3d54
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-filter-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-group-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-group-expected.png
new file mode 100644
index 0000000..61f2f036
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-group-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-iframe-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-iframe-expected.png
new file mode 100644
index 0000000..3c24c8e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-iframe-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-canvas-expected.png
new file mode 100644
index 0000000..218f124d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-canvas-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-canvas-pattern-expected.png
new file mode 100644
index 0000000..6f07c20
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-canvas-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-canvas-svg-expected.png
new file mode 100644
index 0000000..c6175ef
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-canvas-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-expected.png
new file mode 100644
index 0000000..41f18a4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-filter-all-expected.png
index fab9e69..b6206d8e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-filter-all-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-filter-all-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-object-fit-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-object-fit-expected.png
new file mode 100644
index 0000000..ec2a82d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-object-fit-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-pseudo-content-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-pseudo-content-expected.png
new file mode 100644
index 0000000..385f12f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-pseudo-content-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-shape-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-shape-expected.png
index 261855ce..0d869b19c 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-shape-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-shape-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-svg-resource-url-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-svg-resource-url-expected.png
new file mode 100644
index 0000000..a7328d1d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-svg-resource-url-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-layer-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-layer-expected.png
index 9576de2..966445d7 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-layer-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-layer-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-layer-filter-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-layer-filter-expected.png
index e575d50..0328d65 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-layer-filter-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-layer-filter-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-mask-image-svg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-mask-image-svg-expected.png
new file mode 100644
index 0000000..5757dc6a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-mask-image-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-munsell-adobe-to-srgb-expected.png
index 2111041..21c130b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-munsell-adobe-to-srgb-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-munsell-adobe-to-srgb-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-munsell-adobe-to-srgb-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-munsell-adobe-to-srgb-expected.txt
new file mode 100644
index 0000000..44eb3b02
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-munsell-adobe-to-srgb-expected.txt
@@ -0,0 +1,42 @@
+
+Color         Actual        Expected      dE
+--------------------------------------------
+Dark Skin     114,80,64     115,80,64     1
+Light Skin    195,150,130   195,151,130   1
+Blue Sky      94,123,156    94,123,156    0
+Foliage       88,108,65     88,108,65     0
+Blue Flower   130,129,177   130,129,177   0
+Bluish Green  100,190,171   100,190,171   0
+--------------------------------------------
+Orange        217,121,37    217,122,37    1
+Purplish Blue 72,90,166     72,91,165     1
+Moderate Red  194,84,97     194,84,98     1
+Purple        90,60,106     91,59,107     2
+Yellow Green  160,188,60    160,188,60    0
+Orange Yellow 231,163,42    230,163,42    1
+--------------------------------------------
+Blue          47,60,153     46,60,153     1
+Green         70,149,69     71,150,69     1
+Red           177,45,56     177,44,56     1
+Yellow        239,200,27    238,200,27    1
+Magenta       187,82,147    187,82,148    1
+Cyan (*)      0,135,166     0,135,166     0
+--------------------------------------------
+White         243,242,236   243,242,237   1
+Neutral 8     202,202,200   201,201,201   2
+Neutral 6.5   160,161,160   161,161,161   1
+Neutral 5     123,121,120   122,122,121   2
+Neutral 3.5   83,83,83      83,83,83      0
+Black         50,50,50      50,49,50      1
+--------------------------------------------
+
+Result: total RMS color error: 1.04
+ * Munsell Cyan is outside 255 sRGB gamut
+
+  
+
+
+
+
+
+
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-object-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-object-expected.png
new file mode 100644
index 0000000..01bf3fd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-object-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-expected.png
new file mode 100644
index 0000000..13240f5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-fill-text-expected.png
index fc79a49..5d8eaeae 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-foreign-object-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-foreign-object-expected.png
new file mode 100644
index 0000000..b9d0f32
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-foreign-object-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/cross-fade-background-size-expected.png
new file mode 100644
index 0000000..11fcc98
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/cross-fade-background-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/jpeg-with-color-profile-expected.png
index fa45ad4..0420018 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/images/jpeg-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/jpeg-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/png-suite/test-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/png-suite/test-expected.png
new file mode 100644
index 0000000..f28c076
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/png-suite/test-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/png-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/png-with-color-profile-expected.png
index fa45ad4..0420018 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/images/png-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/png-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/webp-color-profile-lossless-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/webp-color-profile-lossless-expected.png
new file mode 100644
index 0000000..b2eac244
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/webp-color-profile-lossless-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/webp-color-profile-lossy-alpha-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/webp-color-profile-lossy-alpha-expected.png
new file mode 100644
index 0000000..647765f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/webp-color-profile-lossy-alpha-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/webp-color-profile-lossy-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/webp-color-profile-lossy-expected.png
new file mode 100644
index 0000000..340a356
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/webp-color-profile-lossy-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-drag-image-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-drag-image-expected.png
new file mode 100644
index 0000000..36809b99
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-drag-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-expected.png
index 4f54fc5..03a3ff4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-pattern-expected.png
index 2158746..c6d9e832 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
index ae2355f..17ae7af 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/motion-jpeg-single-frame-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/motion-jpeg-single-frame-expected.png
index ac66499d..5f3feea 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/motion-jpeg-single-frame-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/motion-jpeg-single-frame-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-space-expected.png
index 45c260bd..b846fca 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-space-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-space-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-drag-image-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-drag-image-expected.png
new file mode 100644
index 0000000..36809b99
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-drag-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png
index 704ba37..5338925 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png
index 814ab4a1..197d272 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
index cb2b97af..6f9aa863 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
index 0791b72..58f9d15a 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.txt
new file mode 100644
index 0000000..44eb3b02
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.txt
@@ -0,0 +1,42 @@
+
+Color         Actual        Expected      dE
+--------------------------------------------
+Dark Skin     114,80,64     115,80,64     1
+Light Skin    195,150,130   195,151,130   1
+Blue Sky      94,123,156    94,123,156    0
+Foliage       88,108,65     88,108,65     0
+Blue Flower   130,129,177   130,129,177   0
+Bluish Green  100,190,171   100,190,171   0
+--------------------------------------------
+Orange        217,121,37    217,122,37    1
+Purplish Blue 72,90,166     72,91,165     1
+Moderate Red  194,84,97     194,84,98     1
+Purple        90,60,106     91,59,107     2
+Yellow Green  160,188,60    160,188,60    0
+Orange Yellow 231,163,42    230,163,42    1
+--------------------------------------------
+Blue          47,60,153     46,60,153     1
+Green         70,149,69     71,150,69     1
+Red           177,45,56     177,44,56     1
+Yellow        239,200,27    238,200,27    1
+Magenta       187,82,147    187,82,148    1
+Cyan (*)      0,135,166     0,135,166     0
+--------------------------------------------
+White         243,242,236   243,242,237   1
+Neutral 8     202,202,200   201,201,201   2
+Neutral 6.5   160,161,160   161,161,161   1
+Neutral 5     123,121,120   122,122,121   2
+Neutral 3.5   83,83,83      83,83,83      0
+Black         50,50,50      50,49,50      1
+--------------------------------------------
+
+Result: total RMS color error: 1.04
+ * Munsell Cyan is outside 255 sRGB gamut
+
+  
+
+
+
+
+
+
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-svg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-svg-expected.png
index 13a65a2..b26e8e68 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
index 5672dcf..23428e3 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
index a2ab773..110e837 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/images/color-profile-munsell-adobe-to-srgb-expected.png
index c2f6927..2152282b 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/images/color-profile-munsell-adobe-to-srgb-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/images/color-profile-munsell-adobe-to-srgb-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/images/color-profile-svg-fill-text-expected.png
index eb2d2f3..08343bfa 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
index 78fa092..1707ff76 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
index 31e275b17..3545404 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/images/color-profile-svg-fill-text-expected.png
index 8b3c803..b2aeb5a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
index 5d18dabf..dd84e95 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/cHRM_color_spin-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/cHRM_color_spin-expected.png
new file mode 100644
index 0000000..a05298a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/cHRM_color_spin-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-jpeg-with-color-profile-expected.png
new file mode 100644
index 0000000..977c381c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-jpeg-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-animate-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-animate-expected.png
new file mode 100644
index 0000000..c34bf0f7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-animate-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-animate-rotate-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-animate-rotate-expected.png
new file mode 100644
index 0000000..cc3f2d5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-animate-rotate-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-clip-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-clip-text-expected.png
new file mode 100644
index 0000000..12bc6570
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-clip-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-cover-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-cover-expected.png
new file mode 100644
index 0000000..04ef9c1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-cover-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-cross-fade-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-cross-fade-expected.png
index 62c0608..5827ab7d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-cross-fade-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-cross-fade-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-cross-fade-png-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-cross-fade-png-expected.png
index 62c0608..5827ab7d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-cross-fade-png-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-cross-fade-png-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-repeat-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-repeat-expected.png
new file mode 100644
index 0000000..7d888d9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-repeat-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-space-expected.png
new file mode 100644
index 0000000..c5d0b0f0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-background-image-space-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-border-fade-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-border-fade-expected.png
new file mode 100644
index 0000000..5ae5650
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-border-fade-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-border-image-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-border-image-expected.png
new file mode 100644
index 0000000..e9925129
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-border-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-border-radius-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-border-radius-expected.png
index d9557de..75b980ef 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-border-radius-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-border-radius-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-clip-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-clip-expected.png
new file mode 100644
index 0000000..91aac89
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-clip-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-drag-image-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-drag-image-expected.png
index 1fc9fe1..4ef6fec 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-drag-image-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-drag-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-filter-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-filter-expected.png
index 3422705..1c035e2 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-filter-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-filter-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-group-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-group-expected.png
index 1f81b383..04354ed 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-group-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-group-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-iframe-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-iframe-expected.png
new file mode 100644
index 0000000..3c24c8e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-iframe-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-canvas-expected.png
new file mode 100644
index 0000000..218f124d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-canvas-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-canvas-pattern-expected.png
new file mode 100644
index 0000000..6f07c20
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-canvas-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-canvas-svg-expected.png
index d359ffc..fa863df7 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-canvas-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-canvas-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-expected.png
index 8d47b0ff..fdb2bd3 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-filter-all-expected.png
index fcd0652f..b8333e5 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-filter-all-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-filter-all-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-object-fit-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-object-fit-expected.png
new file mode 100644
index 0000000..ec2a82d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-object-fit-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-pseudo-content-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-pseudo-content-expected.png
new file mode 100644
index 0000000..385f12f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-pseudo-content-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-shape-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-shape-expected.png
index 1cbc88ff3..18e442a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-shape-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-shape-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-svg-resource-url-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-svg-resource-url-expected.png
new file mode 100644
index 0000000..a7328d1d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-svg-resource-url-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-layer-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-layer-expected.png
index 69ad073..62a796c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-layer-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-layer-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-layer-filter-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-layer-filter-expected.png
index e575d50..0328d65 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-layer-filter-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-layer-filter-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-mask-image-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-mask-image-svg-expected.png
new file mode 100644
index 0000000..5757dc6a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-mask-image-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-munsell-adobe-to-srgb-expected.png
index 7c29dbb0..522c84c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-munsell-adobe-to-srgb-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-munsell-adobe-to-srgb-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-munsell-adobe-to-srgb-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-munsell-adobe-to-srgb-expected.txt
new file mode 100644
index 0000000..44eb3b02
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-munsell-adobe-to-srgb-expected.txt
@@ -0,0 +1,42 @@
+
+Color         Actual        Expected      dE
+--------------------------------------------
+Dark Skin     114,80,64     115,80,64     1
+Light Skin    195,150,130   195,151,130   1
+Blue Sky      94,123,156    94,123,156    0
+Foliage       88,108,65     88,108,65     0
+Blue Flower   130,129,177   130,129,177   0
+Bluish Green  100,190,171   100,190,171   0
+--------------------------------------------
+Orange        217,121,37    217,122,37    1
+Purplish Blue 72,90,166     72,91,165     1
+Moderate Red  194,84,97     194,84,98     1
+Purple        90,60,106     91,59,107     2
+Yellow Green  160,188,60    160,188,60    0
+Orange Yellow 231,163,42    230,163,42    1
+--------------------------------------------
+Blue          47,60,153     46,60,153     1
+Green         70,149,69     71,150,69     1
+Red           177,45,56     177,44,56     1
+Yellow        239,200,27    238,200,27    1
+Magenta       187,82,147    187,82,148    1
+Cyan (*)      0,135,166     0,135,166     0
+--------------------------------------------
+White         243,242,236   243,242,237   1
+Neutral 8     202,202,200   201,201,201   2
+Neutral 6.5   160,161,160   161,161,161   1
+Neutral 5     123,121,120   122,122,121   2
+Neutral 3.5   83,83,83      83,83,83      0
+Black         50,50,50      50,49,50      1
+--------------------------------------------
+
+Result: total RMS color error: 1.04
+ * Munsell Cyan is outside 255 sRGB gamut
+
+  
+
+
+
+
+
+
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-object-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-object-expected.png
new file mode 100644
index 0000000..01bf3fd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-object-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-expected.png
new file mode 100644
index 0000000..13240f5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-fill-text-expected.png
index 90d5b87b..5773e7e 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-foreign-object-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-foreign-object-expected.png
new file mode 100644
index 0000000..b9d0f32
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-foreign-object-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/cross-fade-background-size-expected.png
index d65d9f0..1bd3c48 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/cross-fade-background-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/cross-fade-background-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/jpeg-with-color-profile-expected.png
index 5f1c56e..a910e01 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/jpeg-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/jpeg-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/png-suite/test-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/png-suite/test-expected.png
index 5205383..b61ee4e8 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/png-suite/test-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/png-suite/test-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/png-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/png-with-color-profile-expected.png
index 5f1c56e..a910e01 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/png-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/png-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/webp-color-profile-lossless-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/webp-color-profile-lossless-expected.png
new file mode 100644
index 0000000..b2eac244
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/webp-color-profile-lossless-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/webp-color-profile-lossy-alpha-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/webp-color-profile-lossy-alpha-expected.png
new file mode 100644
index 0000000..647765f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/webp-color-profile-lossy-alpha-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/webp-color-profile-lossy-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/webp-color-profile-lossy-expected.png
new file mode 100644
index 0000000..340a356
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/webp-color-profile-lossy-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-drag-image-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-drag-image-expected.png
new file mode 100644
index 0000000..4ef6fec
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-drag-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-expected.png
index 4f54fc5..03a3ff4 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-pattern-expected.png
index 2158746..c6d9e832 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
index 07146811..7c31ef7d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/motion-jpeg-single-frame-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/motion-jpeg-single-frame-expected.png
index ac66499d..5f3feea 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/motion-jpeg-single-frame-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/motion-jpeg-single-frame-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-space-expected.png
index 45c260bd..b846fca 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-space-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-space-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-drag-image-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-drag-image-expected.png
index 1fc9fe1..4ef6fec 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-drag-image-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-drag-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png
index 704ba37..5338925 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png
index 814ab4a1..197d272 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
index d0d1192..95ed5a56 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
index 2ebfc28..d6b9921 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.txt
new file mode 100644
index 0000000..44eb3b02
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.txt
@@ -0,0 +1,42 @@
+
+Color         Actual        Expected      dE
+--------------------------------------------
+Dark Skin     114,80,64     115,80,64     1
+Light Skin    195,150,130   195,151,130   1
+Blue Sky      94,123,156    94,123,156    0
+Foliage       88,108,65     88,108,65     0
+Blue Flower   130,129,177   130,129,177   0
+Bluish Green  100,190,171   100,190,171   0
+--------------------------------------------
+Orange        217,121,37    217,122,37    1
+Purplish Blue 72,90,166     72,91,165     1
+Moderate Red  194,84,97     194,84,98     1
+Purple        90,60,106     91,59,107     2
+Yellow Green  160,188,60    160,188,60    0
+Orange Yellow 231,163,42    230,163,42    1
+--------------------------------------------
+Blue          47,60,153     46,60,153     1
+Green         70,149,69     71,150,69     1
+Red           177,45,56     177,44,56     1
+Yellow        239,200,27    238,200,27    1
+Magenta       187,82,147    187,82,148    1
+Cyan (*)      0,135,166     0,135,166     0
+--------------------------------------------
+White         243,242,236   243,242,237   1
+Neutral 8     202,202,200   201,201,201   2
+Neutral 6.5   160,161,160   161,161,161   1
+Neutral 5     123,121,120   122,122,121   2
+Neutral 3.5   83,83,83      83,83,83      0
+Black         50,50,50      50,49,50      1
+--------------------------------------------
+
+Result: total RMS color error: 1.04
+ * Munsell Cyan is outside 255 sRGB gamut
+
+  
+
+
+
+
+
+
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-svg-expected.png
index 13a65a2..b26e8e68 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
index c4d1829..1f6447a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
index 61e7160..8182872 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/cHRM_color_spin-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/cHRM_color_spin-expected.png
new file mode 100644
index 0000000..c58d78c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/cHRM_color_spin-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-jpeg-with-color-profile-expected.png
new file mode 100644
index 0000000..fffe3ce
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-jpeg-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-animate-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-animate-expected.png
new file mode 100644
index 0000000..1d3c5cf6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-animate-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-animate-rotate-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-animate-rotate-expected.png
new file mode 100644
index 0000000..4b6946aa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-animate-rotate-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-clip-text-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-clip-text-expected.png
new file mode 100644
index 0000000..cd6c30e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-clip-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-cover-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-cover-expected.png
new file mode 100644
index 0000000..9d54f38
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-cover-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-cross-fade-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-cross-fade-expected.png
index e5ed6397..9bb2f0e 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-cross-fade-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-cross-fade-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-cross-fade-png-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-cross-fade-png-expected.png
index e5ed6397..9bb2f0e 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-cross-fade-png-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-cross-fade-png-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-repeat-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-repeat-expected.png
new file mode 100644
index 0000000..17674ff
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-repeat-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-space-expected.png
new file mode 100644
index 0000000..37132b9d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-background-image-space-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-border-fade-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-border-fade-expected.png
new file mode 100644
index 0000000..81f8e58
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-border-fade-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-border-image-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-border-image-expected.png
new file mode 100644
index 0000000..842b376
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-border-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-border-radius-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-border-radius-expected.png
index 921ed9d2..6e35e92 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-border-radius-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-border-radius-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-clip-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-clip-expected.png
new file mode 100644
index 0000000..ae2c4fae
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-clip-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-drag-image-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-drag-image-expected.png
index 938db221..659899c1 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-drag-image-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-drag-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-filter-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-filter-expected.png
index 7c96b563..2aa3e7e 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-filter-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-filter-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-group-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-group-expected.png
index e5d69163..45a17476 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-group-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-group-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-iframe-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-iframe-expected.png
new file mode 100644
index 0000000..56e40aa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-iframe-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-canvas-expected.png
new file mode 100644
index 0000000..4184891
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-canvas-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-canvas-pattern-expected.png
new file mode 100644
index 0000000..3f6f4b8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-canvas-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-canvas-svg-expected.png
index c1e917b..042f085 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-canvas-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-canvas-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-expected.png
index 05c7b17..27af8d9 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-filter-all-expected.png
index 1a13dce..7f92261 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-filter-all-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-filter-all-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-object-fit-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-object-fit-expected.png
new file mode 100644
index 0000000..285a199f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-object-fit-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-pseudo-content-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-pseudo-content-expected.png
new file mode 100644
index 0000000..92cebe7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-pseudo-content-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-shape-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-shape-expected.png
index aeb8341..e5f9356 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-shape-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-shape-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-svg-resource-url-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-svg-resource-url-expected.png
new file mode 100644
index 0000000..16d4a424
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-svg-resource-url-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-layer-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-layer-expected.png
index 19ac0d89..3ffae8c 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-layer-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-layer-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-layer-filter-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-layer-filter-expected.png
index 0857f456..3bcb94e 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-layer-filter-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-layer-filter-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-mask-image-svg-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-mask-image-svg-expected.png
new file mode 100644
index 0000000..fc34f08
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-mask-image-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-munsell-adobe-to-srgb-expected.png
index e13ea91..a7c575d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-munsell-adobe-to-srgb-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-munsell-adobe-to-srgb-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-munsell-adobe-to-srgb-expected.txt b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-munsell-adobe-to-srgb-expected.txt
new file mode 100644
index 0000000..07a3654
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-munsell-adobe-to-srgb-expected.txt
@@ -0,0 +1,42 @@
+
+Color         Actual        Expected      dE
+--------------------------------------------
+Dark Skin     114,80,64     115,80,64     1
+Light Skin    195,150,130   195,151,130   1
+Blue Sky      94,122,157    94,123,156    1
+Foliage       88,108,65     88,108,65     0
+Blue Flower   130,129,177   130,129,177   0
+Bluish Green  100,191,171   100,190,171   1
+--------------------------------------------
+Orange        217,121,37    217,122,37    1
+Purplish Blue 72,90,166     72,91,165     1
+Moderate Red  194,84,97     194,84,98     1
+Purple        90,60,106     91,59,107     2
+Yellow Green  160,188,60    160,188,60    0
+Orange Yellow 231,163,42    230,163,42    1
+--------------------------------------------
+Blue          47,60,153     46,60,153     1
+Green         70,149,69     71,150,69     1
+Red           177,44,56     177,44,56     0
+Yellow        239,200,27    238,200,27    1
+Magenta       187,82,147    187,82,148    1
+Cyan (*)      0,135,166     0,135,166     0
+--------------------------------------------
+White         243,242,237   243,242,237   0
+Neutral 8     201,201,200   201,201,201   1
+Neutral 6.5   160,161,160   161,161,161   1
+Neutral 5     123,121,120   122,122,121   2
+Neutral 3.5   83,83,83      83,83,83      0
+Black         50,50,50      50,49,50      1
+--------------------------------------------
+
+Result: total RMS color error: 0.98
+ * Munsell Cyan is outside 255 sRGB gamut
+
+  
+
+
+
+
+
+
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-object-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-object-expected.png
new file mode 100644
index 0000000..af04af6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-object-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-expected.png
new file mode 100644
index 0000000..7dc5cb6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-fill-text-expected.png
index 9dbd9b6..3cf8370 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-foreign-object-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-foreign-object-expected.png
new file mode 100644
index 0000000..2619eeaf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-foreign-object-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/cross-fade-background-size-expected.png
index 723ea2f..7ec4ebf 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/cross-fade-background-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/cross-fade-background-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/jpeg-with-color-profile-expected.png
index 34fb0bf8..862e3abd 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/jpeg-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/jpeg-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/png-suite/test-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/png-suite/test-expected.png
index 2b557807..f3ab422 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/png-suite/test-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/png-suite/test-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/png-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/png-with-color-profile-expected.png
index 34fb0bf8..862e3abd 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/png-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/png-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/webp-color-profile-lossless-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/webp-color-profile-lossless-expected.png
new file mode 100644
index 0000000..1ac3b74
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/webp-color-profile-lossless-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/webp-color-profile-lossy-alpha-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/webp-color-profile-lossy-alpha-expected.png
new file mode 100644
index 0000000..f47b1d8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/webp-color-profile-lossy-alpha-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/webp-color-profile-lossy-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/webp-color-profile-lossy-expected.png
new file mode 100644
index 0000000..cd5662e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/webp-color-profile-lossy-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-drag-image-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-drag-image-expected.png
new file mode 100644
index 0000000..659899c1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-drag-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-canvas-expected.png
index bd54921..2f9eab5 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-canvas-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-canvas-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-canvas-pattern-expected.png
index 5610619..94f2a00 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-canvas-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-canvas-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
index 268f59d5..f70a25e 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-profile-match-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-profile-match-expected.png
index 6a45cb0..4fa96d9 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-profile-match-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-profile-match-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/jpeg-yuv-progressive-image-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/jpeg-yuv-progressive-image-expected.png
index d8aa952..d08af7d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/jpeg-yuv-progressive-image-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/jpeg-yuv-progressive-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/motion-jpeg-single-frame-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/motion-jpeg-single-frame-expected.png
index a05c100..4647e729 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/motion-jpeg-single-frame-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/motion-jpeg-single-frame-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-space-expected.png
index e7469c4..ccdc16fa 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-space-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-space-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-drag-image-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-drag-image-expected.png
index 938db221..659899c1 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-drag-image-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-drag-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png
index 13102cc..008788d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png
index c42e54a3..8a3fbd56 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
index a28c2e7..19fdb2b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
index bb8ee48..1e766924 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.txt
new file mode 100644
index 0000000..07a3654
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.txt
@@ -0,0 +1,42 @@
+
+Color         Actual        Expected      dE
+--------------------------------------------
+Dark Skin     114,80,64     115,80,64     1
+Light Skin    195,150,130   195,151,130   1
+Blue Sky      94,122,157    94,123,156    1
+Foliage       88,108,65     88,108,65     0
+Blue Flower   130,129,177   130,129,177   0
+Bluish Green  100,191,171   100,190,171   1
+--------------------------------------------
+Orange        217,121,37    217,122,37    1
+Purplish Blue 72,90,166     72,91,165     1
+Moderate Red  194,84,97     194,84,98     1
+Purple        90,60,106     91,59,107     2
+Yellow Green  160,188,60    160,188,60    0
+Orange Yellow 231,163,42    230,163,42    1
+--------------------------------------------
+Blue          47,60,153     46,60,153     1
+Green         70,149,69     71,150,69     1
+Red           177,44,56     177,44,56     0
+Yellow        239,200,27    238,200,27    1
+Magenta       187,82,147    187,82,148    1
+Cyan (*)      0,135,166     0,135,166     0
+--------------------------------------------
+White         243,242,237   243,242,237   0
+Neutral 8     201,201,200   201,201,201   1
+Neutral 6.5   160,161,160   161,161,161   1
+Neutral 5     123,121,120   122,122,121   2
+Neutral 3.5   83,83,83      83,83,83      0
+Black         50,50,50      50,49,50      1
+--------------------------------------------
+
+Result: total RMS color error: 0.98
+ * Munsell Cyan is outside 255 sRGB gamut
+
+  
+
+
+
+
+
+
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-svg-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-svg-expected.png
index 7afe6939..cf1d5f50 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
index 4b3375a9..42b3df29 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
index 7c8e5da..42595f8 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/Source/core/events/EventTarget.cpp b/third_party/WebKit/Source/core/events/EventTarget.cpp
index 3fc24eb..54b08f2 100644
--- a/third_party/WebKit/Source/core/events/EventTarget.cpp
+++ b/third_party/WebKit/Source/core/events/EventTarget.cpp
@@ -43,10 +43,12 @@
 #include "core/events/Event.h"
 #include "core/events/EventUtil.h"
 #include "core/events/PointerEvent.h"
+#include "core/frame/FrameConsole.h"
 #include "core/frame/LocalDOMWindow.h"
 #include "core/frame/PerformanceMonitor.h"
 #include "core/frame/Settings.h"
 #include "core/frame/UseCounter.h"
+#include "core/inspector/ConsoleMessage.h"
 #include "core/probe/CoreProbes.h"
 #include "platform/EventDispatchForbiddenScope.h"
 #include "platform/Histogram.h"
@@ -241,7 +243,16 @@
         if (executing_window) {
           UseCounter::Count(executing_window->document(),
                             WebFeature::kSmoothScrollJSInterventionActivated);
+
+          executing_window->GetFrame()->Console().AddMessage(
+              ConsoleMessage::Create(
+                  kInterventionMessageSource, kWarningMessageLevel,
+                  "Registering mousewheel event as passive due to "
+                  "smoothscroll.js usage. The smoothscroll.js library is "
+                  "buggy, no longer necessary and degrades performance. See "
+                  "https://www.chromestatus.com/feature/5749447073988608"));
         }
+
         return;
       }
     }
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
index ecaa21a9..25fd42f 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -1404,8 +1404,7 @@
   layout_size.SetHeight(layout_view_item.ViewHeight(kIncludeScrollbars) / zoom);
 
   BrowserControls& browser_controls = frame_->GetPage()->GetBrowserControls();
-  if (RuntimeEnabledFeatures::InertTopControlsEnabled() &&
-      browser_controls.PermittedState() != kWebBrowserControlsHidden) {
+  if (browser_controls.PermittedState() != kWebBrowserControlsHidden) {
     // We use the layoutSize rather than frameRect to calculate viewport units
     // so that we get correct results on mobile where the page is laid out into
     // a rect that may be larger than the viewport (e.g. the 980px fallback
@@ -1652,8 +1651,7 @@
 
   ShowOverlayScrollbars();
 
-  if (RuntimeEnabledFeatures::InertTopControlsEnabled() && GetLayoutView() &&
-      frame_->IsMainFrame() &&
+  if (GetLayoutView() && frame_->IsMainFrame() &&
       frame_->GetPage()->GetBrowserControls().Height()) {
     if (GetLayoutView()->Style()->HasFixedBackgroundImage()) {
       // In the case where we don't change layout size from top control resizes,
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
index 31898e96..d0bb6c8 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
@@ -527,10 +527,6 @@
       status: "experimental",
     },
     {
-      name: "InertTopControls",
-      status: "stable",
-    },
-    {
       name: "InputEvent",
       status: "stable",
     },
@@ -973,7 +969,7 @@
     },
     {
       name: "SmoothScrollJSIntervention",
-      status: "experimental",
+      status: "stable",
     },
     // Used as argument in attribute of stable-release functions/interfaces
     // where a runtime-enabled feature name is required for correct IDL syntax.
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp
index 458a596..4677ee01 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.cpp
+++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -1798,8 +1798,7 @@
   // controls hide so that the ICB will always be the same size as the
   // viewport with the browser controls shown.
   IntSize icb_size = size_;
-  if (RuntimeEnabledFeatures::InertTopControlsEnabled() &&
-      GetBrowserControls().PermittedState() == kWebBrowserControlsBoth &&
+  if (GetBrowserControls().PermittedState() == kWebBrowserControlsBoth &&
       !GetBrowserControls().ShrinkViewport())
     icb_size.Expand(0, -GetBrowserControls().Height());
 
diff --git a/third_party/WebKit/Source/web/tests/BrowserControlsTest.cpp b/third_party/WebKit/Source/web/tests/BrowserControlsTest.cpp
index 0c9074c3..074ac878 100644
--- a/third_party/WebKit/Source/web/tests/BrowserControlsTest.cpp
+++ b/third_party/WebKit/Source/web/tests/BrowserControlsTest.cpp
@@ -71,8 +71,6 @@
   }
 
   WebViewBase* Initialize(const std::string& page_name = "large-div.html") {
-    RuntimeEnabledFeatures::SetInertTopControlsEnabled(true);
-
     // Load a page with large body and set viewport size to 400x400 to ensure
     // main frame is scrollable.
     helper_.InitializeAndLoad(base_url_ + page_name, true, nullptr, nullptr,
diff --git a/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp b/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
index 7b4e83deb..676b4e0 100644
--- a/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
+++ b/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
@@ -2111,10 +2111,6 @@
 // Make sure a composited background-attachment:fixed background gets resized
 // when using inert (non-layout affecting) browser controls.
 TEST_P(VisualViewportTest, ResizeCompositedAndFixedBackground) {
-  bool originalInertTopControls =
-      RuntimeEnabledFeatures::InertTopControlsEnabled();
-  RuntimeEnabledFeatures::SetInertTopControlsEnabled(true);
-
   std::unique_ptr<FrameTestHelpers::TestWebViewClient>
       fake_compositing_web_view_client =
           WTF::MakeUnique<FrameTestHelpers::TestWebViewClient>();
@@ -2181,8 +2177,6 @@
   EXPECT_EQ(page_width, compositor->FixedRootBackgroundLayer()->Size().Width());
   EXPECT_EQ(page_height,
             compositor->FixedRootBackgroundLayer()->Size().Height());
-
-  RuntimeEnabledFeatures::SetInertTopControlsEnabled(originalInertTopControls);
 }
 
 static void configureAndroidNonCompositing(WebSettings* settings) {
@@ -2197,10 +2191,6 @@
 // Make sure a non-composited background-attachment:fixed background gets
 // resized when using inert (non-layout affecting) browser controls.
 TEST_P(VisualViewportTest, ResizeNonCompositedAndFixedBackground) {
-  bool originalInertTopControls =
-      RuntimeEnabledFeatures::InertTopControlsEnabled();
-  RuntimeEnabledFeatures::SetInertTopControlsEnabled(true);
-
   FrameTestHelpers::WebViewHelper web_view_helper;
   WebViewBase* web_view_impl = web_view_helper.Initialize(
       true, nullptr, nullptr, nullptr, &configureAndroidNonCompositing);
@@ -2295,16 +2285,11 @@
             (*raster_invalidations)[0].rect);
 
   document->View()->SetTracksPaintInvalidations(false);
-  RuntimeEnabledFeatures::SetInertTopControlsEnabled(originalInertTopControls);
 }
 
 // Make sure a browser control resize with background-attachment:not-fixed
 // background doesn't cause invalidation or layout.
 TEST_P(VisualViewportTest, ResizeNonFixedBackgroundNoLayoutOrInvalidation) {
-  bool originalInertTopControls =
-      RuntimeEnabledFeatures::InertTopControlsEnabled();
-  RuntimeEnabledFeatures::SetInertTopControlsEnabled(true);
-
   std::unique_ptr<FrameTestHelpers::TestWebViewClient>
       fake_compositing_web_view_client =
           WTF::MakeUnique<FrameTestHelpers::TestWebViewClient>();
@@ -2381,14 +2366,9 @@
     EXPECT_FALSE(invalidation_tracking);
 
   document->View()->SetTracksPaintInvalidations(false);
-  RuntimeEnabledFeatures::SetInertTopControlsEnabled(originalInertTopControls);
 }
 
 TEST_P(VisualViewportTest, InvalidateLayoutViewWhenDocumentSmallerThanView) {
-  bool originalInertTopControls =
-      RuntimeEnabledFeatures::InertTopControlsEnabled();
-  RuntimeEnabledFeatures::SetInertTopControlsEnabled(true);
-
   std::unique_ptr<FrameTestHelpers::TestWebViewClient>
       fake_compositing_web_view_client =
           WTF::MakeUnique<FrameTestHelpers::TestWebViewClient>();
@@ -2435,7 +2415,6 @@
   }
 
   document->View()->SetTracksPaintInvalidations(false);
-  RuntimeEnabledFeatures::SetInertTopControlsEnabled(originalInertTopControls);
 }
 
 // Make sure we don't crash when the visual viewport's height is 0. This can
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py
index b2b67e3..7867317 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py
@@ -100,10 +100,9 @@
         self._printer.write_update('Collecting tests ...')
         running_all_tests = False
 
-        try:
+        if not args or any('external' in path for path in args):
             self._printer.write_update('Generating MANIFEST.json for web-platform-tests ...')
             WPTManifest.ensure_manifest(self._port.host)
-        finally:
             self._printer.write_update('Completed generating manifest.')
 
         self._printer.write_update('Collecting tests ...')
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py
index f718cde..f2c6c8f 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py
@@ -1107,7 +1107,7 @@
             tests_included=True, host=host)
         file_list = host.filesystem.written_files.keys()
         self.assertEqual(details.exit_code, 0)
-        self.assertEqual(len(file_list), 9)
+        self.assertEqual(len(file_list), 8)
         self.assert_baselines(file_list, 'failures/unexpected/text-image-checksum', ['.txt', '.png'], err)
 
     def test_reset_missing_results(self):
@@ -1120,7 +1120,7 @@
                                       tests_included=True, host=host)
         file_list = host.filesystem.written_files.keys()
         self.assertEqual(details.exit_code, 0)
-        self.assertEqual(len(file_list), 10)
+        self.assertEqual(len(file_list), 9)
         self.assert_baselines(file_list, 'failures/unexpected/missing_text', ['.txt'], err)
         self.assert_baselines(file_list, 'failures/unexpected/missing_image', ['.png'], err)
         self.assert_baselines(file_list, 'failures/unexpected/missing_render_tree_dump', ['.txt'], err)
@@ -1141,7 +1141,7 @@
             tests_included=True, host=host)
         file_list = host.filesystem.written_files.keys()
         self.assertEqual(details.exit_code, 0)
-        self.assertEqual(len(file_list), 9)
+        self.assertEqual(len(file_list), 8)
         self.assert_baselines(file_list,
                               'platform/test-mac-mac10.10/failures/unexpected/text-image-checksum',
                               ['.png'], err)
@@ -1163,7 +1163,7 @@
             tests_included=True, host=host)
         file_list = host.filesystem.written_files.keys()
         self.assertEqual(details.exit_code, 0)
-        self.assertEqual(len(file_list), 9)
+        self.assertEqual(len(file_list), 8)
         # We should create new pixel baseline only.
         self.assertFalse(
             host.filesystem.exists(
@@ -1179,7 +1179,7 @@
         details, err, _ = logging_run(['--reset-results', 'passes/reftest.html'], tests_included=True, host=host)
         file_list = host.filesystem.written_files.keys()
         self.assertEqual(details.exit_code, 0)
-        self.assertEqual(len(file_list), 7)
+        self.assertEqual(len(file_list), 6)
         self.assert_baselines(file_list, '', [], err)
 
         host.filesystem.write_text_file(test.LAYOUT_TEST_DIR + '/passes/reftest-expected.txt', '')
diff --git a/third_party/boringssl/BUILD.generated.gni b/third_party/boringssl/BUILD.generated.gni
index e3eb76a3..35d948c3 100644
--- a/third_party/boringssl/BUILD.generated.gni
+++ b/third_party/boringssl/BUILD.generated.gni
@@ -372,6 +372,29 @@
   "src/ssl/tls_record.c",
 ]
 
+crypto_sources_ios_aarch64 = [
+  "ios-aarch64/crypto/chacha/chacha-armv8.S",
+  "ios-aarch64/crypto/fipsmodule/aesv8-armx64.S",
+  "ios-aarch64/crypto/fipsmodule/armv8-mont.S",
+  "ios-aarch64/crypto/fipsmodule/ghashv8-armx64.S",
+  "ios-aarch64/crypto/fipsmodule/sha1-armv8.S",
+  "ios-aarch64/crypto/fipsmodule/sha256-armv8.S",
+  "ios-aarch64/crypto/fipsmodule/sha512-armv8.S",
+]
+
+crypto_sources_ios_arm = [
+  "ios-arm/crypto/chacha/chacha-armv4.S",
+  "ios-arm/crypto/fipsmodule/aes-armv4.S",
+  "ios-arm/crypto/fipsmodule/aesv8-armx32.S",
+  "ios-arm/crypto/fipsmodule/armv4-mont.S",
+  "ios-arm/crypto/fipsmodule/bsaes-armv7.S",
+  "ios-arm/crypto/fipsmodule/ghash-armv4.S",
+  "ios-arm/crypto/fipsmodule/ghashv8-armx32.S",
+  "ios-arm/crypto/fipsmodule/sha1-armv4-large.S",
+  "ios-arm/crypto/fipsmodule/sha256-armv4.S",
+  "ios-arm/crypto/fipsmodule/sha512-armv4.S",
+]
+
 crypto_sources_linux_aarch64 = [
   "linux-aarch64/crypto/chacha/chacha-armv8.S",
   "linux-aarch64/crypto/fipsmodule/aesv8-armx64.S",
diff --git a/third_party/boringssl/BUILD.generated_tests.gni b/third_party/boringssl/BUILD.generated_tests.gni
index 842e12e..d507a9c3 100644
--- a/third_party/boringssl/BUILD.generated_tests.gni
+++ b/third_party/boringssl/BUILD.generated_tests.gni
@@ -37,6 +37,7 @@
   "src/crypto/ecdh/ecdh_test.cc",
   "src/crypto/err/err_test.cc",
   "src/crypto/evp/evp_extra_test.cc",
+  "src/crypto/evp/evp_test.cc",
   "src/crypto/evp/pbkdf_test.cc",
   "src/crypto/fipsmodule/aes/aes_test.cc",
   "src/crypto/fipsmodule/bn/bn_test.cc",
@@ -67,18 +68,6 @@
 ]
 
 template("create_tests") {
-  executable("boringssl_evp_test") {
-    sources = [
-      "src/crypto/evp/evp_test.cc",
-    ]
-    sources += test_support_sources
-    if (defined(invoker.configs_exclude)) {
-      configs -= invoker.configs_exclude
-    }
-    configs += invoker.configs
-    deps = invoker.deps + [ "//build/config:exe_and_shlib_deps" ]
-  }
-
   executable("boringssl_example_mul") {
     sources = [
       "src/crypto/fipsmodule/ec/example_mul.c",
@@ -129,7 +118,6 @@
 
   group(target_name) {
     deps = [
-      ":boringssl_evp_test",
       ":boringssl_example_mul",
       ":boringssl_p256-x86_64_test",
       ":boringssl_tab_test",
diff --git a/third_party/boringssl/crypto_test_data.cc b/third_party/boringssl/crypto_test_data.cc
index c75551fa..85cd414 100644
--- a/third_party/boringssl/crypto_test_data.cc
+++ b/third_party/boringssl/crypto_test_data.cc
@@ -46,6 +46,7 @@
  *       crypto/cipher_extra/test/nist_cavp/tdes_ecb.txt \
  *       crypto/curve25519/ed25519_tests.txt \
  *       crypto/ecdh/ecdh_tests.txt \
+ *       crypto/evp/evp_tests.txt \
  *       crypto/fipsmodule/aes/aes_tests.txt \
  *       crypto/fipsmodule/bn/bn_tests.txt \
  *       crypto/fipsmodule/ecdsa/ecdsa_sign_tests.txt \
@@ -2410,11 +2411,30 @@
 static const size_t kLen31 = 58307;
 
 static const char *kData32[] = {
-    "# Test vectors from FIPS-197, Appendix C.\n\nMode = Raw\nKey = 000102030405060708090a0b0c0d0e0f\nPlaintext = 00112233445566778899aabbccddeeff\nCiphertext = 69c4e0d86a7b0430d8cdb78070b4c55a\n\nMode = Raw\nKey = 000102030405060708090a0b0c0d0e0f1011121314151617\nPlaintext = 00112233445566778899aabbccddeeff\nCiphertext = dda97ca4864cdfe06eaf70a0ec0d7191\n\nMode = Raw\nKey = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\nPlaintext = 00112233445566778899aabbccddeeff\nCiphertext = 8ea2b7ca516745bfeafc49904b496089\n\n\n# Test vectors from\n# http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf\n\nMode = KeyWrap\nKey = 000102030405060708090a0b0c0d0e0f\nPlaintext = 00112233445566778899aabbccddeeff\nCiphertext = 1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5\n\nMode = KeyWrap\nKey = 000102030405060708090a0b0c0d0e0f1011121314151617\nPlaintext = 00112233445566778899aabbccddeeff\nCiphertext = 96778b25ae6ca435f92b5b97c050aed2468ab8a17ad84e5d\n\nMode = KeyWrap\nKey = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\nPlaintext = 00112233445566778899aabbccddeeff\nCiphertext = 64e8c3f9ce0f5ba263e9777905818a2a93c8191e7d6e8ae7\n\nMode = KeyWrap\nKey = 000102030405060708090a0b0c0d0e0f1011121314151617\nPlaintext = 00112233445566778899aabbccddeeff0001020304050607\nCiphertext = 031d33264e15d33268f24ec260743edce1c6c7ddee725a936ba814915c6762d2\n\nMode = KeyWrap\nKey = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\nPlaintext = 00112233445566778899aabbccddeeff0001020304050607\nCiphertext = a8f9bc1612c68b3ff6e6f4fbe30e71e4769c8b80a32cb8958cd5d17d6b254da1\n\nMode = KeyWrap\nKey = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\nPlaintext = 00112233445566778899aabbccddeeff000102030405060708090a0b0c0d0e0f\nCiphertext = 28c9f404c4b810f4cbccb35cfb87f8263f5786e2d80ed326cbc7f0e71a99f43bfb988b9b7a02dd21\n",
+    "# Public key algorithm tests\n\n# Keys used for PKEY operations.\n\n# RSA 2048 bit key.\nPrivateKey = RSA-2048\nType = RSA\nInput = 308204bc020100300d06092a864886f70d0101010500048204a6308204a20201000282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f02030100010282010060297ac7991b167a06d6b24758b8cbe208beb9b2d9ec9738bd80f90a2e35005dd7ce292d9e29ba885bd316fef1f20913bc0ac90d6b0808b2414d82104441d8624a33ce0233c8f780a48b375aff02d76712228a702484db3f9ebecccfbbee1709dba182800d949e9e4216e0bff3558388f8bd90da373a1d82743ec3fbdd1427fd16825a657a316912e8695365117ca2f845c909405fcac55f895fc15d20386c26ee78c9e99075029a178a6c1e4cf0c200e8a9cfb27e9d156f86e6c2adc22b1a84a1cd5ca5b2790875d79407c84b352395cb81cc3fed5bb043b69ede0c07204550025cee8c5f440170b6120bb48e0f747bcd8f522110850df043c428dfd187053102818100f6f961b47cbc035d3aedebc7de850a956b65ecdb9cf60764063f15aa48553c58d972fe6675056e35ddfdc37bf3b9f2f622ee271337256849c9bef2176fe8f7c3f8bb91ba374dd53baf3dec814d2bdec10c1fdc88cdd16876f26b1edfa3f094197edf4d42ff1fb2971103b898ca859c427287086a842ab410bb69cf2d35af6be302818100d47e724a7ff41048b270c2524a4101878b73159bb73d3dbc187b220e635b3534f96e243a184d93f860b6bfbb6b71c1ed9a1e1f458583023c301e96a692c1a08b53d0ec9ca910100d80451e3b7dc6a01bac4aecef8df798846bc235a08cbba2cf4c06804cc11219e95608c714e3f1430d491fadbba32a5751a04f97745834c9a502818021f2452bb9b95dfd028c914bf799f1ca77e89a95d50d3c16d384f8455f8bd7af9eb3dfa3d591d9842def235f7630a8e48c088ff6642e101794535a933e1e976fa8509fc728b2da0c4a1a08d7fcf37abaae1ff3001aca1dc1bbb05d9dffbaa1a09f7fb1eef38237d9ebccc722b9338436dde7119112798c26809c1a8dec4320610281801f7510aa62c2d8de4a3c53282781f41e02d0e8b402ae78432e449c48110161a11403f02d01880a8dcc938152d79721a4711a607ac4471ebf964810f95be47a45e60499e29f4c9773c83773404f606637728c2d0351bb03c326c8bb73a721e7fa5440ea2172bba1465fcc30dcb0d9f89930e815aa1f7f9729a857e00e0338dd590281804d1f0d756fe77e01099a652f50a88b7b685dc5bf00981d5d2376fd0c6fe29cd5b638734479305a73ad3c1599d39eae3bae035fbd6fed07c28de705933879a06e48e6a603686ed8e2560a5f6af1f2c24faf4aa960e382186f15eedce9a2491ae730680dd4cf778b70faa86826ab3223477cc91377b19a6d5a2eaea219760beed5\n\n# The public half of the same key encoded as a SubjectPublicKeyInfo.\nPublicKey = RSA-2048-SPKI\nType = RSA\nInput = 30820122300d06092a864886f70d01010105000382010f003082010a0282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f0203010001\n\n# The same key but with missing parameters rather than a NULL.\nPublicKey = RSA-2048-SPKI-Invalid\nInput = 30820120300b06092a864886f70d0101010382010f003082010a0282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f0203010001\nError = DECODE_ERROR\n\n# The same key but with an incorrectly-encoded length prefix.\nPublicKey = RSA-2048-SPKI-Invalid2\nInput = 3083000122300d06092a864886f70d01010105000382010f003082010a0282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f0203010001\nError = DECODE_ERROR\n\n# RSA 512 bit key.\nPrivateKey = RSA-512\nType = RSA\nInput = 30820154020100300d06092a864886f70d01010105000482013e3082013a020100024100dd20403d976a38c9d79152d87b5c8e9f05033eadd7b7de709bf5b0c4a5182a97d18483526b02362b992e154a9f37faa396ca2685cdab8fec09877ebe705f4dd70203010001024055bebcca655d7e39de8a6eaa9d636db682161907064039544755c53eeb99ec618c03a210dbc61471eaba10c5c365c9726d6b7a96f54d455f7d168d49367270e1022100f21a05d9fd6817301ce49ce10448f9bdd44f5ef5b7557cd7d83155db46382ae7022100e9d1f7157783db2feab1936954ddc4e83aa365695868144cda1be6813b61d791022100d6001eb0040920860ce41fafdf23ca6dfbdf74e6e9f98cf3164cf5c16f9e727d02206f6f73f4b52b10517be6f9bc5f87fa0a3bb817e2e711636b651f9af1c85d4f21022063eff2e57f5b4ca20342cfe793e25526624e3692f192461f9e1ce7f13f2d72c8\n\n# RSA 515 bit key.\nPrivateKey = RSA-515\nType = RSA\nInput = 30820157020100300d06092a864886f70d0101010500048201413082013d0201000241054fa166e205e658bbe8a2dc35311c0c2b75b7e4569fd9642c8bae809279271fc824f26baa1166ea46298ca63379ea76adbada2b61e5066820a35beaec1aca227f020301000102410266c972be0d30e53ac2acb1aa13b4bd0401cccf212452a66b4615f7e943831f67b4ca48560582d0ca886044aaaaf87945252a848c1947944186e6eb83969bf91102210309e631761842cc8a2ccfd372c20a9cba21de1a199c30ab440bc6b51079f4e825022101bf715c1db432627ca7c29a293b9210f2eff1e92d12f306ebaa5334f8ee03dcd30221018ac58a765f2b8f37d434081fe5ff92b81735ead2f263f4968ccf63d61fbe3d0d0221015b247a1159a2d5a25d0db049593c6405f77f3a278c521d066e290c2a2d8fb59d0221026224aa31fd95c14d24fd03b8a195bba4cc88df7c37f5370a5ab19f882f1404d6\n\n# EC P-256 key\nPrivateKey = P-256\nType = EC\nInput = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9\n\n# The same key as above with the optional public key omitted.\nPrivateKey = P-256-MissingPublic\nType = EC\nInput = 3041020100301306072a8648ce3d020106082a8648ce3d0301070427302502010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725\n\n# The same key as above with redundant parameters.\nPrivateKey = P-256-ExtraParameters\nType = EC\nInput = 308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a00a06082a8648ce3d030107a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9\n# The key re-encodes with the parameters removed.\nOutput = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9\n\n# The same key, but with the redundant parameters in the ECPrivateKey mismatched.\nPrivateKey = P-256-BadInnerParameters\nInput = 308190020100301306072a8648ce3d020106082a8648ce3d0301070476307402010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a00706052b81040022a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9\nError = GROUP_MISMATCH\n\n# The public half of the same key encoded as a PublicKey.\nPublicKey = P-256-SPKI\nType = EC\nInput = 3059301306072a8648ce3d020106082a8648ce3d030107034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cd",
+    "b664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9\n\n# The same as above, but with the curve explicitly spelled out.\nPublicKey = P-256-SPKI\nInput = 3082014b3082010306072a8648ce3d02013081f7020101302c06072a8648ce3d0101022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff305b0420ffffffff00000001000000000000000000000000fffffffffffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b031500c49d360886e704936a6678e1139d26b7819f7e900441046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551020101034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9\nError = DECODE_ERROR\n\n# The same as above, but with trailing data after the curve name.\nPublicKey = P-256-SPKI\nInput = 305b301506072a8648ce3d020106082a8648ce3d0301070500034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9\nError = DECODE_ERROR\n\n# A DSA private key.\nPrivateKey = DSA-1024\nType = DSA\nInput = 308202650201003082023906072a8648ce3804013082022c02820101009e12fab3de12213501dd82aa10ca2d101d2d4ebfef4d2a3f8daa0fe0cedad8d6af85616aa2f3252c0a2b5a6db09e6f14900e0ddb8311876dd8f9669525f99ed65949e184d5064793271169a228680b95ec12f59a8e20b21f2b58eb2a2012d35bde2ee351822fe8f32d0a330565dcce5c672b7259c14b2433d0b5b2ca2b2db0ab626e8f13f47fe0345d904e7294bb038e9ce21a9e580b83356278706cfe768436c69de149ccff98b4aab8cb4f6385c9f102ce59346eaeef27e0ad222d53d6e89cc8cde5776dd00057b03f2d88ab3cedbafd7b585f0b7f7835e17a3728bbf25ea62572f245dc111f3ce39cb6ffacc31b0a2790e7bde90224ea9b09315362af3d2b022100f381dcf53ebf724f8b2e5ca82c010fb4b5eda9358d0fd88ed278589488b54fc3028201000c402a725dcc3a62e02bf4cf43cd17f4a493591220223669cf4193edab423ad08dfb552e308a6a57a5ffbc7cd0fb2087f81f8df0cb08ab2133287d2b6968714a94f633c940845a48a3e16708dde761cc6a8eab2d84db21b6ea5b07681493cc9c31fbc368b243f6ddf8c932a8b4038f44e7b15ca876344a147859f2b43b39458668ad5e0a1a9a669546dd2812e3b3617a0aef99d58e3bb4cc87fd94225e01d2dcc469a77268146c51918f18e8b4d70aa1f0c7623bcc52cf3731d38641b2d2830b7eecb2f09552ff137d046e494e7f33c3590002b16d1b97d936fda28f90c3ed3ca35338168ac16f77c3c57adc2e8f7c6c2256e41a5f65450590dbb5bcf06d66610423022100b0c768702743bc51242993a971a52889795444f7c6452203d0ce84fe6117d46e\n\n# A DSA public key.\nPublicKey = DSA-1024-SPKI\nType = DSA\nInput = 308201b73082012c06072a8648ce3804013082011f02818100b3429b8b128c9079f9b72e86857e98d265e5d91661ed8b5f4cc56e5eed1e571da30186983a9dd76297eab73ee13a1db841f8800d04a7cab478af6cde2ea4a2868531af169a24858c6268efa39ceb7ed0d4227eb5bbb01124a2a5a26038c7bcfb8cc827f68f5202345166e4718596799b65c9def82828ce44e62e38e41a0d24b1021500c5a56c81ddd87f47e676546c56d05706421624cf0281810094de40d27314fe929e47ff9b1ac65cfc73ef38c4d381c890be6217b15039ae18190e6b421af8c0bda35a5cfd050f58ae2644adce83e68c8e5ba11729df56bbb21e227a60b816cc033fa799a38fe1ba5b4aa1801b6f841ce3df99feb3b4fb96950c960af13fa2ce920aabc12dd24ad2044a35063ea0e25f67f560f4cfbdc5598303818400028180258c30ebbb7f34fdc873ce679f6cea373c7886d75d4421b90920db034daedd292c64d8edd8cdbdd7f3ad23d74cfa2135247d0cef6ecf2e14f99e19d22a8c1266bd8fb8719c0e5667c716c45c7adbdabe548085bdad2dfee636f8d52fd6adb2193df6c4f0520fbd171b91882e0e4f321f8250ffecf4dbea00e114427d3ef96c1a\n\n# The same key as above, but without the parameters.\nPublicKey = DSA-1024-SPKI-No-Params\nType = DSA\nInput = 308192300906072a8648ce38040103818400028180258c30ebbb7f34fdc873ce679f6cea373c7886d75d4421b90920db034daedd292c64d8edd8cdbdd7f3ad23d74cfa2135247d0cef6ecf2e14f99e19d22a8c1266bd8fb8719c0e5667c716c45c7adbdabe548085bdad2dfee636f8d52fd6adb2193df6c4f0520fbd171b91882e0e4f321f8250ffecf4dbea00e114427d3ef96c1a\n\n# Private keys from RFC 8032.\nPrivateKey = Ed25519\nType = Ed25519\nInput = 302e020100300506032b6570042204209d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60\n\nPrivateKey = Ed25519-2\nType = Ed25519\nInput = 302e020100300506032b6570042204204ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb\n\nPrivateKey = Ed25519-3\nType = Ed25519\nInput = 302e020100300506032b657004220420c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7\n\nPrivateKey = Ed25519-4\nType = Ed25519\nInput = 302e020100300506032b657004220420f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5\n\nPrivateKey = Ed25519-5\nType = Ed25519\nInput = 302e020100300506032b657004220420833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42\n\n# Public keys from RFC 8032.\nPublicKey = Ed25519-SPKI\nType = Ed25519\nInput = 302a300506032b6570032100d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a\n\nPublicKey = Ed25519-SPKI-2\nType = Ed25519\nInput = 302a300506032b65700321003d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c\n\nPublicKey = Ed25519-SPKI-3\nType = Ed25519\nInput = 302a300506032b6570032100fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025\n\nPublicKey = Ed25519-SPKI-4\nType = Ed25519\nInput = 302a300506032b6570032100278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e\n\nPublicKey = Ed25519-SPKI-5\nType = Ed25519\nInput = 302a300506032b6570032100ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf\n\n# The first key, private and public, with invalid NULL parameters.\nPrivateKey = Ed25519-NULL\nInput = 3030020100300706032b65700500042204209d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60\nError = DECODE_ERROR\n\nPublicKey = Ed25519-SPKI-NULL\nInput = 302c300706032b65700500032100d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a\nError = DECODE_ERROR\n\n# Sample public key from draft-ietf-curdle-pkix-04.\nPublicKey = Ed25519-SPKI-Spec\nType = Ed25519\nInput = 302a300506032b657003210019bf44096984cdfe8541bac167dc3b96c85086aa30b6b6cb0c5c38ad703166e1\n\n# Sample private key from draft-ietf-curdle-pkix-04.\nPrivateKey = Ed25519-Spec\nType = Ed25519\nInput = 302e020100300506032b657004220420d4ee72dbf913584ad5b6d8f1f769f8ad3afe7c28cbf1d4fbe097a88f44755842\n\n\n# RSA tests\n\nSign = RSA-2048\nDigest = SHA1\nInput = \"0123456789ABCDEF1234\"\nOutput = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad\n\nVerify = RSA-2048\nDigest = SHA1\nInput = \"0123456789ABCDEF1234\"\nOutput = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad\n\nVerify = RSA-2048-SPKI\nDigest = SHA1\nInput = \"0123456789ABCDEF1234\"\nOutput = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad\n\n# Digest too long\nSign = RSA-2048\nDigest = SHA1\nInput = \"0123456789ABCDEF12345\"\nError = INVALID_MESSAGE_LENGTH\n\nVerify = RSA-2048\nDigest = SHA1\nInput = \"0123456789ABCDEF12345\"\nOutput = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db1",
+    "5dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad\nError = INVALID_MESSAGE_LENGTH\n\n# Digest too short\nSign = RSA-2048\nDigest = SHA1\nInput = \"0123456789ABCDEF123\"\nError = INVALID_MESSAGE_LENGTH\n\nVerify = RSA-2048\nDigest = SHA1\nInput = \"0123456789ABCDEF123\"\nOutput = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad\nError = INVALID_MESSAGE_LENGTH\n\n# Digest too large for key.\nSign = RSA-512\nDigest = SHA512\nInput = \"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\"\nError = DIGEST_TOO_BIG_FOR_RSA_KEY\n\n# Mismatched digest\nVerify = RSA-2048\nDigest = SHA1\nInput = \"0123456789ABCDEF1233\"\nOutput = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad\nError = BAD_SIGNATURE\n\n# Corrupted signature\nVerify = RSA-2048\nDigest = SHA1\nInput = \"0123456789ABCDEF1233\"\nOutput = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ae\nError = BLOCK_TYPE_IS_NOT_01\n\n# parameter missing (NOTE: this differs from upstream)\nVerify = RSA-2048\nDigest = SHA1\nInput = \"0123456789ABCDEF1234\"\nOutput = 3ec3fc29eb6e122bd7aa361cd09fe1bcbe85311096a7b9e4799cedfb2351ce0ab7fe4e75b4f6b37f67edd9c60c800f9ab941c0c157d7d880ca9de40c951d60fd293ae220d4bc510b1572d6e85a1bbbd8605b52e05f1c64fafdae59a1c2fbed214b7844d0134619de62851d5a0522e32e556e5950f3f97b8150e3f0dffee612c924201c27cd9bc8b423a71533380c276d3d59fcba35a2e80a1a192ec266a6c2255012cd86a349fe90a542b355fa3355b04da6cdf1df77f0e7bd44a90e880e1760266d233e465226f5db1c68857847d82072861ee266ddfc2e596845b77e1803274a579835ab5e4975d81d20b7df9cec7795489e4a2bdb8c1cf6a6b359945ac92c\nError = BAD_SIGNATURE\n\n# embedded digest too long\nVerify = RSA-2048\nDigest = SHA1\nInput = \"0123456789ABCDEF1234\"\nOutput = afec9a0d5330a08f54283bb4a9d4e7e7e70fc1342336c4c766fba713f66970151c6e27413c48c33864ea45a0238787004f338ed3e21b53b0fe9c1151c42c388cbc7cba5a06b706c407a5b48324fbe994dc7afc3a19fb3d2841e66222596c14cd72a0f0a7455a019d8eb554f59c0183f9552b75aa96fee8bf935945e079ca283d2bd3534a86f11351f6d6181fbf433e5b01a6d1422145c7a72214d3aacdd5d3af12b2d6bf6438f9f9a64010d8aeed801c87f0859412b236150b86a545f7239be022f4a7ad246b59df87514294cb4a4c7c5a997ee53c66054d9f38ca4e76c1f7af83c30f737ef70f83a45aebe18238ddb95e1998814ca4fc72388f1533147c169d\nError = BAD_SIGNATURE\n\n# embedded digest too short\nVerify = RSA-2048\nDigest = SHA1\nInput = \"0123456789ABCDEF1234\"\nOutput = afec9a0d5330a08f54283bb4a9d4e7e7e70fc1342336c4c766fba713f66970151c6e27413c48c33864ea45a0238787004f338ed3e21b53b0fe9c1151c42c388cbc7cba5a06b706c407a5b48324fbe994dc7afc3a19fb3d2841e66222596c14cd72a0f0a7455a019d8eb554f59c0183f9552b75aa96fee8bf935945e079ca283d2bd3534a86f11351f6d6181fbf433e5b01a6d1422145c7a72214d3aacdd5d3af12b2d6bf6438f9f9a64010d8aeed801c87f0859412b236150b86a545f7239be022f4a7ad246b59df87514294cb4a4c7c5a997ee53c66054d9f38ca4e76c1f7af83c30f737ef70f83a45aebe18238ddb95e1998814ca4fc72388f1533147c169d\nError = BAD_SIGNATURE\n\n# Garbage after DigestInfo\nVerify = RSA-2048\nDigest = SHA1\nInput = \"0123456789ABCDEF1234\"\nOutput = 9ee34872d4271a7d8808af0a4052a145a6d6a8437d00da3ed14428c7f087cd39f4d43334c41af63e7fa1ba363fee7bcef401d9d36a662abbab55ce89a696e1be0dfa19a5d09ca617dd488787b6048baaefeb29bc8688b2fe3882de2b77c905b5a8b56cf9616041e5ec934ba6de863efe93acc4eef783fe7f72a00fa65d6093ed32bf98ce527e62ccb1d56317f4be18b7e0f55d7c36617d2d0678a306e3350956b662ac15df45215dd8f6b314babb9788e6c272fa461e4c9b512a11a4b92bc77c3a4c95c903fccb238794eca5c750477bf56ea6ee6a167367d881b485ae3889e7c489af8fdf38e0c0f2aed780831182e34abedd43c39281b290774bf35cc25274\nError = BAD_SIGNATURE\n\n# invalid tag for parameter\nVerify = RSA-2048\nDigest = SHA1\nInput = \"0123456789ABCDEF1234\"\nOutput = 49525db4d44c755e560cba980b1d85ea604b0e077fcadd4ba44072a3487bbddb835016200a7d8739cce2dc3223d9c20cbdd25059ab02277f1f21318efd18e21038ec89aa9d40680987129e8b41ba33bceb86518bdf47268b921cce2037acabca6575d832499538d6f40cdba0d40bd7f4d8ea6ca6e2eec87f294efc971407857f5d7db09f6a7b31e301f571c6d82a5e3d08d2bb3a36e673d28b910f5bec57f0fcc4d968fd7c94d0b9226dec17f5192ad8b42bcab6f26e1bea1fdc3b958199acb00f14ebcb2a352f3afcedd4c09000128a603bbeb9696dea13040445253972d46237a25c7845e3b464e6984c2348ea1f1210a9ff0b00d2d72b50db00c009bb39f9\nError = BAD_SIGNATURE\n\n\n# RSA-PSS tests.\n\n# Zero salt length makes the output deterministic\nSign = RSA-2048\nRSAPadding = PSS\nPSSSaltLength = 0\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a\n\n# Verify of above signature\nVerify = RSA-2048-SPKI\nRSAPadding = PSS\nPSSSaltLength = 0\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a\n\n# Auto-detected salt length\nVerify = RSA-2048-SPKI\nRSAPadding = PSS\nPSSSaltLength = -2\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a\n\n# Wrong digest\nVerify = RSA-2048-SPKI\nRSAPadding = PSS\nPSSSaltLength = 0\nDigest = SHA256\nInput = \"00000000000000000000000000000000\"\nOutput = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13",
+    "848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a\nError = BAD_SIGNATURE\n\n# Digest too short\nVerify = RSA-2048-SPKI\nRSAPadding = PSS\nPSSSaltLength = 0\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDE\"\nOutput = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a\nError = INVALID_MESSAGE_LENGTH\n\n# Digest too long\nVerify = RSA-2048-SPKI\nRSAPadding = PSS\nPSSSaltLength = 0\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF0\"\nOutput = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a\nError = INVALID_MESSAGE_LENGTH\n\n# Wrong salt length\nVerify = RSA-2048\nRSAPadding = PSS\nPSSSaltLength = 2\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a\nError = SLEN_CHECK_FAILED\n\n# Wrong salt length using implicit hash length\nVerify = RSA-2048\nRSAPadding = PSS\nPSSSaltLength = -1\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a\nError = SLEN_CHECK_FAILED\n\n# Wrong MGF1 digest, SHA-1\nVerify = RSA-2048\nRSAPadding = PSS\nPSSSaltLength = 0\nDigest = SHA256\nMGF1Digest = SHA1\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a\n# If SHA-1, this input happens to succeed recovering a salt length, but it does\n# not match.\nError = SLEN_CHECK_FAILED\n\n# Wrong MGF1 digest, SHA-384\nVerify = RSA-2048\nRSAPadding = PSS\nPSSSaltLength = 0\nDigest = SHA256\nMGF1Digest = SHA384\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a\n# If SHA-384, this input happens fail to recover the salt length altogether.\nError = SLEN_RECOVERY_FAILED\n\n# The salt length is too large for the modulus (signing).\nSign = RSA-2048\nRSAPadding = PSS\nPSSSaltLength = 223\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nError = DATA_TOO_LARGE_FOR_KEY_SIZE\n\n# The salt length is too large for the modulus (verifying).\nVerify = RSA-2048\nRSAPadding = PSS\nPSSSaltLength = 223\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a\nError = DATA_TOO_LARGE\n\n# The hash is too large for the modulus (signing).\nSign = RSA-512\nRSAPadding = PSS\nPSSSaltLength = 0\nDigest = SHA512\nInput = \"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\"\nError = DATA_TOO_LARGE_FOR_KEY_SIZE\n\nSign = RSA-512\nRSAPadding = PSS\nPSSSaltLength = -2\nDigest = SHA512\nInput = \"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\"\nError = DATA_TOO_LARGE_FOR_KEY_SIZE\n\n# The hash is too large for the modulus (verifying).\nVerify = RSA-512\nRSAPadding = PSS\nPSSSaltLength = 0\nDigest = SHA512\nInput = \"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\"\nOutput = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\nError = DATA_TOO_LARGE\n\nVerify = RSA-512\nRSAPadding = PSS\nPSSSaltLength = -2\nDigest = SHA512\nInput = \"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\"\nOutput = 457001d9ca50a93385fc5ec721c9dbbe7a0f2e9e4a2f846a30a8811dde66347b83901c7492039243537c7a667fafffd69049bcbd36afd0010d9b425e2d8785c1\nError = DATA_TOO_LARGE\n\n# Sample RSA-515 signature.\nVerify = RSA-515\nRSAPadding = PSS\nPSSSaltLength = 0\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = 00c5926600f160f85e7fe950cfe123908384211cd8fe25c90cb8e8cc0593308e9aa2efe3acbf100ec1658ded8f72f506525fc2c44f06251b08d896e7bb3f05b135\n\n# The above, but with too few leading zeros.\nVerify = RSA-515\nRSAPadding = PSS\nPSSSaltLength = 0\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = c5926600f160f85e7fe950cfe123908384211cd8fe25c90cb8e8cc0593308e9aa2efe3acbf100ec1658ded8f72f506525fc2c44f06251b08d896e7bb3f05b135\nError = DATA_LEN_NOT_EQUAL_TO_MOD_LEN\n\n# The above, but with too many leading zeros.\nVerify = RSA-515\nRSAPadding = PSS\nPSSSaltLength = 0\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = 0000c5926600f160f85e7fe950cfe123908384211cd8fe25c90cb8e8cc0593308e9aa2efe3acbf100ec1658ded8f72f506525fc2c44f06251b08d896e7bb3f05b135\nError = DATA_LEN_NOT_EQUAL_TO_MOD_LEN\n\n# The above with an invalid leading byte. The top few bits of EM are required to\n# be cleared.\nVerify = RSA-515\nRSAPadding = PSS\nPSSSaltLength = 0\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = 007f803c832a2090aea04013d9fa9c1630732a1625232826d235f0950f7050d3fb0eb06ef9ea8b260fad68e1165a2d770a8c7fc7a8aaa68620b021fc19c97e0041\nError = FIRST_OCTET_INVALID\n\n# The above with an invalid trailing byte.\nVerify = RSA-515\nRSAPadding = PSS\nPSSSaltLength = 0\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = 03e68555035891eb08d96c0967db22328cd892ad2856d88516ecb946bfdba732bb029b5c0dfa2119ed7349",
+    "897d2324e95e86d91d0c4afc82700a36db8933abbf58\nError = LAST_OCTET_INVALID\n\n# Non-zero salt length.\nVerify = RSA-2048-SPKI\nRSAPadding = PSS\nPSSSaltLength = 32\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = 4065b284b0a6e98d4c41a8427007f878d8dd61599c87764fa79b8bf03f030c48127a4b1a5af5a6e0cf9055e57a1f47e5b0c0d8c600e78369cf1c39374899fac91a812692aa2216ba10900ce85a5cf7fddcafb726e4b83479c5bb7b3b84b08ffe183b4c2973aa3193ec7b7d4ea73bf1b579c6657b78ad7800e1975a4838c28ffe353fafef96be27b5c69677760a71b6f4df65ba6fe6b3565580a536f966928294c6e9ece807a90c1477779bcbfa3a250e98d685097c162c1c8c56ab02bd2e16eec7a019b51c067bdba7fa8cd5460796e22c607a8b6d12e1deb9be51c6943c46590f416800c48bb4cbb8c409d316573e59eadf7d3b9e6e5c2d0e570692e511e139\n\n# Non-zero salt length, wrong salt length.\nVerify = RSA-2048-SPKI\nRSAPadding = PSS\nPSSSaltLength = 31\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = 4065b284b0a6e98d4c41a8427007f878d8dd61599c87764fa79b8bf03f030c48127a4b1a5af5a6e0cf9055e57a1f47e5b0c0d8c600e78369cf1c39374899fac91a812692aa2216ba10900ce85a5cf7fddcafb726e4b83479c5bb7b3b84b08ffe183b4c2973aa3193ec7b7d4ea73bf1b579c6657b78ad7800e1975a4838c28ffe353fafef96be27b5c69677760a71b6f4df65ba6fe6b3565580a536f966928294c6e9ece807a90c1477779bcbfa3a250e98d685097c162c1c8c56ab02bd2e16eec7a019b51c067bdba7fa8cd5460796e22c607a8b6d12e1deb9be51c6943c46590f416800c48bb4cbb8c409d316573e59eadf7d3b9e6e5c2d0e570692e511e139\nError = SLEN_CHECK_FAILED\n\n# Non-zero salt length, match hash length.\nVerify = RSA-2048-SPKI\nRSAPadding = PSS\nPSSSaltLength = -1\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = 4065b284b0a6e98d4c41a8427007f878d8dd61599c87764fa79b8bf03f030c48127a4b1a5af5a6e0cf9055e57a1f47e5b0c0d8c600e78369cf1c39374899fac91a812692aa2216ba10900ce85a5cf7fddcafb726e4b83479c5bb7b3b84b08ffe183b4c2973aa3193ec7b7d4ea73bf1b579c6657b78ad7800e1975a4838c28ffe353fafef96be27b5c69677760a71b6f4df65ba6fe6b3565580a536f966928294c6e9ece807a90c1477779bcbfa3a250e98d685097c162c1c8c56ab02bd2e16eec7a019b51c067bdba7fa8cd5460796e22c607a8b6d12e1deb9be51c6943c46590f416800c48bb4cbb8c409d316573e59eadf7d3b9e6e5c2d0e570692e511e139\n\n# Non-zero salt length, auto-detected.\nVerify = RSA-2048-SPKI\nRSAPadding = PSS\nPSSSaltLength = -2\nDigest = SHA256\nInput = \"0123456789ABCDEF0123456789ABCDEF\"\nOutput = 4065b284b0a6e98d4c41a8427007f878d8dd61599c87764fa79b8bf03f030c48127a4b1a5af5a6e0cf9055e57a1f47e5b0c0d8c600e78369cf1c39374899fac91a812692aa2216ba10900ce85a5cf7fddcafb726e4b83479c5bb7b3b84b08ffe183b4c2973aa3193ec7b7d4ea73bf1b579c6657b78ad7800e1975a4838c28ffe353fafef96be27b5c69677760a71b6f4df65ba6fe6b3565580a536f966928294c6e9ece807a90c1477779bcbfa3a250e98d685097c162c1c8c56ab02bd2e16eec7a019b51c067bdba7fa8cd5460796e22c607a8b6d12e1deb9be51c6943c46590f416800c48bb4cbb8c409d316573e59eadf7d3b9e6e5c2d0e570692e511e139\n\n\n# RSA decrypt\n\nDecrypt = RSA-2048\nInput = 550af55a2904e7b9762352f8fb7fa235a9cb053aacb2d5fcb8ca48453cb2ee3619746c701abf2d4cc67003471a187900b05aa812bd25ed05c675dfc8c97a24a7bf49bd6214992cad766d05a9a2b57b74f26a737e0237b8b76c45f1f226a836d7cfbc75ba999bdbe48dbc09227aa46c88f21dccba7840141ad5a5d71fd122e6bd6ac3e564780dfe623fc1ca9b995a6037bf0bbd43b205a84ac5444f34202c05ce9113087176432476576de6ffff9a52ea57c08be3ec2f49676cb8e12f762ac71fa3c321e00ac988910c85ff52f93825666ce0d40ffaa0592078919d4493f46d95ccf76364c6d57760dd0b64805f9afc76a2365a5575ca301d5103f0ea76cb9a78\nOutput = \"Hello World\"\n\n# Corrupted ciphertext\nDecrypt = RSA-2048\nInput = 550af55a2904e7b9762352f8fb7fa235a9cb053aacb2d5fcb8ca48453cb2ee3619746c701abf2d4cc67003471a187900b05aa812bd25ed05c675dfc8c97a24a7bf49bd6214992cad766d05a9a2b57b74f26a737e0237b8b76c45f1f226a836d7cfbc75ba999bdbe48dbc09227aa46c88f21dccba7840141ad5a5d71fd122e6bd6ac3e564780dfe623fc1ca9b995a6037bf0bbd43b205a84ac5444f34202c05ce9113087176432476576de6ffff9a52ea57c08be3ec2f49676cb8e12f762ac71fa3c321e00ac988910c85ff52f93825666ce0d40ffaa0592078919d4493f46d95ccf76364c6d57760dd0b64805f9afc76a2365a5575ca301d5103f0ea76cb9a79\nError = PKCS_DECODING_ERROR\n\n# OAEP padding\nDecrypt = RSA-2048\nRSAPadding = OAEP\nInput = 458708dfbd42a1297ce7a9c86c7087ab80b1754810929b89c5107ca55368587686986fce94d86cc1595b3fb736223a656ec0f34d18ba1cc5665593610f56c58e26b272d584f3d983a5c91085700755aebd921fb280bba3eda7046ec07b43e7298e52d59edc92be4639a8ce08b2f85976ecf6d98cc469eeb9d5d8e2a32ea8a6626edafe1038b3df455668a9f3c77cad8b92fb872e00058c3d2a7ede1a1f03fc5622084ae04d9d24f6bf0995c58d35b93b699b9763595e123f2ab0863cc9229eb290e2ede7715c7a8f39e0b9a3e2e1b56ebb62f1cbfbb5986fb212ebd785b83d01d968b11d1756c7337f70c1f1a63bff03608e24f3a2fd44e67f832a8701c5d5af\nOutput = \"Hello World\"\n\n# OAEP padding, corrupted ciphertext\nDecrypt = RSA-2048\nRSAPadding = OAEP\nInput = 458708dfbd42a1297ce7a9c86c7087ab80b1754810929b89c5107ca55368587686986fce94d86cc1595b3fb736223a656ec0f34d18ba1cc5665593610f56c58e26b272d584f3d983a5c91085700755aebd921fb280bba3eda7046ec07b43e7298e52d59edc92be4639a8ce08b2f85976ecf6d98cc469eeb9d5d8e2a32ea8a6626edafe1038b3df455668a9f3c77cad8b92fb872e00058c3d2a7ede1a1f03fc5622084ae04d9d24f6bf0995c58d35b93b699b9763595e123f2ab0863cc9229eb290e2ede7715c7a8f39e0b9a3e2e1b56ebb62f1cbfbb5986fb212ebd785b83d01d968b11d1756c7337f70c1f1a63bff03608e24f3a2fd44e67f832a8701c5d5ac\nError = OAEP_DECODING_ERROR\n\n\n# EC tests\n\nVerify = P-256\nDigest = SHA1\nInput = \"0123456789ABCDEF1234\"\nOutput = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8\n\nVerify = P-256-SPKI\nDigest = SHA1\nInput = \"0123456789ABCDEF1234\"\nOutput = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8\n\n# Digest too long\nVerify = P-256\nDigest = SHA1\nInput = \"0123456789ABCDEF12345\"\nOutput = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8\nError = BAD_SIGNATURE\n\n# Digest too short\nVerify = P-256\nDigest = SHA1\nInput = \"0123456789ABCDEF123\"\nOutput = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8\nError = BAD_SIGNATURE\n\n# Digest invalid\nVerify = P-256\nDigest = SHA1\nInput = \"0123456789ABCDEF1235\"\nOutput = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8\nError = BAD_SIGNATURE\n\n# Invalid signature\nVerify = P-256\nDigest = SHA1\nInput = \"0123456789ABCDEF1234\"\nOutput = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec7\nError = BAD_SIGNATURE\n\n# Garbage after signature\nVerify = P-256\nDigest = SHA1\nInput = \"0123456789ABCDEF1234\"\nOutput = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec800\nError = BAD_SIGNATURE\n\n# BER signature\nVerify = P-256\nDigest = SHA1\nInput = \"0123456789ABCDEF1234\"\nOutput = 3080022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec80000\nError = BAD_SIGNATURE\n\n\n# Additional RSA-PSS and RSA-OAEP tests converted from\n# ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip\n\nPublicKey = RSA-PSS-1\nType = RSA\nInput = 30819f300d06092a864886f70d010101050003818d0030818902818100a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a21370203010001\n\nVerify = RSA-PSS-1\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = cd8b6538cb8e8de566b68bd067569dbf1ee2718e\nOutput = 9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c\n\nVerify = RSA-PSS-1\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = e35befc17a1d160b9ce35fbd8eb16e7ee491d3fd\nOutput = 3ef7f46e831bf92b32274142a585ffcefbdca7b32a",
+    "e90d10fb0f0c729984f04ef29a9df0780775ce43739b97838390db0a5505e63de927028d9d29b219ca2c4517832558a55d694a6d25b9dab66003c4cccd907802193be5170d26147d37b93590241be51c25055f47ef62752cfbe21418fafe98c22c4d4d47724fdb5669e843\n\nVerify = RSA-PSS-1\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 0652ec67bcee30f9d2699122b91c19abdba89f91\nOutput = 666026fba71bd3e7cf13157cc2c51a8e4aa684af9778f91849f34335d141c00154c4197621f9624a675b5abc22ee7d5baaffaae1c9baca2cc373b3f33e78e6143c395a91aa7faca664eb733afd14d8827259d99a7550faca501ef2b04e33c23aa51f4b9e8282efdb728cc0ab09405a91607c6369961bc8270d2d4f39fce612b1\n\nVerify = RSA-PSS-1\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 39c21c4cceda9c1adf839c744e1212a6437575ec\nOutput = 4609793b23e9d09362dc21bb47da0b4f3a7622649a47d464019b9aeafe53359c178c91cd58ba6bcb78be0346a7bc637f4b873d4bab38ee661f199634c547a1ad8442e03da015b136e543f7ab07c0c13e4225b8de8cce25d4f6eb8400f81f7e1833b7ee6e334d370964ca79fdb872b4d75223b5eeb08101591fb532d155a6de87\n\nVerify = RSA-PSS-1\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 36dae913b77bd17cae6e7b09453d24544cebb33c\nOutput = 1d2aad221ca4d31ddf13509239019398e3d14b32dc34dc5af4aeaea3c095af73479cf0a45e5629635a53a018377615b16cb9b13b3e09d671eb71e387b8545c5960da5a64776e768e82b2c93583bf104c3fdb23512b7b4e89f633dd0063a530db4524b01c3f384c09310e315a79dcd3d684022a7f31c865a664e316978b759fad\n\nVerify = RSA-PSS-1\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 45eef191f4f79c31fe5d2ede7e5098994e929d2d\nOutput = 2a34f6125e1f6b0bf971e84fbd41c632be8f2c2ace7de8b6926e31ff93e9af987fbc06e51e9be14f5198f91f3f953bd67da60a9df59764c3dc0fe08e1cbef0b75f868d10ad3fba749fef59fb6dac46a0d6e504369331586f58e4628f39aa278982543bc0eeb537dc61958019b394fb273f215858a0a01ac4d650b955c67f4c58\n\nPublicKey = RSA-PSS-2\nType = RSA\nInput = 30819f300d06092a864886f70d010101050003818d0030818902818101d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c90203010001\n\nVerify = RSA-PSS-2\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 5c81a3e2a658246628cd0ee8b00bb4c012bc9739\nOutput = 014c5ba5338328ccc6e7a90bf1c0ab3fd606ff4796d3c12e4b639ed9136a5fec6c16d8884bdd99cfdc521456b0742b736868cf90de099adb8d5ffd1deff39ba4007ab746cefdb22d7df0e225f54627dc65466131721b90af445363a8358b9f607642f78fab0ab0f43b7168d64bae70d8827848d8ef1e421c5754ddf42c2589b5b3\n\nVerify = RSA-PSS-2\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 27f71611446aa6eabf037f7dedeede3203244991\nOutput = 010991656cca182b7f29d2dbc007e7ae0fec158eb6759cb9c45c5ff87c7635dd46d150882f4de1e9ae65e7f7d9018f6836954a47c0a81a8a6b6f83f2944d6081b1aa7c759b254b2c34b691da67cc0226e20b2f18b42212761dcd4b908a62b371b5918c5742af4b537e296917674fb914194761621cc19a41f6fb953fbcbb649dea\n\nVerify = RSA-PSS-2\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 03ecc2c33e93f05fc7224fcc0d461356cb897217\nOutput = 007f0030018f53cdc71f23d03659fde54d4241f758a750b42f185f87578520c30742afd84359b6e6e8d3ed959dc6fe486bedc8e2cf001f63a7abe16256a1b84df0d249fc05d3194ce5f0912742dbbf80dd174f6c51f6bad7f16cf3364eba095a06267dc3793803ac7526aebe0a475d38b8c2247ab51c4898df7047dc6adf52c6c4\n\nVerify = RSA-PSS-2\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 246c727b4b9494849dddb068d582e179ac20999c\nOutput = 009cd2f4edbe23e12346ae8c76dd9ad3230a62076141f16c152ba18513a48ef6f010e0e37fd3df10a1ec629a0cb5a3b5d2893007298c30936a95903b6ba85555d9ec3673a06108fd62a2fda56d1ce2e85c4db6b24a81ca3b496c36d4fd06eb7c9166d8e94877c42bea622b3bfe9251fdc21d8d5371badad78a488214796335b40b\n\nVerify = RSA-PSS-2\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = e8617ca3ea66ce6a58ede2d11af8c3ba8a6ba912\nOutput = 00ec430824931ebd3baa43034dae98ba646b8c36013d1671c3cf1cf8260c374b19f8e1cc8d965012405e7e9bf7378612dfcc85fce12cda11f950bd0ba8876740436c1d2595a64a1b32efcfb74a21c873b3cc33aaf4e3dc3953de67f0674c0453b4fd9f604406d441b816098cb106fe3472bc251f815f59db2e4378a3addc181ecf\n\nVerify = RSA-PSS-2\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 7a6fdc1a4e434ecbc35d657ad49a2f4fafd43bc8\nOutput = 00475b1648f814a8dc0abdc37b5527f543b666bb6e39d30e5b49d3b876dccc58eac14e32a2d55c2616014456ad2f246fc8e3d560da3ddf379a1c0bd200f10221df078c219a151bc8d4ec9d2fc2564467811014ef15d8ea01c2ebbff8c2c8efab38096e55fcbe3285c7aa558851254faffa92c1c72b78758663ef4582843139d7a6\n\nPublicKey = RSA-PSS-3\nType = RSA\nInput = 30819f300d06092a864886f70d010101050003818d0030818902818102f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a4430203010001\n\nVerify = RSA-PSS-3\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 3552be69dd74bdc56d2cf8c38ef7bafe269040fe\nOutput = 0088b135fb1794b6b96c4a3e678197f8cac52b64b2fe907d6f27de761124964a99a01a882740ecfaed6c01a47464bb05182313c01338a8cd097214cd68ca103bd57d3bc9e816213e61d784f182467abf8a01cf253e99a156eaa8e3e1f90e3c6e4e3aa2d83ed0345b89fafc9c26077c14b6ac51454fa26e446e3a2f153b2b16797f\n\nVerify = RSA-PSS-3\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 609143ff7240e55c062aba8b9e4426a781919bc9\nOutput = 02a5f0a858a0864a4f65017a7d69454f3f973a2999839b7bbc48bf78641169179556f595fa41f6ff18e286c2783079bc0910ee9cc34f49ba681124f923dfa88f426141a368a5f5a930c628c2c3c200e18a7644721a0cbec6dd3f6279bde3e8f2be5e2d4ee56f97e7ceaf33054be7042bd91a63bb09f897bd41e81197dee99b11af\n\nVerify = RSA-PSS-3\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 0afd22f879a9cda7c584f4135f8f1c961db114c0\nOutput = 0244bcd1c8c16955736c803be401272e18cb990811b14f72db964124d5fa760649cbb57afb8755dbb62bf51f466cf23a0a1607576e983d778fceffa92df7548aea8ea4ecad2c29dd9f95bc07fe91ecf8bee255bfe8762fd7690aa9bfa4fa0849ef728c2c42c4532364522df2ab7f9f8a03b63f7a499175828668f5ef5a29e3802c\n\nVerify = RSA-PSS-3\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 405dd56d395ef0f01b555c48f748cc32b210650b\nOutput = 0196f12a005b98129c8df13c4cb16f8aa887d3c40d96df3a88e7532ef39cd992f273abc370bc1be6f097cfebbf0118fd9ef4b927155f3df22b904d90702d1f7ba7a52bed8b8942f412cd7bd676c9d18e170391dcd345c06a730964b3f30bcce0bb20ba106f9ab0eeb39cf8a6607f75c0347f0af79f16afa081d2c92d1ee6f836b8\n\nVerify = RSA-PSS-3\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = a2c313b0440c8a0c47233b87f0a160c61af3eae7\nOutput = 021eca3ab4892264ec22411a752d92221076d4e01c0e6f0dde9afd26ba5acf6d739ef987545d16683e5674c9e70f1de649d7e61d48d0caeb4fb4d8b24fba84a6e3108fee7d0705973266ac524b4ad280f7ae17dc59d96d3351586b5a3bdb895d1e1f7820ac6135d8753480998382ba32b7349559608c38745290a85ef4e9f9bd83\n\nVerify = RSA-PSS-3\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = f1bf6ca7b4bbdbb6bf20a4bf55728725d177154a\nOutput = 012fafec862f56e9e92f60ab0c77824f4299a0ca734ed26e0644d5d222c7f0bde03964f8e70a5cb65ed44e44d56ae0edf1ff86ca032cc5dd4404dbb76ab854586c44eed8336d08d457ce6c03693b45c0f1efef93624b95b8ec169c616d20e5538ebc0b6737a6f82b4bc0570924fc6b35759a3348426279f8b3d7744e2d222426ce\n\nPublicKey = RSA-PSS-4\nType = RSA\nInput = 30819f300d06092a864886f70d010101050003818d00308189028181054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c37050203010001\n\nVerify = RSA-PSS-4\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = f8b0abf70fec0bca74f0accbc24f75e6e90d3bfd\nOutput = 0323d5b7bf20ba4539289ae452ae4297080feff4518423ff4811a817837e7d82f1836cdfab54514ff0887bddeebf40bf99b047abc3ecfa6a37a3ef00f4a0c4a88aae0904b745c846c4107e8797723e8ac810d9e3d95dfa30ff4966f4d75d13768d20857f2b1406f264cfe75e27d7652f4b5ed3575f28a702f8c4ed9cf9b2d44948\n\nVerify = RSA-PSS-4\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 04a10944bfe11ab801e77889f3fd3d7f4ff0b629\nOutput = 049d0185845a264d28feb1e69edaec090609e8e46d93abb38371ce51f4aa65a599bdaaa81d24fba66a08a116cb644f3f1e653d95c89db8bbd5daac2709c8984000178410a7c6aa8667ddc38c741f710ec8665aa9052be929d4e3b16782c1662114c5414bb0353455c392fc28f3db59054b5f365c49e1d156f876ee10cb4fd70598\n\nVerify = RSA-PSS-4\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = ba01243db223eb97fb86d746c3148adaaa0ca344\nOutput = 03fbc410a2ced59500fb99f9e2af2781ada74e13145624602782e2994813eefca0519ecd253",
+    "b855fb626a90d771eae028b0c47a199cbd9f8e3269734af4163599090713a3fa910fa0960652721432b971036a7181a2bc0cab43b0b598bc6217461d7db305ff7e954c5b5bb231c39e791af6bcfa76b147b081321f72641482a2aad\n\nVerify = RSA-PSS-4\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 934bb0d38d6836daec9de82a9648d4593da67cd2\nOutput = 0486644bc66bf75d28335a6179b10851f43f09bded9fac1af33252bb9953ba4298cd6466b27539a70adaa3f89b3db3c74ab635d122f4ee7ce557a61e59b82ffb786630e5f9db53c77d9a0c12fab5958d4c2ce7daa807cd89ba2cc7fcd02ff470ca67b229fcce814c852c73cc93bea35be68459ce478e9d4655d121c8472f371d4f\n\nVerify = RSA-PSS-4\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = ec35d81abd1cceac425a935758b683465c8bd879\nOutput = 022a80045353904cb30cbb542d7d4990421a6eec16a8029a8422adfd22d6aff8c4cc0294af110a0c067ec86a7d364134459bb1ae8ff836d5a8a2579840996b320b19f13a13fad378d931a65625dae2739f0c53670b35d9d3cbac08e733e4ec2b83af4b9196d63e7c4ff1ddeae2a122791a125bfea8deb0de8ccf1f4ffaf6e6fb0a\n\nVerify = RSA-PSS-4\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 72ce251d17b04dd3970d6ff1fbe3624899e9e941\nOutput = 00938dcb6d583046065f69c78da7a1f1757066a7fa75125a9d2929f0b79a60b627b082f11f5b196f28eb9daa6f21c05e5140f6aef1737d2023075c05ecf04a028c686a2ab3e7d5a0664f295ce12995e890908b6ad21f0839eb65b70393a7b5afd9871de0caa0cedec5b819626756209d13ab1e7bb9546a26ff37e9a51af9fd562e\n\nPublicKey = RSA-PSS-5\nType = RSA\nInput = 30819f300d06092a864886f70d010101050003818d003081890281810d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc5070203010001\n\nVerify = RSA-PSS-5\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = d98b7061943510bc3dd9162f7169aabdbdcd0222\nOutput = 0ba373f76e0921b70a8fbfe622f0bf77b28a3db98e361051c3d7cb92ad0452915a4de9c01722f6823eeb6adf7e0ca8290f5de3e549890ac2a3c5950ab217ba58590894952de96f8df111b2575215da6c161590c745be612476ee578ed384ab33e3ece97481a252f5c79a98b5532ae00cdd62f2ecc0cd1baefe80d80b962193ec1d\n\nVerify = RSA-PSS-5\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 7ae8e699f754988f4fd645e463302e49a2552072\nOutput = 08180de825e4b8b014a32da8ba761555921204f2f90d5f24b712908ff84f3e220ad17997c0dd6e706630ba3e84add4d5e7ab004e58074b549709565d43ad9e97b5a7a1a29e85b9f90f4aafcdf58321de8c5974ef9abf2d526f33c0f2f82e95d158ea6b81f1736db8d1af3d6ac6a83b32d18bae0ff1b2fe27de4c76ed8c7980a34e\n\nVerify = RSA-PSS-5\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 8d46c7c05534c1ba2cc7624500d48a4531604bff\nOutput = 05e0fdbdf6f756ef733185ccfa8ced2eb6d029d9d56e35561b5db8e70257ee6fd019d2f0bbf669fe9b9821e78df6d41e31608d58280f318ee34f559941c8df13287574bac000b7e58dc4f414ba49fb127f9d0f8936638c76e85356c994f79750f7fa3cf4fd482df75e3fb9978cd061f7abb17572e6e63e0bde12cbdcf18c68b979\n\nVerify = RSA-PSS-5\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = ee3de96783fd0a157c8b20bf5566124124dcfe65\nOutput = 0bc989853bc2ea86873271ce183a923ab65e8a53100e6df5d87a24c4194eb797813ee2a187c097dd872d591da60c568605dd7e742d5af4e33b11678ccb63903204a3d080b0902c89aba8868f009c0f1c0cb85810bbdd29121abb8471ff2d39e49fd92d56c655c8e037ad18fafbdc92c95863f7f61ea9efa28fea401369d19daea1\n\nVerify = RSA-PSS-5\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 1204df0b03c2724e2709c23fc71789a21b00ae4c\nOutput = 0aefa943b698b9609edf898ad22744ac28dc239497cea369cbbd84f65c95c0ad776b594740164b59a739c6ff7c2f07c7c077a86d95238fe51e1fcf33574a4ae0684b42a3f6bf677d91820ca89874467b2c23add77969c80717430d0efc1d3695892ce855cb7f7011630f4df26def8ddf36fc23905f57fa6243a485c770d5681fcd\n\nVerify = RSA-PSS-5\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 29926bc3280c841f601acd0d6f17ea38023eddbc\nOutput = 02802dccfa8dfaf5279bf0b4a29ba1b157611faeaaf419b8919d15941900c1339e7e92e6fae562c53e6cc8e84104b110bce03ad18525e3c49a0eadad5d3f28f244a8ed89edbafbb686277cfa8ae909714d6b28f4bf8e293aa04c41efe7c0a81266d5c061e2575be032aa464674ff71626219bd74cc45f0e7ed4e3ff96eee758e8f\n\nPublicKey = RSA-PSS-6\nType = RSA\nInput = 30819f300d06092a864886f70d010101050003818d00308189028181164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d10203010001\n\nVerify = RSA-PSS-6\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = ab464e8cb65ae5fdea47a53fa84b234d6bfd52f6\nOutput = 04c0cfacec04e5badbece159a5a1103f69b3f32ba593cb4cc4b1b7ab455916a96a27cd2678ea0f46ba37f7fc9c86325f29733b389f1d97f43e7201c0f348fc45fe42892335362eee018b5b161f2f9393031225c713012a576bc88e23052489868d9010cbf033ecc568e8bc152bdc59d560e41291915d28565208e22aeec9ef85d1\n\nVerify = RSA-PSS-6\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 92d0bcae82b641f578f040f5151be8eda6d42299\nOutput = 0a2314250cf52b6e4e908de5b35646bcaa24361da8160fb0f9257590ab3ace42b0dc3e77ad2db7c203a20bd952fbb56b1567046ecfaa933d7b1000c3de9ff05b7d989ba46fd43bc4c2d0a3986b7ffa13471d37eb5b47d64707bd290cfd6a9f393ad08ec1e3bd71bb5792615035cdaf2d8929aed3be098379377e777ce79aaa4773\n\nVerify = RSA-PSS-6\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 3569bd8fd2e28f2443375efa94f186f6911ffc2b\nOutput = 086df6b500098c120f24ff8423f727d9c61a5c9007d3b6a31ce7cf8f3cbec1a26bb20e2bd4a046793299e03e37a21b40194fb045f90b18bf20a47992ccd799cf9c059c299c0526854954aade8a6ad9d97ec91a1145383f42468b231f4d72f23706d9853c3fa43ce8ace8bfe7484987a1ec6a16c8daf81f7c8bf42774707a9df456\n\nVerify = RSA-PSS-6\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 7abbb7b42de335730a0b641f1e314b6950b84f98\nOutput = 0b5b11ad549863ffa9c51a14a1106c2a72cc8b646e5c7262509786105a984776534ca9b54c1cc64bf2d5a44fd7e8a69db699d5ea52087a4748fd2abc1afed1e5d6f7c89025530bdaa2213d7e030fa55df6f34bcf1ce46d2edf4e3ae4f3b01891a068c9e3a44bbc43133edad6ecb9f35400c4252a5762d65744b99cb9f4c559329f\n\nVerify = RSA-PSS-6\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 55b7eb27be7a787a59eb7e5fac468db8917a7725\nOutput = 02d71fa9b53e4654fefb7f08385cf6b0ae3a817942ebf66c35ac67f0b069952a3ce9c7e1f1b02e480a9500836de5d64cdb7ecde04542f7a79988787e24c2ba05f5fd482c023ed5c30e04839dc44bed2a3a3a4fee01113c891a47d32eb8025c28cb050b5cdb576c70fe76ef523405c08417faf350b037a43c379339fcb18d3a356b\n\nVerify = RSA-PSS-6\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = de2fa0367ef49083ff89b9905d3fd646fcc12c38\nOutput = 0a40a16e2fe2b38d1df90546167cf9469c9e3c3681a3442b4b2c2f581deb385ce99fc6188bb02a841d56e76d301891e24560550fcc2a26b55f4ccb26d837d350a154bcaca8392d98fa67959e9727b78cad03269f56968fc56b68bd679926d83cc9cb215550645ccda31c760ff35888943d2d8a1d351e81e5d07b86182e751081ef\n\nPublicKey = RSA-PSS-7\nType = RSA\nInput = 30819f300d06092a864886f70d010101050003818d0030818902818137c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab30203010001\n\nVerify = RSA-PSS-7\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 8be4afbdd76bd8d142c5f4f46dba771ee5d6d29d\nOutput = 187f390723c8902591f0154bae6d4ecbffe067f0e8b795476ea4f4d51ccc810520bb3ca9bca7d0b1f2ea8a17d873fa27570acd642e3808561cb9e975ccfd80b23dc5771cdb3306a5f23159dacbd3aa2db93d46d766e09ed15d900ad897a8d274dc26b47e994a27e97e2268a766533ae4b5e42a2fcaf755c1c4794b294c60555823\n\nVerify = RSA-PSS-7\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 402140dc605b2f5c5ec0d15bce9f9ba8857fe117\nOutput = 10fd89768a60a67788abb5856a787c8561f3edcf9a83e898f7dc87ab8cce79429b43e56906941a886194f137e591fe7c339555361fbbe1f24feb2d4bcdb80601f3096bc9132deea60ae13082f44f9ad41cd628936a4d51176e42fc59cb76db815ce5ab4db99a104aafea68f5d330329ebf258d4ede16064bd1d00393d5e1570eb8\n\nVerify = RSA-PSS-7\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 3e885205892ff2b6b37c2c4eb486c4bf2f9e7f20\nOutput = 2b31fde99859b977aa09586d8e274662b25a2a640640b457f594051cb1e7f7a911865455242926cf88fe80dfa3a75ba9689844a11e634a82b075afbd69c12a0df9d25f84ad4945df3dc8fe90c3cefdf26e95f0534304b5bdba20d3e5640a2ebfb898aac35ae40f26fce5563c2f9f24f3042af76f3c7072d687bbfb959a88460af1\n\nVerify = RSA-PSS-7\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 1fc2201d0c442a4736cd8b2cd00c959c47a3bf42\nOutput = 32c7ca38ff26949a15000c4ba04b2b13b35a3810e568184d7ecabaa166b7ffabddf2b6cf4ba07124923790f2e5b1a5be04",
+    "0aea36fe132ec130e1f10567982d17ac3e89b8d26c3094034e762d2e031264f01170beecb3d1439e05846f25458367a7d9c02060444672671e64e877864559ca19b2074d588a281b5804d23772fbbe19\n\nVerify = RSA-PSS-7\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = e4351b66819e5a31501f89acc7faf57030e9aac5\nOutput = 07eb651d75f1b52bc263b2e198336e99fbebc4f332049a922a10815607ee2d989db3a4495b7dccd38f58a211fb7e193171a3d891132437ebca44f318b280509e52b5fa98fcce8205d9697c8ee4b7ff59d4c59c79038a1970bd2a0d451ecdc5ef11d9979c9d35f8c70a6163717607890d586a7c6dc01c79f86a8f28e85235f8c2f1\n\nVerify = RSA-PSS-7\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 49f6cc58365e514e1a3f301f4de16f9fb5347ff2\nOutput = 18da3cdcfe79bfb77fd9c32f377ad399146f0a8e810620233271a6e3ed3248903f5cdc92dc79b55d3e11615aa056a795853792a3998c349ca5c457e8ca7d29d796aa24f83491709befcfb1510ea513c92829a3f00b104f655634f320752e130ec0ccf6754ff893db302932bb025eb60e87822598fc619e0e981737a9a4c4152d33\n\nPublicKey = RSA-PSS-8\nType = RSA\nInput = 30819f300d06092a864886f70d010101050003818d00308189028181495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f0203010001\n\nVerify = RSA-PSS-8\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = a1dd230d8ead860199b6277c2ecfe3d95f6d9160\nOutput = 0262ac254bfa77f3c1aca22c5179f8f040422b3c5bafd40a8f21cf0fa5a667ccd5993d42dbafb409c520e25fce2b1ee1e716577f1efa17f3da28052f40f0419b23106d7845aaf01125b698e7a4dfe92d3967bb00c4d0d35ba3552ab9a8b3eef07c7fecdbc5424ac4db1e20cb37d0b2744769940ea907e17fbbca673b20522380c5\n\nVerify = RSA-PSS-8\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = f6e68e53c602c5c65fa67b5aa6d786e5524b12ab\nOutput = 2707b9ad5115c58c94e932e8ec0a280f56339e44a1b58d4ddcff2f312e5f34dcfe39e89c6a94dcee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6c86ee68396e8b3a14c9c8f34b178eb741f9d3f121109bf5c8172fada2e768f9ea1433032c004a8aa07eb990000a48dc94c8bac8aabe2b09b1aa46c0a2aa0e12f63fbba775ba7e\n\nVerify = RSA-PSS-8\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = d6f9fcd3ae27f32bb2c7c93536782eba52af1f76\nOutput = 2ad20509d78cf26d1b6c406146086e4b0c91a91c2bd164c87b966b8faa42aa0ca446022323ba4b1a1b89706d7f4c3be57d7b69702d168ab5955ee290356b8c4a29ed467d547ec23cbadf286ccb5863c6679da467fc9324a151c7ec55aac6db4084f82726825cfe1aa421bc64049fb42f23148f9c25b2dc300437c38d428aa75f96\n\nVerify = RSA-PSS-8\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 7ff2a53ce2e2d900d468e498f230a5f5dd0020de\nOutput = 1e24e6e58628e5175044a9eb6d837d48af1260b0520e87327de7897ee4d5b9f0df0be3e09ed4dea8c1454ff3423bb08e1793245a9df8bf6ab3968c8eddc3b5328571c77f091cc578576912dfebd164b9de5454fe0be1c1f6385b328360ce67ec7a05f6e30eb45c17c48ac70041d2cab67f0a2ae7aafdcc8d245ea3442a6300ccc7\n\nVerify = RSA-PSS-8\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 4eb309f7022ba0b03bb78601b12931ec7c1be8d3\nOutput = 33341ba3576a130a50e2a5cf8679224388d5693f5accc235ac95add68e5eb1eec31666d0ca7a1cda6f70a1aa762c05752a51950cdb8af3c5379f18cfe6b5bc55a4648226a15e912ef19ad77adeea911d67cfefd69ba43fa4119135ff642117ba985a7e0100325e9519f1ca6a9216bda055b5785015291125e90dcd07a2ca9673ee\n\nVerify = RSA-PSS-8\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 65033bc2f67d6aba7d526acb873b8d9241e5e4d9\nOutput = 1ed1d848fb1edb44129bd9b354795af97a069a7a00d0151048593e0c72c3517ff9ff2a41d0cb5a0ac860d736a199704f7cb6a53986a88bbd8abcc0076a2ce847880031525d449da2ac78356374c536e343faa7cba42a5aaa6506087791c06a8e989335aed19bfab2d5e67e27fb0c2875af896c21b6e8e7309d04e4f6727e69463e\n\nPublicKey = RSA-PSS-9\nType = RSA\nInput = 3081df300d06092a864886f70d01010105000381cd003081c90281c100e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b0203010001\n\nVerify = RSA-PSS-9\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 2715a49b8b0012cd7aee84c116446e6dfe3faec0\nOutput = 586107226c3ce013a7c8f04d1a6a2959bb4b8e205ba43a27b50f124111bc35ef589b039f5932187cb696d7d9a32c0c38300a5cdda4834b62d2eb240af33f79d13dfbf095bf599e0d9686948c1964747b67e89c9aba5cd85016236f566cc5802cb13ead51bc7ca6bef3b94dcbdbb1d570469771df0e00b1a8a06777472d2316279edae86474668d4e1efff95f1de61c6020da32ae92bbf16520fef3cf4d88f61121f24bbd9fe91b59caf1235b2a93ff81fc403addf4ebdea84934a9cdaf8e1a9e\n\nVerify = RSA-PSS-9\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 2dac956d53964748ac364d06595827c6b4f143cd\nOutput = 80b6d643255209f0a456763897ac9ed259d459b49c2887e5882ecb4434cfd66dd7e1699375381e51cd7f554f2c271704b399d42b4be2540a0eca61951f55267f7c2878c122842dadb28b01bd5f8c025f7e228418a673c03d6bc0c736d0a29546bd67f786d9d692ccea778d71d98c2063b7a71092187a4d35af108111d83e83eae46c46aa34277e06044589903788f1d5e7cee25fb485e92949118814d6f2c3ee361489016f327fb5bc517eb50470bffa1afa5f4ce9aa0ce5b8ee19bf5501b958\n\nVerify = RSA-PSS-9\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 28d98c46cccafbd3bc04e72f967a54bd3ea12298\nOutput = 484408f3898cd5f53483f80819efbf2708c34d27a8b2a6fae8b322f9240237f981817aca1846f1084daa6d7c0795f6e5bf1af59c38e1858437ce1f7ec419b98c8736adf6dd9a00b1806d2bd3ad0a73775e05f52dfef3a59ab4b08143f0df05cd1ad9d04bececa6daa4a2129803e200cbc77787caf4c1d0663a6c5987b605952019782caf2ec1426d68fb94ed1d4be816a7ed081b77e6ab330b3ffc073820fecde3727fcbe295ee61a050a343658637c3fd659cfb63736de32d9f90d3c2f63eca\n\nVerify = RSA-PSS-9\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 0866d2ff5a79f25ef668cd6f31b42dee421e4c0e\nOutput = 84ebeb481be59845b46468bafb471c0112e02b235d84b5d911cbd1926ee5074ae0424495cb20e82308b8ebb65f419a03fb40e72b78981d88aad143053685172c97b29c8b7bf0ae73b5b2263c403da0ed2f80ff7450af7828eb8b86f0028bd2a8b176a4d228cccea18394f238b09ff758cc00bc04301152355742f282b54e663a919e709d8da24ade5500a7b9aa50226e0ca52923e6c2d860ec50ff480fa57477e82b0565f4379f79c772d5c2da80af9fbf325ece6fc20b00961614bee89a183e\n\nVerify = RSA-PSS-9\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 6a5b4be4cd36cc97dfde9995efbf8f097a4a991a\nOutput = 82102df8cb91e7179919a04d26d335d64fbc2f872c44833943241de8454810274cdf3db5f42d423db152af7135f701420e39b494a67cbfd19f9119da233a23da5c6439b5ba0d2bc373eee3507001378d4a4073856b7fe2aba0b5ee93b27f4afec7d4d120921c83f606765b02c19e4d6a1a3b95fa4c422951be4f52131077ef17179729cddfbdb56950dbaceefe78cb16640a099ea56d24389eef10f8fecb31ba3ea3b227c0a86698bb89e3e9363905bf22777b2a3aa521b65b4cef76d83bde4c\n\nVerify = RSA-PSS-9\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = b9dfd1df76a461c51e6576c6c8ed0a923d1c50e7\nOutput = a7fdb0d259165ca2c88d00bbf1028a867d337699d061193b17a9648e14ccbbaadeacaacdec815e7571294ebb8a117af205fa078b47b0712c199e3ad05135c504c24b81705115740802487992ffd511d4afc6b854491eb3f0dd523139542ff15c3101ee85543517c6a3c79417c67e2dd9aa741e9a29b06dcb593c2336b3670ae3afbac7c3e76e215473e866e338ca244de00b62624d6b9426822ceae9f8cc460895f41250073fd45c5a1e7b425c204a423a699159f6903e710b37a7bb2bc8049f\n\nPublicKey = RSA-PSS-10\nType = RSA\nInput = 30820122300d06092a864886f70d01010105000382010f003082010a0282010100a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae050203010001\n\nVerify = RSA-PSS-10\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 9596bb630cf6a8d4ea4600422b9eba8b13675dd4\nOutput = 82c2b160093b8aa3c0f7522b19f87354066c77847abf2a9fce542d0e84e920c5afb49ffdfdace16560ee94a1369601148ebad7a0e151cf16331791a5727d05f21e74e7eb811440206935d744765a15e79f015cb66c532c87a6a05961c8bfad741a9a6657022894393e7223739796c02a77455d0f555b0ec01ddf259b6207fd0fd57614cef1a5573baaff4ec00069951659b85f24300a25160ca8522dc6e6727e57d019d7e63629b8fe5e89e25cc15beb3a647577559299280b9b28f79b0409000be25bbd96408ba3b43cc486184dd1c8e62553fa1af4040f60663de7f5e49c04388e257f1ce",
+    "89c95dab48a315d9b66b1b7628233876ff2385230d070d07e1666\n\nVerify = RSA-PSS-10\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = b503319399277fd6c1c8f1033cbf04199ea21716\nOutput = 14ae35d9dd06ba92f7f3b897978aed7cd4bf5ff0b585a40bd46ce1b42cd2703053bb9044d64e813d8f96db2dd7007d10118f6f8f8496097ad75e1ff692341b2892ad55a633a1c55e7f0a0ad59a0e203a5b8278aec54dd8622e2831d87174f8caff43ee6c46445345d84a59659bfb92ecd4c818668695f34706f66828a89959637f2bf3e3251c24bdba4d4b7649da0022218b119c84e79a6527ec5b8a5f861c159952e23ec05e1e717346faefe8b1686825bd2b262fb2531066c0de09acde2e4231690728b5d85e115a2f6b92b79c25abc9bd9399ff8bcf825a52ea1f56ea76dd26f43baafa18bfa92a504cbd35699e26d1dcc5a2887385f3c63232f06f3244c3\n\nVerify = RSA-PSS-10\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 50aaede8536b2c307208b275a67ae2df196c7628\nOutput = 6e3e4d7b6b15d2fb46013b8900aa5bbb3939cf2c095717987042026ee62c74c54cffd5d7d57efbbf950a0f5c574fa09d3fc1c9f513b05b4ff50dd8df7edfa20102854c35e592180119a70ce5b085182aa02d9ea2aa90d1df03f2daae885ba2f5d05afdac97476f06b93b5bc94a1a80aa9116c4d615f333b098892b25fface266f5db5a5a3bcc10a824ed55aad35b727834fb8c07da28fcf416a5d9b2224f1f8b442b36f91e456fdea2d7cfe3367268de0307a4c74e924159ed33393d5e0655531c77327b89821bdedf880161c78cd4196b5419f7acc3f13e5ebf161b6e7c6724716ca33b85c2e25640192ac2859651d50bde7eb976e51cec828b98b6563b86bb\n\nVerify = RSA-PSS-10\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = aa0b72b8b371ddd10c8ae474425ccccf8842a294\nOutput = 34047ff96c4dc0dc90b2d4ff59a1a361a4754b255d2ee0af7d8bf87c9bc9e7ddeede33934c63ca1c0e3d262cb145ef932a1f2c0a997aa6a34f8eaee7477d82ccf09095a6b8acad38d4eec9fb7eab7ad02da1d11d8e54c1825e55bf58c2a23234b902be124f9e9038a8f68fa45dab72f66e0945bf1d8bacc9044c6f07098c9fcec58a3aab100c805178155f030a124c450e5acbda47d0e4f10b80a23f803e774d023b0015c20b9f9bbe7c91296338d5ecb471cafb032007b67a60be5f69504a9f01abb3cb467b260e2bce860be8d95bf92c0c8e1496ed1e528593a4abb6df462dde8a0968dffe4683116857a232f5ebf6c85be238745ad0f38f767a5fdbf486fb\n\nVerify = RSA-PSS-10\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = fad3902c9750622a2bc672622c48270cc57d3ea8\nOutput = 7e0935ea18f4d6c1d17ce82eb2b3836c55b384589ce19dfe743363ac9948d1f346b7bfddfe92efd78adb21faefc89ade42b10f374003fe122e67429a1cb8cbd1f8d9014564c44d120116f4990f1a6e38774c194bd1b8213286b077b0499d2e7b3f434ab12289c556684deed78131934bb3dd6537236f7c6f3dcb09d476be07721e37e1ceed9b2f7b406887bd53157305e1c8b4f84d733bc1e186fe06cc59b6edb8f4bd7ffefdf4f7ba9cfb9d570689b5a1a4109a746a690893db3799255a0cb9215d2d1cd490590e952e8c8786aa0011265252470c041dfbc3eec7c3cbf71c24869d115c0cb4a956f56d530b80ab589acfefc690751ddf36e8d383f83cedd2cc\n\nVerify = RSA-PSS-10\nRSAPadding = PSS\nMGF1Digest = SHA1\nInput = 122196deb5d122bd8c6fc781ff6924d7c695aade\nOutput = 6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f\n\nPrivateKey = RSA-OAEP-1\nType = RSA\nInput = 30820276020100300d06092a864886f70d0101010500048202603082025c02010002818100a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb020301000102818053339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d0cf539e9cfcdd3de653729ead5d1024100d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d024100cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d7702400e12bf1718e9cef5599ba1c3882fe8046a90874eefce8f2ccc20e4f2741fb0a33a3848aec9c9305fbecbd2d76819967d4671acc6431e4037968db37878e695c102410095297b0f95a2fa67d00707d609dfd4fc05c89dafc2ef6d6ea55bec771ea333734d9251e79082ecda866efef13c459e1a631386b7e354c899f5f112ca85d7158302404f456c502493bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a63d5411ce6fa98d5dbefd73263e3728142743818166ed7dd63687dd2a8ca1d2f4fbd8e1\n\nDecrypt = RSA-OAEP-1\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 354fe67b4a126d5d35fe36c777791a3f7ba13def484e2d3908aff722fad468fb21696de95d0be911c2d3174f8afcc201035f7b6d8e69402de5451618c21a535fa9d7bfc5b8dd9fc243f8cf927db31322d6e881eaa91a996170e657a05a266426d98c88003f8477c1227094a0d9fa1e8c4024309ce1ecccb5210035d47ac72e8a\nOutput = 6628194e12073db03ba94cda9ef9532397d50dba79b987004afefe34\n\nDecrypt = RSA-OAEP-1\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 640db1acc58e0568fe5407e5f9b701dff8c3c91e716c536fc7fcec6cb5b71c1165988d4a279e1577d730fc7a29932e3f00c81515236d8d8e31017a7a09df4352d904cdeb79aa583adcc31ea698a4c05283daba9089be5491f67c1a4ee48dc74bbbe6643aef846679b4cb395a352d5ed115912df696ffe0702932946d71492b44\nOutput = 750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5\n\nDecrypt = RSA-OAEP-1\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 423736ed035f6026af276c35c0b3741b365e5f76ca091b4e8c29e2f0befee603595aa8322d602d2e625e95eb81b2f1c9724e822eca76db8618cf09c5343503a4360835b5903bc637e3879fb05e0ef32685d5aec5067cd7cc96fe4b2670b6eac3066b1fcf5686b68589aafb7d629b02d8f8625ca3833624d4800fb081b1cf94eb\nOutput = d94ae0832e6445ce42331cb06d531a82b1db4baad30f746dc916df24d4e3c2451fff59a6423eb0e1d02d4fe646cf699dfd818c6e97b051\n\nDecrypt = RSA-OAEP-1\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 45ead4ca551e662c9800f1aca8283b0525e6abae30be4b4aba762fa40fd3d38e22abefc69794f6ebbbc05ddbb11216247d2f412fd0fba87c6e3acd888813646fd0e48e785204f9c3f73d6d8239562722dddd8771fec48b83a31ee6f592c4cfd4bc88174f3b13a112aae3b9f7b80e0fc6f7255ba880dc7d8021e22ad6a85f0755\nOutput = 52e650d98e7f2a048b4f86852153b97e01dd316f346a19f67a85\n\nDecrypt = RSA-OAEP-1\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 36f6e34d94a8d34daacba33a2139d00ad85a9345a86051e73071620056b920e219005855a213a0f23897cdcd731b45257c777fe908202befdd0b58386b1244ea0cf539a05d5d10329da44e13030fd760dcd644cfef2094d1910d3f433e1c7c6dd18bc1f2df7f643d662fb9dd37ead9059190f4fa66ca39e869c4eb449cbdc439\nOutput = 8da89fd9e5f974a29feffb462b49180f6cf9e802\n\nDecrypt = RSA-OAEP-1\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 42cee2617b1ecea4db3f4829386fbd61dafbf038e180d837c96366df24c097b4ab0fac6bdf590d821c9f10642e681ad05b8d78b378c0f46ce2fad63f74e0ad3df06b075d7eb5f5636f8d403b9059ca761b5c62bb52aa45002ea70baace08ded243b9d8cbd62a68ade265832b56564e43a6fa42ed199a099769742df1539e8255\nOutput = 26521050844271\n\nPrivateKey = RSA-OAEP-2\nType = RSA\nInput = 30820276020100300d06092a864886f70d0101010500048202603082025c02010002818101947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f4502030100010281800823f20fadb5da89088a9d00893e21fa4a1b11fbc93c64a3be0baaea97fb3b93c3ff713704c19c963c1d107aae99054739f79e02e186de86f87a6ddefea6d8ccd1d3c81a47bfa7255be20601a4a4b2f08a167b5e279d715b1b455bdd7eab245941d9768b9acefb3ccda5952da3cee72525b4501663a8ee15c9e992d92462fe3902410159dbde04a33ef06fb608b80b190f4d3e22bcc13ac8e4a081033abfa416edb0b338aa08b57309ea5a5240e7dc6e54378c69414c31d97ddb1f406db3769cc41a430241012b652f30403b38b40995fd6ff41a1acc8ada70373236b7202d39b2ee30cfb46db09511f6f307cc61cc21606c18a75b8a62f822df031ba0df0dafd5506f568bd70240436ef508de736519c2da4c580d98c82cb7452a3fb5efadc3b9c7789a1bc6584f795addbbd32439c74686552ecb6c2c307a4d3af7f539eec157248c7b31f1a2550241012b15a89f3dfb2b39073e73f02bdd0c1a7b379dd435f05cdde2eff9e462948b7cec62ee9050d5e0816e0785a856b49108dcb75f3683874d1ca6329a19013066ff02400270db17d5914b018d76118b24389a7350ec836b0063a21721236fd8edb6d89b51e7eeb87b611b7132cb7ea7356c23151c1e7751507c786d9ee1794170a8c8e8\n\nDecrypt = RSA-OAEP-2\nRSAPadding = OAEP\nMGF1Digest ",
+    "= SHA1\nInput = 0181af8922b9fcb4d79d92ebe19815992fc0c1439d8bcd491398a0f4ad3a329a5bd9385560db532683c8b7da04e4b12aed6aacdf471c34c9cda891addcc2df3456653aa6382e9ae59b54455257eb099d562bbe10453f2b6d13c59c02e10f1f8abb5da0d0570932dacf2d0901db729d0fefcc054e70968ea540c81b04bcaefe720e\nOutput = 8ff00caa605c702830634d9a6c3d42c652b58cf1d92fec570beee7\n\nDecrypt = RSA-OAEP-2\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 018759ff1df63b2792410562314416a8aeaf2ac634b46f940ab82d64dbf165eee33011da749d4bab6e2fcd18129c9e49277d8453112b429a222a8471b070993998e758861c4d3f6d749d91c4290d332c7a4ab3f7ea35ff3a07d497c955ff0ffc95006b62c6d296810d9bfab024196c7934012c2df978ef299aba239940cba10245\nOutput = 2d\n\nDecrypt = RSA-OAEP-2\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 018802bab04c60325e81c4962311f2be7c2adce93041a00719c88f957575f2c79f1b7bc8ced115c706b311c08a2d986ca3b6a9336b147c29c6f229409ddec651bd1fdd5a0b7f610c9937fdb4a3a762364b8b3206b4ea485fd098d08f63d4aa8bb2697d027b750c32d7f74eaf5180d2e9b66b17cb2fa55523bc280da10d14be2053\nOutput = 74fc88c51bc90f77af9d5e9a4a70133d4b4e0b34da3c37c7ef8e\n\nDecrypt = RSA-OAEP-2\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 00a4578cbc176318a638fba7d01df15746af44d4f6cd96d7e7c495cbf425b09c649d32bf886da48fbaf989a2117187cafb1fb580317690e3ccd446920b7af82b31db5804d87d01514acbfa9156e782f867f6bed9449e0e9a2c09bcecc6aa087636965e34b3ec766f2fe2e43018a2fddeb140616a0e9d82e5331024ee0652fc7641\nOutput = a7eb2a5036931d27d4e891326d99692ffadda9bf7efd3e34e622c4adc085f721dfe885072c78a203b151739be540fa8c153a10f00a\n\nDecrypt = RSA-OAEP-2\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 00ebc5f5fda77cfdad3c83641a9025e77d72d8a6fb33a810f5950f8d74c73e8d931e8634d86ab1246256ae07b6005b71b7f2fb98351218331ce69b8ffbdc9da08bbc9c704f876deb9df9fc2ec065cad87f9090b07acc17aa7f997b27aca48806e897f771d95141fe4526d8a5301b678627efab707fd40fbebd6e792a25613e7aec\nOutput = 2ef2b066f854c33f3bdcbb5994a435e73d6c6c\n\nDecrypt = RSA-OAEP-2\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 010839ec20c27b9052e55befb9b77e6fc26e9075d7a54378c646abdf51e445bd5715de81789f56f1803d9170764a9e93cb78798694023ee7393ce04bc5d8f8c5a52c171d43837e3aca62f609eb0aa5ffb0960ef04198dd754f57f7fbe6abf765cf118b4ca443b23b5aab266f952326ac4581100644325f8b721acd5d04ff14ef3a\nOutput = 8a7fb344c8b6cb2cf2ef1f643f9a3218f6e19bba89c0\n\nPrivateKey = RSA-OAEP-3\nType = RSA\nInput = 30820277020100300d06092a864886f70d0101010500048202613082025d02010002818102b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9020301000102818015b48a5b5683a94670e23b5718f814fa0e13f85038f50711182cba61510581f3d22c7e232ef937e22e551d68b86e2f8cb1aad8be2e488f5df7efd279e3f568d4eaf36f80cf7141ace60fcc9113fb6c4a841fd50bbc7c512ffcbeff21487aa811eb3ca8c62005346a86de86bfa1d8a948fd3f348c22eaadf333c3ce6ce13208fd024101bf01d216d73595cf0270c2beb78d40a0d8447d31da919a983f7eea781b77d85fe371b3e9373e7b69217d3150a02d8958de7fad9d555160958b4454127e0e7eaf0241018d3399658166db3829816d7b295416759e9c91987f5b2d8aecd63b04b48bd7b2fcf229bb7f8a6dc88ba13dd2e39ad55b6d1a06160708f9700be80b8fd3744ce7024006c0a249d20a6f2ee75c88b494d53f6aae99aa427c88c28b163a769445e5f390cf40c274fd6ea6329a5ce7c7ce03a2158396ee2a7845786e09e2885a9728e4e5024100d1d27c29fedd92d86c348edd0ccbfac14f746e051ce1d1811df35d61f2ee1c97d4bf2804802f6427187ba8e90a8af44243b4079b03445e602e29fa5193e64fe90241008cb2f756bd8941b1d3b770e5ad31ee373b28acda69ff9b6f40fe578b9f1afb85836f9627d37acff73c2779e634bb26011c2c8f7f3361ae2a9ea65ed689e3639a\n\nDecrypt = RSA-OAEP-3\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 026a0485d96aebd96b4382085099b962e6a2bdec3d90c8db625e14372de85e2d5b7baab65c8faf91bb5504fb495afce5c988b3f6a52e20e1d6cbd3566c5cd1f2b8318bb542cc0ea25c4aab9932afa20760eaddec784396a07ea0ef24d4e6f4d37e5052a7a31e146aa480a111bbe926401307e00f410033842b6d82fe5ce4dfae80\nOutput = 087820b569e8fa8d\n\nDecrypt = RSA-OAEP-3\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 024db89c7802989be0783847863084941bf209d761987e38f97cb5f6f1bc88da72a50b73ebaf11c879c4f95df37b850b8f65d7622e25b1b889e80fe80baca2069d6e0e1d829953fc459069de98ea9798b451e557e99abf8fe3d9ccf9096ebbf3e5255d3b4e1c6d2ecadf067a359eea86405acd47d5e165517ccafd47d6dbee4bf5\nOutput = 4653acaf171960b01f52a7be63a3ab21dc368ec43b50d82ec3781e04\n\nDecrypt = RSA-OAEP-3\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 0239bce681032441528877d6d1c8bb28aa3bc97f1df584563618995797683844ca86664732f4bed7a0aab083aaabfb7238f582e30958c2024e44e57043b97950fd543da977c90cdde5337d618442f99e60d7783ab59ce6dd9d69c47ad1e962bec22d05895cff8d3f64ed5261d92b2678510393484990ba3f7f06818ae6ffce8a3a\nOutput = d94cd0e08fa404ed89\n\nDecrypt = RSA-OAEP-3\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 02994c62afd76f498ba1fd2cf642857fca81f4373cb08f1cbaee6f025c3b512b42c3e8779113476648039dbe0493f9246292fac28950600e7c0f32edf9c81b9dec45c3bde0cc8d8847590169907b7dc5991ceb29bb0714d613d96df0f12ec5d8d3507c8ee7ae78dd83f216fa61de100363aca48a7e914ae9f42ddfbe943b09d9a0\nOutput = 6cc641b6b61e6f963974dad23a9013284ef1\n\nDecrypt = RSA-OAEP-3\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 0162042ff6969592a6167031811a239834ce638abf54fec8b99478122afe2ee67f8c5b18b0339805bfdbc5a4e6720b37c59cfba942464c597ff532a119821545fd2e59b114e61daf71820529f5029cf524954327c34ec5e6f5ba7efcc4de943ab8ad4ed787b1454329f70db798a3a8f4d92f8274e2b2948ade627ce8ee33e43c60\nOutput = df5151832b61f4f25891fb4172f328d2eddf8371ffcfdbe997939295f30eca6918017cfda1153bf7a6af87593223\n\nDecrypt = RSA-OAEP-3\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 00112051e75d064943bc4478075e43482fd59cee0679de6893eec3a943daa490b9691c93dfc0464b6623b9f3dbd3e70083264f034b374f74164e1a00763725e574744ba0b9db83434f31df96f6e2a26f6d8eba348bd4686c2238ac07c37aac3785d1c7eea2f819fd91491798ed8e9cef5e43b781b0e0276e37c43ff9492d005730\nOutput = 3c3bad893c544a6d520ab022319188c8d504b7a788b850903b85972eaa18552e1134a7ad6098826254ff7ab672b3d8eb3158fac6d4cbaef1\n\nPrivateKey = RSA-OAEP-4\nType = RSA\nInput = 30820277020100300d06092a864886f70d0101010500048202613082025d020100028181051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb03902030100010281800411ffca3b7ca5e9e9be7fe38a85105e353896db05c5796aecd2a725161eb3651c8629a9b862b904d7b0c7b37f8cb5a1c2b54001018a00a1eb2cafe4ee4e9492c348bc2bedab4b9ebbf064e8eff322b9009f8eec653905f40df88a3cdc49d4567f75627d41aca624129b46a0b7c698e5e65f2b7ba102c749a10135b6540d04010241027458c19ec1636919e736c9af25d609a51b8f561d19c6bf6943dd1ee1ab8a4a3f232100bd40b88decc6ba235548b6ef792a11c9de823d0a7922c7095b6eba570102410210ee9b33ab61716e27d251bd465f4b35a1a232e2da00901c294bf22350ce490d099f642b5375612db63ba1f20386492bf04d34b3c22bceb909d13441b53b5139024039fa028b826e88c1121b750a8b242fa9a35c5b66bdfd1fa637d3cc48a84a4f457a194e7727e49f7bcc6e5a5a412657fc470c7322ebc37416ef458c307a8c09010241015d99a84195943979fa9e1be2c3c1b69f432f46fd03e47d5befbbbfd6b1d1371d83efb330a3e020942b2fed115e5d02be24fd92c9019d1cecd6dd4cf1e54cc899024101f0b7015170b3f5e42223ba30301c41a6d87cbb70e30cb7d3c67d25473db1f6cbf03e3f9126e3e97968279a865b2c2b426524cfc52a683d31ed30eb984be412ba\n\nDecrypt = RSA-OAEP-4\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 04cce19614845e094152a3fe18e54e3330c44e5efbc64ae16886cb1869014cc5781b1f8f9e045384d0112a135ca0d12e9c88a8e4063416deaae3844f60d6e96fe155145f4525b9a34431ca3766180f70e15a5e5d8e8b1a516ff870609f13f896935ced188279a58ed13d07114277d75c6568607e0ab092fd803a223e4a8ee0b1a8\nOutput = 4a86609534ee434a6cbca3f7e962e76d455e3264c19f605f6e5ff6137c65c56d7fb344cd52bc93374f3d166c9f0c6f9c506bad19330972d2\n\nDecrypt = RSA-OAEP-4\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 0097b698c6165645b303486fbf5a2a4479c0ee85889b541a6f0b858d6b6597b13b854eb4f839af03399a80d79bda6578c841f90d645715b280d37143992dd186c80b949b775cae97370e4ec97443136c6da484e970ffdb1323a20847821d3b18381de13bb49aaea66530c4a4b8271f3eae172cd366e07e6636f1019d2a28aed15e\nOutput = b0adc4f3fe11da59ce992773d9059943c03046497ee9d9f9a06df1166db46d98f58d27ec074c02eee6cbe2449c8b9fc5080c5c3f4433092512ec46aa793743c8\n\nDecrypt = RSA-OAEP-4\nRSAPadding = OAEP\nMGF1Digest = SHA1",
+    "\nInput = 0301f935e9c47abcb48acbbe09895d9f5971af14839da4ff95417ee453d1fd77319072bb7297e1b55d7561cd9d1bb24c1a9a37c619864308242804879d86ebd001dce5183975e1506989b70e5a83434154d5cbfd6a24787e60eb0c658d2ac193302d1192c6e622d4a12ad4b53923bca246df31c6395e37702c6a78ae081fb9d065\nOutput = bf6d42e701707b1d0206b0c8b45a1c72641ff12889219a82bdea965b5e79a96b0d0163ed9d578ec9ada20f2fbcf1ea3c4089d83419ba81b0c60f3606da99\n\nDecrypt = RSA-OAEP-4\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 02d110ad30afb727beb691dd0cf17d0af1a1e7fa0cc040ec1a4ba26a42c59d0a796a2e22c8f357ccc98b6519aceb682e945e62cb734614a529407cd452bee3e44fece8423cc19e55548b8b994b849c7ecde4933e76037e1d0ce44275b08710c68e430130b929730ed77e09b015642c5593f04e4ffb9410798102a8e96ffdfe11e4\nOutput = fb2ef112f5e766eb94019297934794f7be2f6fc1c58e\n\nDecrypt = RSA-OAEP-4\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 00dbb8a7439d90efd919a377c54fae8fe11ec58c3b858362e23ad1b8a44310799066b99347aa525691d2adc58d9b06e34f288c170390c5f0e11c0aa3645959f18ee79e8f2be8d7ac5c23d061f18dd74b8c5f2a58fcb5eb0c54f99f01a83247568292536583340948d7a8c97c4acd1e98d1e29dc320e97a260532a8aa7a758a1ec2\nOutput = 28ccd447bb9e85166dabb9e5b7d1adadc4b9d39f204e96d5e440ce9ad928bc1c2284\n\nDecrypt = RSA-OAEP-4\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 00a5ffa4768c8bbecaee2db77e8f2eec99595933545520835e5ba7db9493d3e17cddefe6a5f567624471908db4e2d83a0fbee60608fc84049503b2234a07dc83b27b22847ad8920ff42f674ef79b76280b00233d2b51b8cb2703a9d42bfbc8250c96ec32c051e57f1b4ba528db89c37e4c54e27e6e64ac69635ae887d9541619a9\nOutput = f22242751ec6b1\n\nPrivateKey = RSA-OAEP-5\nType = RSA\nInput = 30820279020100300d06092a864886f70d0101010500048202633082025f0201000281810aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed902030100010281810256eb4cba7067f2d2be540dcdff4582a36b7d31d1c9099bb214b79848466a268f80f58a49ac04c0e3648934a0206c04537c19b236643a6082732144df75fa217588f794682be89168276dc726c5c0cbdb84d31bbf26d0a43af495717f7d528acfee341561f6ff3cae05c578f8470d9682f9c0d072f9f6068b56d5880f682be2c5024103b0d3962f6d17549cbfca11294348dcf0e7e39f8c2bc6824f2164b606d687860dae1e632393cfedf513228229069e2f60e4acd7e633a436063f82385f48993707024102e4c32e2f517269b7072309f00c0e31365f7ce28b236b82912df239abf39572cf0ed604b02982e53564c52d6a05397de5c052a2fddc141ef7189836346aeb331f024101e84b119d25161fa67b00256a5bd9b645d2b232ecb05b015180029a88622adc3f09b3aeacde6161ab7cde22c2ad26e7797df54e072cbd3b2673800b3e4338dbd5024100eb90aa1a40135b4cea07197cedc8819be1e7cbff2547662116f465a4a9f487ab12f3ba4fef13822265a65297d98b7bded9372e3ffe81a38b3e9600fed055754f0241012f7f8138f9404062eb85a42924520b38f5bb886a0196f48bb8dcea60fd92cc027f18e78158a34a5c5d5f860a0f6c04071a7d01312c065062f1eb48b79d1c83cb\n\nDecrypt = RSA-OAEP-5\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 036046a4a47d9ed3ba9a89139c105038eb7492b05a5d68bfd53accff4597f7a68651b47b4a4627d927e485eed7b4566420e8b409879e5d606eae251d22a5df799f7920bfc117b992572a53b1263146bcea03385cc5e853c9a101c8c3e1bda31a519807496c6cb5e5efb408823a352b8fa0661fb664efadd593deb99fff5ed000e5\nOutput = af71a901e3a61d3132f0fc1fdb474f9ea6579257ffc24d164170145b3dbde8\n\nDecrypt = RSA-OAEP-5\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 03d6eb654edce615bc59f455265ed4e5a18223cbb9be4e4069b473804d5de96f54dcaaa603d049c5d94aa1470dfcd2254066b7c7b61ff1f6f6770e3215c51399fd4e34ec5082bc48f089840ad04354ae66dc0f1bd18e461a33cc1258b443a2837a6df26759aa2302334986f87380c9cc9d53be9f99605d2c9a97da7b0915a4a7ad\nOutput = a3b844a08239a8ac41605af17a6cfda4d350136585903a417a79268760519a4b4ac3303ec73f0f87cfb32399\n\nDecrypt = RSA-OAEP-5\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 0770952181649f9f9f07ff626ff3a22c35c462443d905d456a9fd0bff43cac2ca7a9f554e9478b9acc3ac838b02040ffd3e1847de2e4253929f9dd9ee4044325a9b05cabb808b2ee840d34e15d105a3f1f7b27695a1a07a2d73fe08ecaaa3c9c9d4d5a89ff890d54727d7ae40c0ec1a8dd86165d8ee2c6368141016a48b55b6967\nOutput = 308b0ecbd2c76cb77fc6f70c5edd233fd2f20929d629f026953bb62a8f4a3a314bde195de85b5f816da2aab074d26cb6acddf323ae3b9c678ac3cf12fbdde7\n\nDecrypt = RSA-OAEP-5\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 0812b76768ebcb642d040258e5f4441a018521bd96687e6c5e899fcd6c17588ff59a82cc8ae03a4b45b31299af1788c329f7dcd285f8cf4ced82606b97612671a45bedca133442144d1617d114f802857f0f9d739751c57a3f9ee400912c61e2e6992be031a43dd48fa6ba14eef7c422b5edc4e7afa04fdd38f402d1c8bb719abf\nOutput = 15c5b9ee1185\n\nDecrypt = RSA-OAEP-5\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 07b60e14ec954bfd29e60d0047e789f51d57186c63589903306793ced3f68241c743529aba6a6374f92e19e0163efa33697e196f7661dfaaa47aac6bde5e51deb507c72c589a2ca1693d96b1460381249b2cdb9eac44769f2489c5d3d2f99f0ee3c7ee5bf64a5ac79c42bd433f149be8cb59548361640595513c97af7bc2509723\nOutput = 21026e6800c7fa728fcaaba0d196ae28d7a2ac4ffd8abce794f0985f60c8a6737277365d3fea11db8923a2029a\n\nDecrypt = RSA-OAEP-5\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 08c36d4dda33423b2ed6830d85f6411ba1dcf470a1fae0ebefee7c089f256cef74cb96ea69c38f60f39abee44129bcb4c92de7f797623b20074e3d9c2899701ed9071e1efa0bdd84d4c3e5130302d8f0240baba4b84a71cc032f2235a5ff0fae277c3e8f9112bef44c9ae20d175fc9a4058bfc930ba31b02e2e4f444483710f24a\nOutput = 541e37b68b6c8872b84c02\n\nPrivateKey = RSA-OAEP-6\nType = RSA\nInput = 30820279020100300d06092a864886f70d0101010500048202633082025f02010002818112b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af02030100010281810295eca3560618369559cecd303aa9cfdafc1d9f06959df75ffef929aa896961bcd190dc6997eda7f5963e724d07b4dc11f3065e5ae97d96835112280b9084bb14f2a21ebd4e889d41b9c4132ec1956fcab8bb2fed0575884936522c5ff7d33261904824e7cadee4e0bb372d2457cf78e2bd1286228ff83f10731ce63c90cff3f9024104a6ce8b7358dfa69bdcf742617005afb5385f5f3a58a24ef74a22a8c05cb7cc38ebd4cc9d9a9d789a62cd0f60f0cb941d3423c9692efa4fe3adff290c4749a38b02410404c9a803371fedb4c5be39f3c00b009e5e08a63be1e40035cdaca5011cc701cf7eebcb99f0ffe17cfd0a4bf7befd2dd536ac946db797fdbc4abe8f29349b91ed024103961c8f760aa2bd5154c7aafd77225b3bacd0139ae7b5948ea3311fccd86fb95c75afa767284b9b2de559572f15d8d044c7eb83a1be5fadf2cc377c0d8475294b0241022197e066742196aabc03fa2feeb4e70b15cb787d617acd31bb75c7bc234ad706f7c48d2182d1f0ff9c228dcf41967b6c0ba6d2c0ad110a1b857831ec245e2cb102410401c4c0c53d45dbdb5e9d96d0fecf4275df0974bc4a0736b4a74c3269053efb686ace2406e22c9e058ddb4ae540627ae2fdb08261e8e7e4bcbc994daafa305c45\n\nDecrypt = RSA-OAEP-6\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 0630eebcd2856c24f798806e41f9e67345eda9ceda386acc9facaea1eeed06ace583709718d9d169fadf414d5c76f92996833ef305b75b1e4b95f662a20faedc3bae0c4827a8bf8a88edbd57ec203a27a841f02e43a615bab1a8cac0701de34debdef62a088089b55ec36ea7522fd3ec8d06b6a073e6df833153bc0aefd93bd1a3\nOutput = 4046ca8baa3347ca27f49e0d81f9cc1d71be9ba517d4\n\nDecrypt = RSA-OAEP-6\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 0ebc37376173a4fd2f89cc55c2ca62b26b11d51c3c7ce49e8845f74e7607317c436bc8d23b9667dfeb9d087234b47bc6837175ae5c0559f6b81d7d22416d3e50f4ac533d8f0812f2db9e791fe9c775ac8b6ad0f535ad9ceb23a4a02014c58ab3f8d3161499a260f39348e714ae2a1d3443208fd8b722ccfdfb393e98011f99e63f\nOutput = 5cc72c60231df03b3d40f9b57931bc31109f972527f28b19e7480c7288cb3c92b22512214e4be6c914792ddabdf57faa8aa7\n\nDecrypt = RSA-OAEP-6\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 0a98bf1093619394436cf68d8f38e2f158fde8ea54f3435f239b8d06b8321844202476aeed96009492480ce3a8d705498c4c8c68f01501dc81db608f60087350c8c3b0bd2e9ef6a81458b7c801b89f2e4fe99d4900ba6a4b5e5a96d865dc676c7755928794130d6280a8160a190f2df3ea7cf9aa0271d88e9e6905ecf1c5152d65\nOutput = b20e651303092f4bccb43070c0f86d23049362ed96642fc5632c27db4a52e3d831f2ab068b23b149879c002f6bf3feee97591112562c\n\nDecrypt = RSA-OAEP-6\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 008e7a67cacfb5c4e24bec7dee149117f19598ce8c45808fef88c608ff9cd6e695263b9a3c0ad4b8ba4c95238e96a8422b8535629c8d5382374479ad13fa39974b242f9a759eeaf9c83ad5a8ca18940a0162ba755876df263f4bd50c6525c56090267c1f0e09ce0899a0cf359e88120abd9bf893445b3cae77d3607359ae9a52f8\nOutput = 684e3038c5c041f7\n\nDe",
+    "crypt = RSA-OAEP-6\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 00003474416c7b68bdf961c385737944d7f1f40cb395343c693cc0b4fe63b31fedf1eaeeac9ccc0678b31dc32e0977489514c4f09085f6298a9653f01aea4045ff582ee887be26ae575b73eef7f3774921e375a3d19adda0ca31aa1849887c1f42cac9677f7a2f4e923f6e5a868b38c084ef187594dc9f7f048fea2e02955384ab\nOutput = 32488cb262d041d6e4dd35f987bf3ca696db1f06ac29a44693\n\nDecrypt = RSA-OAEP-6\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 0a026dda5fc8785f7bd9bf75327b63e85e2c0fdee5dadb65ebdcac9ae1de95c92c672ab433aa7a8e69ce6a6d8897fac4ac4a54de841ae5e5bbce7687879d79634cea7a30684065c714d52409b928256bbf53eabcd5231eb7259504537399bd29164b726d33a46da701360a4168a091ccab72d44a62fed246c0ffea5b1348ab5470\nOutput = 50ba14be8462720279c306ba\n\nPrivateKey = RSA-OAEP-7\nType = RSA\nInput = 30820278020100300d06092a864886f70d0101010500048202623082025e020100028181311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e3730203010001028181070cfcff2feb8276e27432c45dfee48f49b7917d6530e1f0ca3460f32e0276174487c56e22a45d2500d7775495219d7d165a9cf3bd92c32af9a98d8dc9cc296800adc94a0a54fb40f34291bf84ee8ea12b6f109359c6d3542a50f9c767f5cfff05a681c2e656fb77caaadb4be9468d8abcd4df98f58e86d2053fa1349f748e21b102410749262c111cd470ec2566e6b3732fc09329469aa19071d3b9c01906514c6f1d26baa14beab0971c8b7e611a4f79009d6fea776928ca25285b0de3643d1a3f8c71024106bc1e50e96c02bf636e9eea8b899bbebf7651de77dd474c3e9bc23bad8182b61904c7d97dfbebfb1e00108878b6e67e415391d67942c2b2bf9b4435f88b0cb023024103bc7ea7f0aab143abc6ce8b97118636a30172e4cfe02c8fa0dda3b7baaf90f8092982985525f488bdfcb4bd726e22639ac64a3092ab7ffcbf1d5334cfa50b5bf102410262a6aa29c2a3c67dc5346c06381afd987aa3cc93cfbfecf54fdd9f9d787d7f59a523d398979da137a2f6381fe94801f7c94da21518dc34cb40870c4697994ad90240649d4c17b6ee1721e772d0389a559c3d3cdf9550d457c46b037b74641b1d52166af8a213c8396206cdfba4422f18d6f61dbcb5d214c971bf482aeb976a7370c2\n\nDecrypt = RSA-OAEP-7\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 1688e4ce7794bba6cb7014169ecd559cede2a30b56a52b68d9fe18cf1973ef97b2a03153951c755f6294aa49adbdb55845ab6875fb3986c93ecf927962840d282f9e54ce8b690f7c0cb8bbd73440d9571d1b16cd9260f9eab4783cc482e5223dc60973871783ec27b0ae0fd47732cbc286a173fc92b00fb4ba6824647cd93c85c1\nOutput = 47aae909\n\nDecrypt = RSA-OAEP-7\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 1052ed397b2e01e1d0ee1c50bf24363f95e504f4a03434a08fd822574ed6b9736edbb5f390db10321479a8a139350e2bd4977c3778ef331f3e78ae118b268451f20a2f01d471f5d53c566937171b2dbc2d4bde459a5799f0372d6574239b2323d245d0bb81c286b63c89a361017337e4902f88a467f4c7f244bfd5ab46437ff3b6\nOutput = 1d9b2e2223d9bc13bfb9f162ce735db48ba7c68f6822a0a1a7b6ae165834e7\n\nDecrypt = RSA-OAEP-7\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 2155cd843ff24a4ee8badb7694260028a490813ba8b369a4cbf106ec148e5298707f5965be7d101c1049ea8584c24cd63455ad9c104d686282d3fb803a4c11c1c2e9b91c7178801d1b6640f003f5728df007b8a4ccc92bce05e41a27278d7c85018c52414313a5077789001d4f01910b72aad05d220aa14a58733a7489bc54556b\nOutput = d976fc\n\nDecrypt = RSA-OAEP-7\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 0ab14c373aeb7d4328d0aaad8c094d88b9eb098b95f21054a29082522be7c27a312878b637917e3d819e6c3c568db5d843802b06d51d9e98a2be0bf40c031423b00edfbff8320efb9171bd2044653a4cb9c5122f6c65e83cda2ec3c126027a9c1a56ba874d0fea23f380b82cf240b8cf540004758c4c77d934157a74f3fc12bfac\nOutput = d4738623df223aa43843df8467534c41d013e0c803c624e263666b239bde40a5f29aeb8de79e3daa61dd0370f49bd4b013834b98212aef6b1c5ee373b3cb\n\nDecrypt = RSA-OAEP-7\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 028387a318277434798b4d97f460068df5298faba5041ba11761a1cb7316b24184114ec500257e2589ed3b607a1ebbe97a6cc2e02bf1b681f42312a33b7a77d8e7855c4a6de03e3c04643f786b91a264a0d6805e2cea91e68177eb7a64d9255e4f27e713b7ccec00dc200ebd21c2ea2bb890feae4942df941dc3f97890ed347478\nOutput = bb47231ca5ea1d3ad46c99345d9a8a61\n\nDecrypt = RSA-OAEP-7\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 14c678a94ad60525ef39e959b2f3ba5c097a94ff912b67dbace80535c187abd47d075420b1872152bba08f7fc31f313bbf9273c912fc4c0149a9b0cfb79807e346eb332069611bec0ff9bcd168f1f7c33e77313cea454b94e2549eecf002e2acf7f6f2d2845d4fe0aab2e5a92ddf68c480ae11247935d1f62574842216ae674115\nOutput = 2184827095d35c3f86f600e8e59754013296\n\nPrivateKey = RSA-OAEP-8\nType = RSA\nInput = 30820279020100300d06092a864886f70d0101010500048202633082025f0201000281815bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff702030100010281810f7d1e9e5aaa25fd13e4a0663ae144e0d15f5cd18bcdb09df2cc7e64e3c5e915ad62645304161d098c715bb7ab8bd01d07eaf3fed7c7ed08af2a8a62ef44ab16b320e14af72a48f96afe262a0ae4cf65e635e910790cd4ee5cea768a4b2639f7e6f677b3f0bb6be32b75747d8909036f0264f58d401cdba131716157a75ecf633102410a02ef8448d9fad8bbd0d004c8c2aa9751ef9721c1b0d03236a54b0df947cbaed5a255ee9e8e20d491ea1723fe094704a9762e88afd16ebb5994412ca966dc4f9f0241092d362e7ed3a0bfd9e9fd0e6c0301b6df29159cf50cc83b9b0cf4d6eea71a61e002b46e0ae9f2de62d25b5d7452d498b81c9ac6fc58593d4c3fb4f5d72dfbb0a9024107c71410af103962db367404e37ae850baa4e9c29dd92145815294a67c7d1c6ded263aa030a9b633ae50303e14035d1af014123eba687820308d8ebc85b6957d7d024100ae2c75380c02c016ad05891b3301de881f28ae1171182b6b2c83bea7c515eca9ca298c7b1cab5817a597068fc85060de4da8a016378aae43c7f967bcc37904b902410598d1059e3ada4f6320752c09d805ff7d1f1ae0d017aeeee9cefa0d7dd7ff775e44b578322f6405d6211da19519666aa87fdc4cd8c88f6b6e3d67e961dcbba3d0\n\nDecrypt = RSA-OAEP-8\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 09b3683d8a2eb0fb295b62ed1fb9290b714457b7825319f4647872af889b30409472020ad12912bf19b11d4819f49614824ffd84d09c0a17e7d17309d12919790410aa2995699f6a86dbe3242b5acc23af45691080d6b1ae810fb3e3057087f0970092ce00be9562ff4053b6262ce0caa93e13723d2e3a5ba075d45f0d61b54b61\nOutput = 050b755e5e6880f7b9e9d692a74c37aae449b31bfea6deff83747a897f6c2c825bb1adbf850a3c96994b5de5b33cbc7d4a17913a7967\n\nDecrypt = RSA-OAEP-8\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 2ecf15c97c5a15b1476ae986b371b57a24284f4a162a8d0c8182e7905e792256f1812ba5f83f1f7a130e42dcc02232844edc14a31a68ee97ae564a383a3411656424c5f62ddb646093c367be1fcda426cf00a06d8acb7e57776fbbd855ac3df506fc16b1d7c3f2110f3d8068e91e186363831c8409680d8da9ecd8cf1fa20ee39d\nOutput = 4eb68dcd93ca9b19df111bd43608f557026fe4aa1d5cfac227a3eb5ab9548c18a06dded23f81825986b2fcd71109ecef7eff88873f075c2aa0c469f69c92bc\n\nDecrypt = RSA-OAEP-8\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 4bc89130a5b2dabb7c2fcf90eb5d0eaf9e681b7146a38f3173a3d9cfec52ea9e0a41932e648a9d69344c50da763f51a03c95762131e8052254dcd2248cba40fd31667786ce05a2b7b531ac9dac9ed584a59b677c1a8aed8c5d15d68c05569e2be780bf7db638fd2bfd2a85ab276860f3777338fca989ffd743d13ee08e0ca9893f\nOutput = 8604ac56328c1ab5ad917861\n\nDecrypt = RSA-OAEP-8\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 2e456847d8fc36ff0147d6993594b9397227d577752c79d0f904fcb039d4d812fea605a7b574dd82ca786f93752348438ee9f5b5454985d5f0e1699e3e7ad175a32e15f03deb042ab9fe1dd9db1bb86f8c089ccb45e7ef0c5ee7ca9b7290ca6b15bed47039788a8a93ff83e0e8d6244c71006362deef69b6f416fb3c684383fbd0\nOutput = fdda5fbf6ec361a9d9a4ac68af216a0686f438b1e0e5c36b955f74e107f39c0dddcc\n\nDecrypt = RSA-OAEP-8\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 1fb9356fd5c4b1796db2ebf7d0d393cc810adf6145defc2fce714f79d93800d5e2ac211ea8bbecca4b654b94c3b18b30dd576ce34dc95436ef57a09415645923359a5d7b4171ef22c24670f1b229d3603e91f76671b7df97e7317c97734476d5f3d17d21cf82b5ba9f83df2e588d36984fd1b584468bd23b2e875f32f68953f7b2\nOutput = 4a5f4914bee25de3c69341de07\n\nDecrypt = RSA-OAEP-8\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 3afd9c6600147b21798d818c655a0f4c9212db26d0b0dfdc2a7594ccb3d22f5bf1d7c3e112cd73fc7d509c7a8bafdd3c274d1399009f9609ec4be6477e453f075aa33db382870c1c3409aef392d7386ae3a696b99a94b4da0589447e955d16c98b17602a59bd736279fcd8fb280c4462d590bfa9bf13fed570eafde97330a2c210\nOutput = 8e07d66f7b880a72563abcd3f35092bc33409fb7f88f2472be\n\nPrivateKey = RSA-OAEP-9\nType = RSA\nInput = 30820397020100300d06092a864886f70d0101010500048203813082037d0201000281c100cf2cd41",
+    "e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d02030100010281c0198c141e23715a92bccf6a119a5bc11389468d2811f548d727e17b4ab0eb986d6f211efb53b71f7ccbea87ee69c75ee615008c5332deb52bf390abdfbfe37d7205368159b2638c1de326e21d22251f0fb5848b3bf15005d2a74330f0afe916ee62ccc1344d1d83a709e60676273840f7f377424a5e0a4da75f01b31ff76819cf9cbfdd215243c3917c03ef38199312e567b3bf7aed3ab457f371ef8a1423f45b68c6e282ec111bba2833b987fd69fad83bc1b8c613c5e1ea16c11ed125ea7ec1026100fc8d6c04bec4eb9a8192ca7900cbe536e2e8b519decf33b2459798c6909df4f176db7d23190fc72b8865a718af895f1bcd9145298027423b605e70a47cf58390a8c3e88fc8c48e8b32e3da210dfbe3e881ea5674b6a348c21e93f9e55ea65efd026100d200d45e788aacea606a401d0460f87dd5c1027e12dc1a0d7586e8939d9cf789b40f51ac0442961de7d21cc21e05c83155c1f2aa9193387cfdf956cb48d153ba270406f9bbba537d4987d9e2f9942d7a14cbfffea74fecdda928d23e259f5ee1026100db16802f79a2f0d45f358d69fd33e44b81fae828622e93a54253e997d01b0743759da0e812b4aa4e6c8beab2328d5431955a418a67ff26a8c5c807a5da354e05ef31cc8cf758f463732950b03e265726fb94e39d6a572a26244ab08db75752ad026100a0a317cfe7df1423f87a6dee8451f4e2b4a67e5497f29b4f1e4e830b9fadd9401167026f5596e5a39c97817e0f5f16e27e19ec9902e01d7ea6fb9aa3c760afee1e381b69de6ac9c07585a06ad9c4ba00bf75c8ad2fa898a479e80ae294fed2a102600b21f335c353342eb44c3aa24445780c2d655b940174cae38c7c8a4e6493c0ba9fd303748267b083b9a7a6cb61e42db362b8c9896db7064e02ad5ae61587da15b4649c90594909feb37dbcb654beb7268ec801e5a8b4aa3911bebd88542f05be\n\nDecrypt = RSA-OAEP-9\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 267bcd118acab1fc8ba81c85d73003cb8610fa55c1d97da8d48a7c7f06896a4db751aa284255b9d36ad65f37653d829f1b37f97b8001942545b2fc2c55a7376ca7a1be4b1760c8e05a33e5aa2526b8d98e317088e7834c755b2a59b12631a182c05d5d43ab1779264f8456f515ce57dfdf512d5493dab7b7338dc4b7d78db9c091ac3baf537a69fc7f549d979f0eff9a94fda4169bd4d1d19a69c99e33c3b55490d501b39b1edae118ff6793a153261584d3a5f39f6e682e3d17c8cd1261fa72\nOutput = f735fd55ba92592c3b52b8f9c4f69aaa1cbef8fe88add095595412467f9cf4ec0b896c59eda16210e7549c8abb10cdbc21a12ec9b6b5b8fd2f10399eb6\n\nDecrypt = RSA-OAEP-9\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 93ac9f0671ec29acbb444effc1a5741351d60fdb0e393fbf754acf0de49761a14841df7772e9bc82773966a1584c4d72baea00118f83f35cca6e537cbd4d811f5583b29783d8a6d94cd31be70d6f526c10ff09c6fa7ce069795a3fcd0511fd5fcb564bcc80ea9c78f38b80012539d8a4ddf6fe81e9cddb7f50dbbbbcc7e5d86097ccf4ec49189fb8bf318be6d5a0715d516b49af191258cd32dc833ce6eb4673c03a19bbace88cc54895f636cc0c1ec89096d11ce235a265ca1764232a689ae8\nOutput = 81b906605015a63aabe42ddf11e1978912f5404c7474b26dce3ed482bf961ecc818bf420c54659\n\nDecrypt = RSA-OAEP-9\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 81ebdd95054b0c822ef9ad7693f5a87adfb4b4c4ce70df2df84ed49c04da58ba5fc20a19e1a6e8b7a3900b22796dc4e869ee6b42792d15a8eceb56c09c69914e813cea8f6931e4b8ed6f421af298d595c97f4789c7caa612c7ef360984c21b93edc5401068b5af4c78a8771b984d53b8ea8adf2f6a7d4a0ba76c75e1dd9f658f20ded4a46071d46d7791b56803d8fea7f0b0f8e41ae3f09383a6f9585fe7753eaaffd2bf94563108beecc207bbb535f5fcc705f0dde9f708c62f49a9c90371d3\nOutput = fd326429df9b890e09b54b18b8f34f1e24\n\nDecrypt = RSA-OAEP-9\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = bcc35f94cde66cb1136625d625b94432a35b22f3d2fa11a613ff0fca5bd57f87b902ccdc1cd0aebcb0715ee869d1d1fe395f6793003f5eca465059c88660d446ff5f0818552022557e38c08a67ead991262254f10682975ec56397768537f4977af6d5f6aaceb7fb25dec5937230231fd8978af49119a29f29e424ab8272b47562792d5c94f774b8829d0b0d9f1a8c9eddf37574d5fa248eefa9c5271fc5ec2579c81bdd61b410fa61fe36e424221c113addb275664c801d34ca8c6351e4a858\nOutput = f1459b5f0c92f01a0f723a2e5662484d8f8c0a20fc29dad6acd43bb5f3effdf4e1b63e07fdfe6628d0d74ca19bf2d69e4a0abf86d293925a796772f8088e\n\nDecrypt = RSA-OAEP-9\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 232afbc927fa08c2f6a27b87d4a5cb09c07dc26fae73d73a90558839f4fd66d281b87ec734bce237ba166698ed829106a7de6942cd6cdce78fed8d2e4d81428e66490d036264cef92af941d3e35055fe3981e14d29cbb9a4f67473063baec79a1179f5a17c9c1832f2838fd7d5e59bb9659d56dce8a019edef1bb3accc697cc6cc7a778f60a064c7f6f5d529c6210262e003de583e81e3167b89971fb8c0e15d44fffef89b53d8d64dd797d159b56d2b08ea5307ea12c241bd58d4ee278a1f2e\nOutput = 53e6e8c729d6f9c319dd317e74b0db8e4ccca25f3c8305746e137ac63a63ef3739e7b595abb96e8d55e54f7bd41ab433378ffb911d\n\nDecrypt = RSA-OAEP-9\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 438cc7dc08a68da249e42505f8573ba60e2c2773d5b290f4cf9dff718e842081c383e67024a0f29594ea987b9d25e4b738f285970d195abb3a8c8054e3d79d6b9c9a8327ba596f1259e27126674766907d8d582ff3a8476154929adb1e6d1235b2ccb4ec8f663ba9cc670a92bebd853c8dbf69c6436d016f61add836e94732450434207f9fd4c43dec2a12a958efa01efe2669899b5e604c255c55fb7166de5589e369597bb09168c06dd5db177e06a1740eb2d5c82faeca6d92fcee9931ba9f\nOutput = b6b28ea2198d0c1008bc64\n\nPrivateKey = RSA-OAEP-10\nType = RSA\nInput = 308204bd020100300d06092a864886f70d0101010500048204a7308204a30201000282010100ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb020301000102820100056b04216fe5f354ac77250a4b6b0c8525a85c59b0bd80c56450a22d5f438e596a333aa875e291dd43f48cb88b9d5fc0d499f9fcd1c397f9afc070cd9e398c8d19e61db7c7410a6b2675dfbf5d345b804d201add502d5ce2dfcb091ce9997bbebe57306f383e4d588103f036f7e85d1934d152a323e4a8db451d6f4a5b1b0f102cc150e02feee2b88dea4ad4c1baccb24d84072d14e1d24a6771f7408ee30564fb86d4393a34bcf0b788501d193303f13a2284b001f0f649eaf79328d4ac5c430ab4414920a9460ed1b7bc40ec653e876d09abc509ae45b525190116a0c26101848298509c1c3bf3a483e7274054e15e97075036e989f60932807b5257751e7902818100ecf5aecd1e5515fffacbd75a2816c6ebf49018cdfb4638e185d66a7396b6f8090f8018c7fd95cc34b857dc17f0cc6516bb1346ab4d582cadad7b4103352387b70338d084047c9d9539b6496204b3dd6ea442499207bec01f964287ff6336c3984658336846f56e46861881c10233d2176bf15a5e96ddc780bc868aa77d3ce76902818100bc46c464fc6ac4ca783b0eb08a3c841b772f7e9b2f28babd588ae885e1a0c61e4858a0fb25ac299990f35be85164c259ba1175cdd7192707135184992b6c29b746dd0d2cabe142835f7d148cc161524b4a09946d48b828473f1ce76b6cb6886c345c03e05f41d51b5c3a90a3f24073c7d74a4fe25d9cf21c75960f3fc386318302818100c73564571d00fb15d08a3de9957a50915d7126e9442dacf42bc82e862e5673ff6a008ed4d2e374617df89f17a160b43b7fda9cb6b6b74218609815f7d45ca263c159aa32d272d127faf4bc8ca2d77378e8aeb19b0ad7da3cb3de0ae7314980f62b6d4b0a875d1df03c1bae39ccd833ef6cd7e2d9528bf084d1f969e794e9f6c10281802658b37f6df9c1030be1db68117fa9d87e39ea2b693b7e6d3a2f70947413eec6142e18fb8dfcb6ac545d7c86a0ad48f8457170f0efb26bc48126c53efd1d16920198dc2a1107dc282db6a80cd3062360ba3fa13f70e4312ff1a6cd6b8fc4cd9c5c3db17c6d6a57212f73ae29f619327bad59b153858585ba4e28b60a62a45e490281806f38526b3925085534ef3e415a836ede8b86158a2c7cbfeccb0bd834304fec683ba8d4f479c433d43416e63269623cea100776d85aff401d3fff610ee65411ce3b1363d63a9709eede42647cea561493d54570a879c18682cd97710b96205ec31117d73b5f36223fadd6e8ba90dd7c0ee61d44e163251e20c7f66eb305117cb8\n\nDecrypt = RSA-OAEP-10\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 53ea5dc08cd260fb3b858567287fa91552c30b2febfba213f0ae87702d068d19bab07fe574523dfb42139d68c3c5afeee0bfe4cb7969cbf382b804d6e61396144e2d0e60741f8993c3014b58b9b1957a8babcd23af854f4c356fb1662aa72bfcc7e586559dc4280d160c126785a723ebeebeff71f11594440aaef87d10793a8774a239d4a04c87fe1467b9daf85208ec6c7255794a96cc29142f9a8bd418e3c1fd67344b0cd0829df3b2bec60253196293c6b34d3f75d32f213dd45c6273d505adf4cced1057cb758fc26aeefa441255ed4e64c199ee075e7f16646182fdb464739b68ab5daff0e63e9552016824f054bf4d3c8c90a97bb6b6553284eb429fcc\nOutput = 8bba6bf82a6c0f86d5f1756e97956870b08953b06b4eb205bc1694ee\n\nDecrypt = RSA-OAEP-10\nRSAPadding = OAEP\nMGF1Dig",
+    "est = SHA1\nInput = a2b1a430a9d657e2fa1c2bb5ed43ffb25c05a308fe9093c01031795f5874400110828ae58fb9b581ce9dddd3e549ae04a0985459bde6c626594e7b05dc4278b2a1465c1368408823c85e96dc66c3a30983c639664fc4569a37fe21e5a195b5776eed2df8d8d361af686e750229bbd663f161868a50615e0c337bec0ca35fec0bb19c36eb2e0bbcc0582fa1d93aacdb061063f59f2ce1ee43605e5d89eca183d2acdfe9f81011022ad3b43a3dd417dac94b4e11ea81b192966e966b182082e71964607b4f8002f36299844a11f2ae0faeac2eae70f8f4f98088acdcd0ac556e9fccc511521908fad26f04c64201450305778758b0538bf8b5bb144a828e629795\nOutput = e6ad181f053b58a904f2457510373e57\n\nDecrypt = RSA-OAEP-10\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 9886c3e6764a8b9a84e84148ebd8c3b1aa8050381a78f668714c16d9cfd2a6edc56979c535d9dee3b44b85c18be8928992371711472216d95dda98d2ee8347c9b14dffdff84aa48d25ac06f7d7e65398ac967b1ce90925f67dce049b7f812db0742997a74d44fe81dbe0e7a3feaf2e5c40af888d550ddbbe3bc20657a29543f8fc2913b9bd1a61b2ab2256ec409bbd7dc0d17717ea25c43f42ed27df8738bf4afc6766ff7aff0859555ee283920f4c8a63c4a7340cbafddc339ecdb4b0515002f96c932b5b79167af699c0ad3fccfdf0f44e85a70262bf2e18fe34b850589975e867ff969d48eabf212271546cdc05a69ecb526e52870c836f307bd798780ede\nOutput = 510a2cf60e866fa2340553c94ea39fbc256311e83e94454b4124\n\nDecrypt = RSA-OAEP-10\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 6318e9fb5c0d05e5307e1683436e903293ac4642358aaa223d7163013aba87e2dfda8e60c6860e29a1e92686163ea0b9175f329ca3b131a1edd3a77759a8b97bad6a4f8f4396f28cf6f39ca58112e48160d6e203daa5856f3aca5ffed577af499408e3dfd233e3e604dbe34a9c4c9082de65527cac6331d29dc80e0508a0fa7122e7f329f6cca5cfa34d4d1da417805457e008bec549e478ff9e12a763c477d15bbb78f5b69bd57830fc2c4ed686d79bc72a95d85f88134c6b0afe56a8ccfbc855828bb339bd17909cf1d70de3335ae07039093e606d655365de6550b872cd6de1d440ee031b61945f629ad8a353b0d40939e96a3c450d2a8d5eee9f678093c8\nOutput = bcdd190da3b7d300df9a06e22caae2a75f10c91ff667b7c16bde8b53064a2649a94045c9\n\nDecrypt = RSA-OAEP-10\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 75290872ccfd4a4505660d651f56da6daa09ca1301d890632f6a992f3d565cee464afded40ed3b5be9356714ea5aa7655f4a1366c2f17c728f6f2c5a5d1f8e28429bc4e6f8f2cff8da8dc0e0a9808e45fd09ea2fa40cb2b6ce6ffff5c0e159d11b68d90a85f7b84e103b09e682666480c657505c0929259468a314786d74eab131573cf234bf57db7d9e66cc6748192e002dc0deea930585f0831fdcd9bc33d51f79ed2ffc16bcf4d59812fcebcaa3f9069b0e445686d644c25ccf63b456ee5fa6ffe96f19cdf751fed9eaf35957754dbf4bfea5216aa1844dc507cb2d080e722eba150308c2b5ff1193620f1766ecf4481bafb943bd292877f2136ca494aba0\nOutput = a7dd6c7dc24b46f9dd5f1e91ada4c3b3df947e877232a9\n\nDecrypt = RSA-OAEP-10\nRSAPadding = OAEP\nMGF1Digest = SHA1\nInput = 2d207a73432a8fb4c03051b3f73b28a61764098dfa34c47a20995f8115aa6816679b557e82dbee584908c6e69782d7deb34dbd65af063d57fca76a5fd069492fd6068d9984d209350565a62e5c77f23038c12cb10c6634709b547c46f6b4a709bd85ca122d74465ef97762c29763e06dbc7a9e738c78bfca0102dc5e79d65b973f28240caab2e161a78b57d262457ed8195d53e3c7ae9da021883c6db7c24afdd2322eac972ad3c354c5fcef1e146c3a0290fb67adf007066e00428d2cec18ce58f9328698defef4b2eb5ec76918fde1c198cbb38b7afc67626a9aefec4322bfd90d2563481c9a221f78c8272c82d1b62ab914e1c69f6af6ef30ca5260db4a46\nOutput = eaf1a73a1b0c4609537de69cd9228bbcfb9a8ca8c6c3efaf056fe4a7f4634ed00b7c39ec6922d7b8ea2c04ebac\n\n\n# Single-shot signing tests.\n\nSignMessage = RSA-2048\nDigest = SHA256\nInput = \"Hello world\"\nOutput = 301894798b49d6ec55d32dcc74314f04230591a515781f3eb4492f5324b56046836c4bc3e25942af341e88558cb4c3814a849207575d343189147989b16e296b5138dbbc717116dc416f201dfa35943d15060493953cda1f04a13ff89845cf7fd69e1a78d5d38522a77bb234e5d0ba2ae17ada6e22fdae27a4052fdb8ac267507dfe06ed7a865e61a52b530bbbf65c7caa89739613df10ae3b0e62ff6831ee0770086aad39c329462aede9f1b29a501bc3d09e0fe4034aa5d6831d44491d508111d88a1d7ba50cee5ef7e701b3a589adc09a752a974a6805956f4a1a0582f66309a1e02e9fb6b10d2c820fe98bb2eb04f435bc8a649cc9ab6c5a4c03e83800d1\n\nVerifyMessage = RSA-2048\nDigest = SHA256\nInput = \"Hello world\"\nOutput = 301894798b49d6ec55d32dcc74314f04230591a515781f3eb4492f5324b56046836c4bc3e25942af341e88558cb4c3814a849207575d343189147989b16e296b5138dbbc717116dc416f201dfa35943d15060493953cda1f04a13ff89845cf7fd69e1a78d5d38522a77bb234e5d0ba2ae17ada6e22fdae27a4052fdb8ac267507dfe06ed7a865e61a52b530bbbf65c7caa89739613df10ae3b0e62ff6831ee0770086aad39c329462aede9f1b29a501bc3d09e0fe4034aa5d6831d44491d508111d88a1d7ba50cee5ef7e701b3a589adc09a752a974a6805956f4a1a0582f66309a1e02e9fb6b10d2c820fe98bb2eb04f435bc8a649cc9ab6c5a4c03e83800d1\n\nVerifyMessage = RSA-2048-SPKI\nDigest = SHA256\nInput = \"Hello world\"\nOutput = 301894798b49d6ec55d32dcc74314f04230591a515781f3eb4492f5324b56046836c4bc3e25942af341e88558cb4c3814a849207575d343189147989b16e296b5138dbbc717116dc416f201dfa35943d15060493953cda1f04a13ff89845cf7fd69e1a78d5d38522a77bb234e5d0ba2ae17ada6e22fdae27a4052fdb8ac267507dfe06ed7a865e61a52b530bbbf65c7caa89739613df10ae3b0e62ff6831ee0770086aad39c329462aede9f1b29a501bc3d09e0fe4034aa5d6831d44491d508111d88a1d7ba50cee5ef7e701b3a589adc09a752a974a6805956f4a1a0582f66309a1e02e9fb6b10d2c820fe98bb2eb04f435bc8a649cc9ab6c5a4c03e83800d1\n\nVerifyMessage = P-256\nDigest = SHA256\nInput = \"Hello world\"\nOutput = 304502204c66004635c267394bd6857c1e0b53b22a2bab1ca7dff9d5c1b42143858b3ea7022100ae81228510e03cd49a8863d2ebd1c05fe0c87eacd1150433132b909994cd0dbd\n\n# Digest can't be omitted in many algorithms.\nSignMessage = RSA-2048\nInput = \"Hello world\"\nError = NO_DEFAULT_DIGEST\n\nVerifyMessage = RSA-2048\nInput = \"Hello world\"\nOutput = 301894798b49d6ec55d32dcc74314f04230591a515781f3eb4492f5324b56046836c4bc3e25942af341e88558cb4c3814a849207575d343189147989b16e296b5138dbbc717116dc416f201dfa35943d15060493953cda1f04a13ff89845cf7fd69e1a78d5d38522a77bb234e5d0ba2ae17ada6e22fdae27a4052fdb8ac267507dfe06ed7a865e61a52b530bbbf65c7caa89739613df10ae3b0e62ff6831ee0770086aad39c329462aede9f1b29a501bc3d09e0fe4034aa5d6831d44491d508111d88a1d7ba50cee5ef7e701b3a589adc09a752a974a6805956f4a1a0582f66309a1e02e9fb6b10d2c820fe98bb2eb04f435bc8a649cc9ab6c5a4c03e83800d1\nError = NO_DEFAULT_DIGEST\n\n# Signing test vectors from RFC 8032.\nSignMessage = Ed25519\nInput = \"\"\nOutput = e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b\n\nSignMessage = Ed25519-2\nInput = 72\nOutput = 92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00\n\nSignMessage = Ed25519-3\nInput = af82\nOutput = 6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a\n\nSignMessage = Ed25519-4\nInput = 08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497",
+    "f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0\nOutput = 0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03\n\nSignMessage = Ed25519-5\nInput = ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f\nOutput = dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b58909351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704\n\n# Signing with public keys is not allowed.\nSignMessage = Ed25519-SPKI\nInput = \"\"\nError = NOT_A_PRIVATE_KEY\n\n# Verify test vectors from RFC 8032. Test verifying with both the public and\n# private key.\nVerifyMessage = Ed25519\nInput = \"\"\nOutput = e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b\n\nVerifyMessage = Ed25519-SPKI\nInput = \"\"\nOutput = e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b\n\nVerifyMessage = Ed25519-2\nInput = 72\nOutput = 92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00\n\nVerifyMessage = Ed25519-SPKI-2\nInput = 72\nOutput = 92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00\n\nVerifyMessage = Ed25519-3\nInput = af82\nOutput = 6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a\n\nVerifyMessage = Ed25519-SPKI-3\nInput = af82\nOutput = 6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a\n\nVerifyMessage = Ed25519-4\nInput = 08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0\nOutput = 0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03\n\nVerifyMessage = Ed25519-SPKI-4\nInput = 08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0\nOutput = 0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03\n\nVerifyMessage = Ed25519-5\nInput = ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f\nOutput = dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b58909351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704\n\nVerifyMessage = Ed25519-SPKI-5\nInput = ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f\nOutput = dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b58909351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704\n\n# Length is wrong.\nVerifyMessage = Ed25519-SPKI\nInput = \"\"\nOutput = e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a10\nError = INVALID_SIGNATURE\n\n# Message is wrong.\nVerifyMessage = Ed25519-SPKI\nInput = \"Hello world\"\nOutput = e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b\nError = INVALID_SIGNATURE\n\n# Ed25519 does not support configuring a digest.\nSignMessage = Ed25519\nInput = \"\"\nDigest = SHA256\nError = COMMAND_NOT_SUPPORTED\n\n# Ed25519 does not support signing a pre-hashed value.\nSign = Ed25519\nInput = \"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"\nError = OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE\n\nVerify = Ed25519\nInput = \"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"\nOutput = e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b\nError = OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE\n",
 };
-static const size_t kLen32 = 1834;
+static const size_t kLen32 = 122874;
 
 static const char *kData33[] = {
+    "# Test vectors from FIPS-197, Appendix C.\n\nMode = Raw\nKey = 000102030405060708090a0b0c0d0e0f\nPlaintext = 00112233445566778899aabbccddeeff\nCiphertext = 69c4e0d86a7b0430d8cdb78070b4c55a\n\nMode = Raw\nKey = 000102030405060708090a0b0c0d0e0f1011121314151617\nPlaintext = 00112233445566778899aabbccddeeff\nCiphertext = dda97ca4864cdfe06eaf70a0ec0d7191\n\nMode = Raw\nKey = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\nPlaintext = 00112233445566778899aabbccddeeff\nCiphertext = 8ea2b7ca516745bfeafc49904b496089\n\n\n# Test vectors from\n# http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf\n\nMode = KeyWrap\nKey = 000102030405060708090a0b0c0d0e0f\nPlaintext = 00112233445566778899aabbccddeeff\nCiphertext = 1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5\n\nMode = KeyWrap\nKey = 000102030405060708090a0b0c0d0e0f1011121314151617\nPlaintext = 00112233445566778899aabbccddeeff\nCiphertext = 96778b25ae6ca435f92b5b97c050aed2468ab8a17ad84e5d\n\nMode = KeyWrap\nKey = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\nPlaintext = 00112233445566778899aabbccddeeff\nCiphertext = 64e8c3f9ce0f5ba263e9777905818a2a93c8191e7d6e8ae7\n\nMode = KeyWrap\nKey = 000102030405060708090a0b0c0d0e0f1011121314151617\nPlaintext = 00112233445566778899aabbccddeeff0001020304050607\nCiphertext = 031d33264e15d33268f24ec260743edce1c6c7ddee725a936ba814915c6762d2\n\nMode = KeyWrap\nKey = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\nPlaintext = 00112233445566778899aabbccddeeff0001020304050607\nCiphertext = a8f9bc1612c68b3ff6e6f4fbe30e71e4769c8b80a32cb8958cd5d17d6b254da1\n\nMode = KeyWrap\nKey = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\nPlaintext = 00112233445566778899aabbccddeeff000102030405060708090a0b0c0d0e0f\nCiphertext = 28c9f404c4b810f4cbccb35cfb87f8263f5786e2d80ed326cbc7f0e71a99f43bfb988b9b7a02dd21\n",
+};
+static const size_t kLen33 = 1834;
+
+static const char *kData34[] = {
     "# Sum tests.\n#\n# These test vectors satisfy A + B = Sum.\n\nSum = 0\nA = 0\nB = 0\n\nSum = c590e57ee64fced3ca84d4bb013bba7d633e68b2ff4e27bf1db43f386dbfcce501f112b7fff6fb9436a576ccfccce12867becf02b91961453ea41f414764407d\nA = c590e57ee64fced3ca84d4bb013bba7d633e68b2ff4e27bf1db43f386dbfcce501f112b7fff6fb9436a576ccfccce12867becf02b91961453ea41f414764407d\nB = 0\n\nSum = -c590e57ee64fced3ca84d4bb013bba7d633e68b2ff4e27bf1db43f386dbfcce501f112b7fff6fb9436a576ccfccce12867becf02b91961453ea41f414764407d\nA = -c590e57ee64fced3ca84d4bb013bba7d633e68b2ff4e27bf1db43f386dbfcce501f112b7fff6fb9436a576ccfccce12867becf02b91961453ea41f414764407d\nB = 0\n\nSum = 0\nA = c590e57ee64fced3ca84d4bb013bba7d633e68b2ff4e27bf1db43f386dbfcce501f112b7fff6fb9436a576ccfccce12867becf02b91961453ea41f414764407d\nB = -c590e57ee64fced3ca84d4bb013bba7d633e68b2ff4e27bf1db43f386dbfcce501f112b7fff6fb9436a576ccfccce12867becf02b91961453ea41f414764407d\n\nSum = c590e57ee64fced3ca84d4bb013bba7d633e68b2ff4e27bf1db43f386dbfcce501f112b7fff6fb9436a576ccfccce12867becf02b91961453ea41f414764407d\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 23f85668bf4d0fa273d8c7f63c5fee57811062a674111e295a73a58e08dd0fd58eda1f473960559d5b96d1862164e96efded31f756df3f57c\n\nSum = c590e57ee64fceccd54e0bdc52476a756d32e794922dca0acc780d2c6af8852351102b40dfb97009f95e019a5bf38e5d127aa78bc34425edf96f763084a8b09f\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -4b5b16252ba2355e0b87f01baa721783c403607a4c1b5652c09a68e96926c8e314fa580bf0ad3f8f59bd70f14df86a4676661899b54c79a62\n\nSum = -c590e57ee64fcec882fef3ffd015a3fd9024d8f5f6d53eb537d6abdb0ff5e76a8fb08d5feed113fc9e74745d957adf32704a08339ba42efd5746c5d478e3f57b\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 908007a2f3c551c58958d1059427a0391d4d768f61cb802e4cb062c778354ea3eaa8f0dfbd14ca8203e07ae6d07269b58088a39f7608c5586\n\nSum = -c590e57ee64fceeb242f8a0893eaa0d2ccc3dc57ec40fe917cfde66618fba678ce0c8fffc566d4e8c7944d6443def8014fe8ee410a1b8dfd06cb0b436619e0dd\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -1999301bd9877fe07ca711f308b2f1bc4a704fd194ec4dbc297355d6285340d6ad7e90cb0add1770aea19737a06750c3a7a6fa0b778ca995dc\n\nSum = c590e57ee64fcef321395bba088ca0a867e1e85a1ea77478f8783e6a6cf8f3e582bff83cb2d7d9fd549fcbb40dea22ac140351007030059500bdca81413600e9\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 219639ed8afc21e052422fff0ae5583231ebca2999404b099628093e6540b1dbc20b9c495aa7229b5965b19a5fcd653b3fa0eccab567c5b5e8\n\nSum = c590e57ee64fce834a00cc6282cb0eef49eac7a8d5b51988cb49253ed85ae261c76f2327a691fc63eceab02614807048b2816cdb9b89ca66a17b6ed1abdab580\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -4e40fea1cc899fb166dbc721a6639a28be4164ef92545307ed934796afcb9401d75c18d23352471709fbd049c50740ffeebe5590fa2d959581\n\nSum = -c590e57ee64fce1a17609c61ce02f1020c6eb6e241e3fdd01546ce7247725589de32db95f36718d410f9ce9a94fecc8fb205e876fde75ce83f4d01e1bd5d818d\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = b7739ed1cd3e67cf541943326cf76b4476f767465ee53b94c57c83de417ebee5673809b3bed1c8bac2fc4bce29a4e36d6d2083fdea1c12c974\n\nSum = -c590e57ee64fd03e2d08c3d8e5110d08e3d36557d82e0e49b408337a8c9d4298802ae5f0145a9587531a70d2f8af932b8262245428b5c549817d333f2dfaeeec\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -16ca20955a9d8a64cb2be217c089edecc02a75a1ea95fef584925742c18a234974c0a16ee7991e80bd8d4106db385eafaf421ac3373548aa3eb\n\nSum = c590e57ee64fd1bcac71b5b055e5934ba15dd7f56370063369c36e57a6b753269e085d0f4d38bfb711d5579dd1d89d07f266e727b232a497d5b0d9bfbc02d8a5\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 2eb21724781497ad2f57babeea62a20c3ec5d1559867a0968d74351a337db12c17bc8d1d5446b1115b5441530870f67da4275dfd9f3e2928da4\n\nSum = c590e57ee64fc7860b0be6ce861bc2f099db7fb623912b7b0729c019a8183c669c73efe02b195483a4cd2c78244cd59678ac4d62f6887fe686a3eed37ed460ff\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -74b7ff38760864efd658bd6699915be16cc058454b78495ade8be42c9f7470ca9b7a43655e1427ab1bc35a5693dac424a6ed92d10f85a9bea02\n\nSum = -c590e57ee64fc3126776e79d9fca06233bd2ef5570a65e4521183627bdbdbc555e9118508cf63f519bc0caedbffd5b1a913ee8c3603804820a9ce54b1207bdef\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = bbf238886916ca0ba32e9def9f9c8a8e401eb95dea96ef02df9fc25a186e52fbee9ad42b76ba6ca2c381d12cddd4292c5d355341a80c7688d12\n\nSum = -c590e57ee64fe6dfd728dfbe45aee52380b5a00cf1e05e9f09ac582e2714bb589caf2ad038111c5b1b5573a45706ab1f6fd5d5a1ee7ef4a9bf186dca8a9ede12\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -180e4c29718f394424cd5b03b6bdb8911c57fcfe435cfa66d10941f870f8c5eb1e1fd251f14af03f23ccc1841f014bb42a545f476dfeb12e9311\n\nSum = c590e57ee65004b3e18a5820de4a6d25e7c3d310003e0b8716bbfd51d5f0f3e87fdf8e00599d713397255281e66ef419a9d9bb228e8f052764f5f861ccca656f\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 35e2568ae9f1d1dfaccfc211e9c0c6eec9400a0de880a94309992528d428e77772f84e21d0287fa76cc6fb880481ebc43ad20524f895f35a1a6e\n\nSum = c590e57ee64f84896a5f11f575d34b6001f27d4b4d6e7cd9485260629f8f7f1c6ca6f6115b98d776774295dde4d59cdbbceccad097a0a054b501bfb47d81e85c\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -4a4820a05c39969774f623bf6c03ebe0c56dc45bb46e8d1e6b32ee0fc3c6168d26c4d1c0ec7b81f1ea76f164ebd00b2a2a00aacf40175bee62a5\n\nSum = -c590e57ee64edf1b2b57b4cbb92d778ea6b9d9878a0374d4ea81691b09811b105bb6dbf23a57d89264f0e6c83f8d00fe00681644feed56e15fc81103ab9b7dd6\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = efb65fa7b963533d48c77ef80fc7af4bcd72222cabb6232ccf3efeffdde537ce25a8e4129b91273a8654ade9a05ba3dd73740008eec82dd4cd2b\n\nSum = -c590e57ee650e25da7b60146e014f472bfff9809aa8f519db7943f69d9ad09ee75a3427c6127cce7bd27f224b9dec03111fb066956b4903f9f9740cce1aa4ba7\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -1138c1cb69317d3aa341c9a4daeba71400f56aae62a98acff1f9f1aec88a4ef01ceac74246fcb531738de63a94fc8b3e9c5ea3fc64101083a00a6\n\nSum = c590e57ee653af8752322840ed720f628f9674c81073b58372e49ef26d4a2a9d46a0391bc170336614b27849de98709a4b321da4ddfb978e9f10df29154edb9f\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 3e0b5c732ba11e1074f0c69e48b78d724733c66368a21409c404debe97f444f4a352acbaef5f077d0e9479ce067043b30cd393f3fdf5d3bde909e\n\nSum = c590e57ee64bc13634cbd149aae35ee47bde6ea3663f74ff300cfdb2d845f902f017586c6d4f83f08c3b4f0c035055d13fc9d340b7b9ed164432aed44e8f4d7c\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -40d9b56339ce561876171a9d37aabd30fcd47dca1171e5467f14c6a9f616b04d67a4abcc8334d637731816e87e35feb10dd3f1b9e50f78ae0fd85\n\nSum = -c590e57ee6477eb692705f8da1357e71591336907a5e0a6e39715088d53b2610882765357563fd101bcf05ca545a0c718f52879fdf4f80cb9a12cf108eca60ed\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0f",
     "fcbd9704b01\nB = 8501af88f0ea16b3541e4cc9eb2bebef137d8d33cc4485772c43ed28f54a1fcc2012b2d347c8f126d7ae11eff2f00c37b4989c5be30bb4aa5ea14\n\nSum = -c590e57ee669b662e37f5abf13d00d2f0c1c9a8b99ec546361aad255f375bc2742a3487c351c5ba00efef09c77331577460a47c57125c620b643e9eaf36a146b\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -19e791587fec9007654cd8e66ab13c609d121c54fcbd84c6c7d1d7e7ec8ea4c2f65d64c5fb6e43106b8e2497b89124ce5afbcb5672ea1f19f9c96a\n\nSum = c590e57ee681dcbf1554f22c0b1ffead917dd414299cb37ce6967ffec9c333931e70358729843c8130ac95aba47fa1fa5da74000eff25eecae176f093a4effca\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 320ded8a5583fcfeb53e576bcbeac4f04d7135d9e86b2d9d154943c3b97bafb75e3e45e7a913523db81aa7af5589604d2794974e466f3d60deb4c9\n\nSum = c590e57ee5e505ae4a2e1f25a1ae9b7b4d17dd2cccc09f2416d964e55af6d0d31fe259c160f87646a72e6732d5110256b3b35425225d622b81418435c9dd8cc4\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -6ac92340d14f096abc24dad89a0c226c8ea322f5d4afebd1b7197c3ad46016112d87f4a1d51b2691b684fbfa9e627b806d6829de8f7b960f92be3d\n\nSum = -c590e57ee58c3ef1582bf7a516e36f92b60f5a587e2c8cb071d1d52ff215854e52de1519fd5204fa52292dfdc397d8d76b78005941358b63a3e6ca41b0eb09b7\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = c38fe032d37689f58750c36fa28ef6bb22b5969adc3fa13a98650107d8a4bd74d3f940f6da545ba32fae7b42d9b64761953ef1bbea358a2885414a\n\nSum = -c590e57ee80262967da4038a143f8ff2e78646108f25ff7183444ba507d76f9b05a34c8310e682c05495d0863ceff264964dbfa7c064adf6d26d2dca6e22ab13\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -1b293c4f2a4955b07d4cf9cc1d45cc155d6bd2a769636d3db29854baaec92ab9ec084850b924e2cd6286b11e7fc09071d99e3a1729c2dfe94b26012\n\nSum = c590e57ee85427f08e8c89ffebfcc05c73370ad4cb77696c2b2f3878e6f6df341d4d931b5097aba49f14ac0312e7da1c843d6fd08119822e75e6e7a8c7bcb7b0\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 204591f038d1bd0df9200064d852185922827251e8123a7ba48f4e4c296d943de71ad69561129a9ac2052c9d5ebb92fde4eb7d91615e7dcee4c6caf\n\nSum = c590e57ee051ca1a363c47a4cc016c3de7f7e17985009b545528289e9fbc9086f4b42a73826eca0c278b0d1b4ef6d74b9a0bfcb7855d40fdb201fbad1074b927\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -5fe04b754c3268a406954183dba07d5b44ea6f2b785ec328cf159c866028f63efb7342f2178753e17d0b0071445b9e91d6d8957adcf041ec8fb91da\n\nSum = -c590e57edcd6e9ef06fe33f3817ba3d0c50c8122b77615c4b8fa50c5514f113d7ba53ce057d487bcbc373c4384d07b29a527b7ef785ca609474879b42a9a4c3a\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 978e4e284013a3b8aef1c8560a5682c81d92c8253b3c40bdb5ed911df117cf71a51767e8ccc4615e1f70c290929feb12a6e244c18888617aed5fec7\n\nSum = -c590e57f0436bdceb586a093522eb1630e0fc08f8790957aba1875a42b7676f9ca936e8f6f3478d6ef5cd590bf6ded0700440dcd769496822af8015f0a6ba2b6\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -1de6eefd2a87326445c3f10ce85dd7404e415333ad6a60d2fec88caa6fdcb4b7fd0e7a9ba659533758a665b451f2572cd3c9cc2ccb27019330fb57b5\n\nSum = c590e57f1df3f004d5e49f49fa28603b26659f1fd35e0d8d7a2753591dbc12c51e6b588427dbe3faba2f0c1f2f0a2aea9ba1fcb2fe71c6ff40555058d23c8661\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 37a421334ae5311aedbd9fe500b3b5d09a0ecb466d793e87f10e2875c3b49eacb5b5e5bf712b89c5c842a397ed5046125ba6fca9e084508cf8cc3b60\n\nSum = c590e57e9a4abf4572fa7c4c9f73e9d3fd1227646fd6d15b51924bd7a5d417b01fe6b4273eaa6ece387422b81c8116f29702d7d66d2f6e8c3454807b3b7d413c\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -4c050f8c1804f1e26cf6d682289fc1eac97870ebbb1bc8f986d9d29f3ad005b0337b8f6d108f5fa14a467060174edeca359b5bc92b7c7f509df309c5\n\nSum = -c590e57e64216c306f17017ac9dd7085113e16c83168664dbb77c7ad3ddfc79b09f9ea0c474a0b497ca15e7fb258eed9666fd009f691a3b2d691c2c6b22ba3b3\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 822e62a11be86cb4428d4fd11473d28707e6dbf951364d23eece22b450bccfcb2adbf2f1cc6223d9b46e987947e1e696ac3926a2893f3d052744a74e\n\nSum = -c590e5806ab4d09773c4f94a4aac09f6ed7609eec1d0bafecb09e30f032f706e9adadc191ff9e6d7dccc821f7a8666a590e521749d24912c5a5ffeff246f7c85\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -1846501c5e8c58b1b3e4149a0c7c4209f888178b7be5bce3dd681861f40242241add3e89c93c8ffc613bedf52e2936ad3fa59c6d6fa8eff334aff3184\n\nSum = c590e58248cbf5dd61ec57994fc862ab479dc6cda51cc17356c45cef66bbfdd12f5cc421940a561581c123fb17483beb7a1cce2596fa9ca76e722a6f4621eae9\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 3627c270bd6ece96a435da25521ebdd7e6bcd7f2c4a16481e3a0e1381d4a60a4a21e457da38bda1a1b080b498cbcb1784f42fd2520ea12aa36cb19fe8\n\nSum = c590e5771a85bdb1f26c0386ce837bec4b0af5656496efdf4f134d875f066dd6d477ca8f87ffb275da07da4dd1bed4232849a526836b47f2d69f2d53b6b3e2f1\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -7cbca111f98936aa83de74469daa6f3e9d4b85267bd9ac749cda77c78863eef47ea264bc56efba80b9508b32f8608117a1f5f82628931d27822bc6810\n\nSum = -c590e571c76afad23439f904e8a80fc28dcabb6cb732e361ed3eef471be6fa755e3fe746edbfe448c1f289ffed7dfc01fe9066d780564f57f93abbca9b9a995a\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = d1ee4d3ff56c5752a23c2b09397e72de2821c5ee51f6f258a10c6efd9fc76d290846619f28710f85979498b50afc14fc922747afd669644013dd5b1a7\n\nSum = -c590e598cd5d4a59ff5d6c97c6370fb517f1d492a7776f90063b0ddd6702e37c60fc78bb12857911cea37b7263584d7dc815676de6b8880200acea154b59b08b\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -19e70d7b88745dfe68b9cc4f5ef23feb436e282d48f98cf90c3a54f92d0645bee3a05f7ad6859ff918fc90c62b19c3b0cd43edbdaca0dbea4971e9658a\n\nSum = c590e5b5829e6fceb77830fbe999a98127b50302fd0f6a86ea4aea27b846747a07e6fcf5457676e6446137d6bdd8ff4fb7ca747b650b066d65d7dc1e172488e7\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 369c4ea0fd2c78c2ccdd2ee92b020319b3c3c0283fdd9cd5568b988a2aad30431dd35078aafb5db57d571177fd0978bddac2403c180606dc523db43de6\n\nSum = c590e52a3ab5d5c458634254e2f672a322000750741e969d2f6cd12d172480ad1455300e3a0575b068b85d50b58f9737be13073188d0f03b71494bd0fd2fea16\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -54ab99f90d329c2bda29744db303b1e1fec530aba9dd4143a4158969a2466189c93820888ae04b2508b137f01af03eaf6f19f9da19ee87b3fadc4060eb\n\nSum = -c590e4880579ef7241bde94e8c7847badc705f53828751f9975f0e66371d2ddff8740b143f32e88be8e686e2bf5a3ce03d864d7699a813b1777b9239af242c7d\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = f6e0d5df5f494184e07ff2789b494189fbb6c7f04d754f066af590bc6f6242aec332f315af601cfb76a76d4a7270cb692a0922b6a3e8556d922a4c1e84\n\nSum = -c590e6dbe54098694155509e38c61d503ab7e5237d2cdfc2b87fb57e3a8420fe37fe50a0dad4f0eae3d38fad6198e4ecaeae183a12078f53d09ac8099c715242\nA = -c590e5",
     "7ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -15cfef0c997b655e26f2c5b5cfa1505fbd443dd9d7babd1a0ad0dd636aedd4796c968aef2af9ad00d53fad15d9a005c61996f3cc4fe70c9c83dc3010741\n\nSum = c590e906254d013be2021ad591e76e26706a6815b8c484b6528fec65416e1066957002713e1183f1005f565983aad7aa031e549e6fc57094ca3e4383e7fdbc15\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 3873efd326a5702aca6857cadd04ab87ec67f75426f45e1d79414c026173ab94899cbeb85b5b75bd4001ce3505754cc9dfdccfaa63f6a6d43b80e8d7114\n\nSum = c590e0e0079190d7afd80acd6326fe93cc00903318608df31ee4493d11271dac7291bd142cca0e5dd7dda59dabd460a69b7855d9c2acb5f062de76665e07cbd7\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -49edebe3df9db276361a943c1c259b1591c20eeb453edc9cb941b86cca2e824fcc3455befdd7125dcbbbaf326ac12d960c6e01e1464fcf289657b687f2a\n\nSum = -c590d9ae456d66c1b132d844eb223867ba4560b36f53c42a616cf8cc657e6d252f813847fb9fc50127227684e5c0f5cd890eceb341d21e788e42f843e9b64080\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = bd0a0e2680fd9cc95ea214887ee6b6c889bc9fb7e1cab411c04c72f7d2a2b35818f7686393a21e10bd4810691852542e7ed60f8abdcd18e0787efba0a81\n\nSum = -c5910498291472fe1d0047d5bdd9e46deb3f26000e943fce8d83d700d9ae233ab3a28849bbb346803da142db6a471e9f79cd49571f40dbc46f7b727a4bb3016a\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -1f1942c4a42c9200d9a6b16f2417c58d3cb0d544fd8780d5c22fad0038eb58ebce72498d4844f49dc082037f974ccb7b92b67c76116f0faa72ae7242b669\n\nSum = c59112d841ea109440e78563d9eefef201c81e86ae967083f8b7db80d1eaf58551d30519ca6dd79164fe69a29cf1ba22446cb2999f73292241005bf17b37528e\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 2d595b9a41c2b5e81734cd843e9bdc16353775472e3cec09c6afa53d0b35f71c4b425847d9561bfae749362a32cf961afbf8fca85ecce12f5c25a1c7078d\n\nSum = c590671f890ca06c74ac6d2c4d75aabeaaa55312e85a5e1ea9cef0e08e154e2b090eaba869e9f6e4a47ae10b9c1eb0f6ae4fb3ef12b3121d96066c6c8e592b6e\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -7e5f5d432e6516530102bef515977b0c963c50f4e42862df23f09e989c2451a80e2f083c0756a488a14dcaa8d65c000202b19017b837c9ca935f4b171f93\n\nSum = -c58ff0ae92ab03072154949a7143d45278ef77a0ba71a785d5a370e0d30a9b4b4f7e96a395d13e6afeebbd717365d471ee56ba11c472a63c0532558104bedfc5\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = f4d053a4cbca69aad9949b26ec03acc271ae7edd9ac1370aa3f059a34f040b382333dc54bfd04a17c4e7f361b2e0bffafc8ede5824195a9eaa4ad4b16b3c\n\nSum = -c5927a5fcc3b31abeca3998ad99c07626112288a6ad95b24929fed581040757fdce73881c48b02daf09986ea436a3f5ceb6833c31fa2e1691567601a26c7a6c9\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -194e0e5eb62da61a42b5bcd31470c3b603f3b318a18dd85f1d886e3928b3082307eaa5265049fa7960490dca2b80a3d167d227cd81713b596604e4d575bc8\n\nSum = c59395e94d495451e3fea153f3e4361a088004a7d5426c1b94aec44108ad6f5cecc3a80dda0cea9f51b882747258137e171bf021b4fc59f4dcf0106d4ba952fa\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 2b06a66f9858058ff3324e77975c3e2ce1b589bf329d48800af6fdbff850d920cee3667e6ec6408b5001b0b908c2b68ca398112318f9f7d1f10a1723907f9\n\nSum = c58bdb26c0fd6766f3affea389cbe7db25c06d5d56356d3d945347775bddf479ffc9e279e7d1ee88eddb239906749815ae4502fbbc6fe978a001ccdafd89cb10\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -50a582552676a974f6f8b829ed87afff17bf1e319d509785acd59d0cff5d55aecd75d8a540fb25b285ec06052ef3d000cb3a4e65ae0dcbfcf32f0dbe67ff1\n\nSum = -c581afe9b7ae86d4b7053f19649beea6cb935799a553f035f9b9a7fba6d5559e4ecdcd1637c73c8052c6cc52ee1c28d1e5aed9db7261b7356afd6e3dbc213684\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = f35952ea147fcd3fa2f15a7ced1af5a1e91b593fb521112f46cd585d894b10be8ecc13a5ec1baf63cb60678ab5e80c8a2dcc53069131ff4d3918e1d4f147d\n\nSum = -c5a19f36a65a6a8d52a53a63f99a1b957d6e376b7010ad14695d78d67b0d7c86881006188bd27bbf205c8c9c200dc8f5c08ab6b97dcd512f6cb93ed9a361ff9f\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -10b9b7c00a9bbbc7a5cc34ed2f5b3f57bc4e1c36c16acd5caf64054e5f92372d594c4119ac7d83d7590a42b94641a312390018db0286da0ce83f0dc9f1b49e\n\nSum = c5cd0e5da24b67a894402b0eee5dd586ab70e5beb0693e263a54995193663a9b770141379c1f097a49d1a889bbf0c348c6f40ed50bd7bdc11a7869c6106c6d80\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 3c28debbfb98d70940bcdfe1f3153085befc6f7719fbdf2da6848066b8504c1c4a876029f90b3f00ce263055293bf618a25834690cf36bbaa769fa36fc227f\n\nSum = c54e2c560a00226701b76cf03d5de27a8c69b38a6b85dad9f7c903d2e87f9a7d247522e72491460f6a529e5ca2aaaf690cb238b873ffb49d9fb0ecacfedd4e90\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -42b928dc4fac6a8948013ecf0cdddb994835c4cdc9676d14e510fe442e4fd2364196f04d94b82bdeb0e3fcc41cd7e9a19f7de82ecb15b7c020131eda92fc71\n\nSum = -c4bfb037f6e6e861efb090ee610c33e7568790259f747dc6e55d442aadd68c0cc93c7617f83980e8813c0fb7dd28c8aaca6ad8fdde5d2bfec9ae096faa9ef54e\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = d13546ef68e66f9b4edd40ab5e8c6ecf2a592999dac4802750d0a67ed75e42917a43bf79ec7d52c7c772a1899ebea7e3e6dda2c46d9e569622f65c2ed155b3\n\nSum = -c6aa2af8c9ae8be4aada83f66b7f31a8bce5e92c67d8938424a1405903e5502bffc4ee1e333da4bcfd0cb383b19a566372f877a8344b66dbceabc9786dd0e4f2\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -1194579e35ebd131fdb15c75f1471529733ffdd2e89513d17f32b87d73765dca50e3446c117a681b409312a4ad2cf10c4a6c10791809c866edac9ac946099f1\n\nSum = c8aff66c9bdaa49eafac0f65d3ddff223b7a5471f7400431ca3a54615d600fc4a163f8fb648bddb5fd6915db1991611805040e0f86f152c8fd3333ef70d632e4\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = 31f10edb58ad5cd24aca136c7733ecc15c86b22bdf0c1eabd8c3f9030b2257546ad3f23f265df7ab4659381b2c9d9c556b2576ee42688739d6234239765e7e3\n\nSum = be1b6eb768e2cef388eebe31f9b21e51b38b351cc8175eba06d49eef04c2936f32167174dcb82297fd4180d0afb5da2c455d158c7a5bf01bdef8c295a4f20390\nA = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -77576c77d6cffde0210affd12b8a2047226b4327137e38d05d975e227eb56e028a04862956ddba34bc20188b711ad2668f4a114286eda3980d83d36347e4771\n\nSum = -ba32fca1d5cc5f31ecaf5407f376d3aef9f4abc04fd4c6893721d3e50e9141abf356eb2ff6f7a4f9b42983148670d2918e1dff7aa7ae33a6e9dadcb708b4f9dc\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = b5de8dd10836f9f9e501a2718f3eca72bbd3d8ee97a7bbdd58c40ec1e1ca8a3675fcea77b2e594194d9ff44e056b4c12033b725fb1c96ae75f62314d0bb5125\n\nSum = -e388afbf17c495f86aa7298a45f848eb57e5baaee42b1f7de8c2311bfbb8f74549712c05fd3bd11ab8874fb55abb22a37ba3512e733ecd5c472842e8e6f7b179\nA = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01\nB = -1df7ca403174c726dfa7bb5b398d88953233d15faadbdd36dc141c",
@@ -2518,9 +2538,9 @@
     "3ae461\nE = 1a\n\nExp = a0ea5f6a4de49beb8fb7f0dab280d6a32c5a3814c9a5153a7944cec0a9028497846a8a89044348721a0bb5f0c3ded3e980574ea321b0cdb0ead4f4e93841ea7478a7f15d9729b646a8165813a0750e8124f5465dda9b105e1bbeff18fd09c09a2e26610d9176d253b877c3a8908a6be521cbe1e472a7a1b7820e4e890f8f28aacd34609c686e76e15b01bd9324a71290812724ea564d11c874a6765b262c3e57d479da0287a76026a1e8fe53da0b02405da1d379eaa30fc65f\nA = fccec0f6df\nE = 25\n\n\n# ModSqrt tests.\n#\n# These test vectors satisfy ModSqrt * ModSqrt = A (mod P) with P a prime.\n# ModSqrt is in [0, (P-1)/2].\n\nModSqrt = 1\nA = 1\nP = 2\n\nModSqrt = 1\nA = 1\nP = 2\n\nModSqrt = 1\nA = 1\nP = 2\n\nModSqrt = 1\nA = -1\nP = 2\n\nModSqrt = 1\nA = -1\nP = 2\n\nModSqrt = 0\nA = 0\nP = 3\n\nModSqrt = 0\nA = -3\nP = 3\n\nModSqrt = 0\nA = -3\nP = 3\n\nModSqrt = 0\nA = 0\nP = 3\n\nModSqrt = 0\nA = 0\nP = 3\n\nModSqrt = 0\nA = 0\nP = 5\n\nModSqrt = 1\nA = -4\nP = 5\n\nModSqrt = 0\nA = -5\nP = 5\n\nModSqrt = 2\nA = 4\nP = 5\n\nModSqrt = 0\nA = -5\nP = 5\n\nModSqrt = 3\nA = -5\nP = 7\n\nModSqrt = 0\nA = 0\nP = 7\n\nModSqrt = 0\nA = 0\nP = 7\n\nModSqrt = 2\nA = 4\nP = 7\n\nModSqrt = 3\nA = -5\nP = 7\n\nModSqrt = 4\nA = 10\nP = b\n\nModSqrt = 0\nA = 0\nP = b\n\nModSqrt = 3\nA = -2\nP = b\n\nModSqrt = 3\nA = -2\nP = b\n\nModSqrt = 2\nA = 4\nP = b\n\nModSqrt = 2\nA = 1e\nP = d\n\nModSqrt = 2\nA = 1e\nP = d\n\nModSqrt = 0\nA = -d\nP = d\n\nModSqrt = 0\nA = -d\nP = d\n\nModSqrt = 3\nA = 9\nP = d\n\nModSqrt = 8\nA = d\nP = 11\n\nModSqrt = 6\nA = df\nP = 11\n\nModSqrt = 4\nA = 10\nP = 11\n\nModSqrt = 5\nA = 90\nP = 11\n\nModSqrt = 3\nA = 80\nP = 11\n\nModSqrt = 9\nA = -e\nP = 13\n\nModSqrt = 7\nA = 7d\nP = 13\n\nModSqrt = 6\nA = 37\nP = 13\n\nModSqrt = 1\nA = 1\nP = 13\n\nModSqrt = 8\nA = 1a\nP = 13\n\nModSqrt = 54d4cf0fafe265056a29016778cea6b712bc66a132fb5e6b6865e9b49e4c97ec\nA = 599c10484b22d0b5a115268c7538ca99b3253a311a4ab1ca11c3665b0bec393a1167d1ad94fb84cb2c7ad7e2c933e8f613bdd08fe1f1aa4a9b0b9de0c8a7c9d4\nP = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1\n\nModSqrt = 38a7365a15365e911286c1be2a7afe76ef390234d76269e04dee17313f6ea54d\nA = 1c4aabb4d8369710131c664ecf2849e963c1bc31d66e0b939bacf99a870c71f24ed71bdddcf566f3908271fee43fc1ebb51eac7e3153efae641b49d2e796a12a\nP = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1\n\nModSqrt = 35ab18a560dece04725667f640ca61d1d59f14d191f94c79f58531acd097d444\nA = 685168ae855d60eba220d803f5296459b30a289580668db9ed51bca51cc2d453a937e13819ae34f7a9a143ac96d17420c53919167e46279b562b550be1cd9abc\nP = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1\n\nModSqrt = 288370029e87024175e5bec0eab0929179f42e16995e7f6194eefc61061e54f4\nA = 2a14ab77c045bdc48220ba9c463e1a4b4049cb01edb53be0937767eb2ec19b7d719855052281250a36a0b76d9a5d967d0756e1ded7a052f7056191ad66bcfc9\nP = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1\n\nModSqrt = 32255cf01dc943577ec2bcb221b98491d7a1130d046d6c68e95fedff643ce3a4\nA = e26f6dd46a513a1dd3fb14b71be1d4c9e9d79eda1cde10ea4d1eb8abfd4d5857572205e247184dd0cbefa37b5c0bf680ba2bd28c5741f725cfe2aae37419baf\nP = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1\n\nModSqrt = 5172345e801ada63fbc4782e32583cc3b4fea88b9e6dfd542f3542f8538ade66\nA = 40dafa8342b302bb04b1f3ddb3b9015a8fc1b597857c115b40631c7be9e22de89358fca23b331596ee5ff304dad7811e6d8e8822f7aa533c9e7c882634ea550\nP = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3\n\nModSqrt = 4dcf63c423bf0e39aca2293d57f6792d023db649d6719fe936446904b9f7e60d\nA = 5bcdb514bbe84261e169203e8017909b60c9bb330400c766ee01b0189378e70e61867a164a12643ddc9e94b61e09e5b158cbe85be228a3cc48f95a552958b8f2\nP = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3\n\nModSqrt = cf77c5c2d12a500b75cbfb1f3e66ee75d886b9365cf4f8b4d1bd18a6be0f387\nA = 4652ddc2ea7b460d8ec3c9059b8f9b5dae6cac55b51f2ad86fcb336b25235737965cc515e2ff0b54835015b7ebeeda6fadd986471d8cb424d309fc353d1e269\nP = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3\n\nModSqrt = 1e0549e4c5a26023e9d24fd8c67419960746f82b1ecd113bdac66f570a475d87\nA = 5f4a6d450ab1390d96ab1deaa0ba18f897cb63daf0c9e1ef6c08e804c26b5e842f6c08f13db5d4a6e88f07af2a3cb04fa06fc3e59c410b9356f025ed81acc74\nP = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3\n\nModSqrt = 144481a781d831c1ca046ca9e322d79ad4d2c6dd9f780bea9d1ced9cd20b7b23\nA = 4c254fabca441017132b9eacd4ca40a336db3e5c09715773fa07af095989a91cc968ff07a9ff56ed06b0ce0c5269f7b2ab68564ecab9f4467a7e96b6cc6b21b7\nP = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3\n\nModSqrt = 216fecc7667f488a3d2d102a38b46b4860ab858300b8638af4f34e1103fd73ba\nA = 17878f8048227573a9d70f53c0e76ff13fe9f56e9c984c92514d3d13dec23c816661f0618d21371b80dfd885cb59551bdf80046f65f22ea9b89c78645a6e455a\nP = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95\n\nModSqrt = 458e5e789ccd2417174f7e30bb31914b9656bd8cf2b9f5a9752a8737a67707bc\nA = 5c7d39a4bb04e69201aa519f80ee7e62ea14ca55e13656d1da3f45367e2fb2d061aa2940708d02ac67d35cd2ccf54a1bf95bcbc759779e692cfdcbb3aa1a05b\nP = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95\n\nModSqrt = 543125a16c2bb8b8f8a2c39c497e5224ec77533602d7dbe24002e32dcbd2ef1a\nA = 3413afae333b2ad9ff45c7f3c7e5934b3127e8b1a55225958ee6ccf42423e81559bf070ad3f3353b78c0ffd41475af49f59d268ef78bdae879f5155e8d1cc07\nP = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95\n\nModSqrt = 10e16859c67bdb2eaab52a7c847dbf37162eda258a9f6262ebacfe4cbbbc1080\nA = 21ce7905894faf220bdf4a82a2d855994ca2dc9feaecaa53c7f146e1f49934215695e9bb46ba370b7005a90c399674caa8969eb442e7914d90f749774d7fd194\nP = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95\n\nModSqrt = 32a00586adc6f6cc2b1a04e1be0ab569fde235e1436c38b6af92bc5ebd60bc1c\nA = 350da4fd8cf03c12f7dd6ac6d3ab801a3413964083e374662aaf878d6838b97d4feb9e52cd307a25b113e101661a865463ee2480c626aa4e2ec437d72e7bae4c\nP = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95\n\nModSqrt = 971f75bc7afa8b4b50f1d4b05e52deac7d4836a08d30546f29649bf1ca6a247\nA = 655ed4c5d8d0afb4f9360372ee1ef1303898d2423e585108a3303faedb55064d2ef25666ed4c4d71fe6063fea1f3142b435714b0e30b339dd791d347c884654\nP = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7\n\nModSqrt = 48fa882b7cb6a29de9e3769f72eb67f1efd4d2af56f0c7e410c610efcbce2065\nA = 14f3503f33b243800eac1defaab33e04c01e80163fb3efd03860970cc016832431ca4fc6d1b760f4f40166b0b8b3c40dbebc81460cc10890172243770338f090\nP = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7\n\nModSqrt = 236fd7e397ea7f8bc2a288eb7236ca41936fa702b7dccca56c8852e147511f7d\nA = 1bbd0980feac854782813bcde4da85e8a054549a1b515e065da4236528035e756882e29e762cf60453e375cca9dc6ff637f9558bf86646e3b928f68f82af7efe\nP = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7\n\nModSqrt = 693f0cbe8c81b0afde0cd2f83e53795dcae6b0cc4ba930ab5c752400d787f14\nA = 7b20f9664b23907e152ab8c9a907f72e8670c1c38ab4cd1411ea7c2159c09aa131afe068929b8e6ad1409b74c04975180d1cd0a9fa74e923c3fd451e8da2c34\nP = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7\n\nModSqrt = 4a086c50b0bad576501ddb6280743b2c9d247841eb7f14d90561432ff7dca6f0\nA = 4367431ec0cd0d7626538b93a090c30fe0c97c18ca03b97ddae304b619112b5b4d02bf0f041fa3fd673f9ef2ceb07eb2079d11c56dd903b1a87e8252a97b8079\nP = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7\n\nModSqrt = 18f8433fa468d8065157708f1f1e53b8e31d39c6011fbc2bad93de1b5548e19c\nA = 739c032bb4139c199c40f548d37234298772e4ccb9d3ba28412b60ad23b4c465b0787e2382f1c5a4a87af2d20eb978b7dcbe73f2112249477d15c8a85e54a79\nP = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659\n\nModSqrt = 49e3c8eef5e067cabd51a7c01384ce05ab8f4342f655559d8a689eb7b20e0106\nA = 18400c2cc3e06b99b4e39c77b9af5ff0e9c683f1708321afa4cd5b6988d13b36b1d9eb4379b7902d9ceb40c03f814b2b6a01b90509bbb4532f13ab1571c4d04a\nP = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659\n\nModSqrt = 35548c530745f440329325cc8a5fbd90c16a7f0788879a4869bc4d4f73acda0e\nA = 181a3c5ab02566e7166c4d6d2f2bd4a8ecc25991a98d270bde80cf4332766a7068b14240bf5f5dcd45e90ef252596da3eb05b11d68b2063f7b3a825742593ca9\nP = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659\n\nModSqrt = 1ab7046e6af061ade5f9719008fa4d989007e2a579a134a5b9f19ec410984096\nA = 1008a03e211fab0d45856377079bc96b0776c2d4c0175661f3493246cea2ab0a02a706c85314fb707ad9906bedb2cfd577d62092ae08ff21d7b949373ea954c7\nP = adcd56924f73836ebe4dccfe",
     "006ad3b1e5076562cd11b161642cab7af2284659\n\nModSqrt = 2be9e3e7515960d90f115b89f60dedc173a73ce163b4036e85b7b6a76fd90852\nA = 392053a9f0100540a8e1a0c353e922068a84dad3a4a8e8962fbc0bee2b6a06e20d08ade16eb1409a16acfcac3db5c43c421505e07035ca308b15c4a6db0864c0\nP = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659\n\nModSqrt = 5b301bb93bdcf050183107e36258b53b4805918114ea1c2227b0911d5b4dc077\nA = 55e55e5f94dc3d7aabc921f6469d85fa2e1e92a87347c57afad5872306ae69f9fb99297d1e3e793dd9e8632244208154de5da7114fd876383bf1422f7ece024\nP = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb\n\nModSqrt = 2df9609e2f5a5156c3260461b2ee52eacdef00bd8b091479813143a6c5283f71\nA = 2099325b7f12fe77353ddf3f2b2c5ef77b49671b150af954cf84e9675e3ecde3e057084641a633d19533b4712ab49924c8b5c31d591abcc88291f51253fa2a7\nP = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb\n\nModSqrt = dfab751710e9008e25e422d1199d6fbec4dc7fba35b4da9d225a746eb4126a0\nA = c006af53d4737fb293584df6ffe2e4cb3fd8dc77fb7c1f13b97bb9c249e3ee5fb9feff7488265b3093906c08a4946f142ac7b491937d24bfba6413366ce371d\nP = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb\n\nModSqrt = 26bc030008d6c60a09fb0e16093a649fcb40c6c21a8e2da2353ba4b07c4f85d5\nA = 1eaabcfad2ed349ac9356e6f4da0b301266ddde811cb0f817aba8f5c10fb8b8ba9d0ef2dd386b668f16eac296118fdb8cb7afe1b865648c81c2fa3cf21f2711b\nP = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb\n\nModSqrt = 35051b1482ec2578f3dc0000a422cb5111e43c37f1ac20b1844d3de2128c4556\nA = 315ff9de178681116f2a5fa78eebf4818e1d680435eacdfaf9d0e5c4fc01fc034b352c82fd52c81ca30d68864952dacc99d08269c9dd7ca99ccf22da98c3840\nP = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb\n\nModSqrt = a5474252885cacf004c460a7793ff0b0a2187bb1a9ed700ae3470199faef71f\nA = 19856fc1351c4b02abf573bb2fc6ff92355fa369d62bb8f2260fa772fb1693f509a56cad661930abcac049dd70f4b16bed4a4c172e73e772504c9990ce7f92f\nP = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d\n\nModSqrt = 12daf4722387ecf47de1b0b6b110a062dc5ea2685bc9dbde66b8d15622985029\nA = fb8479787069116abc42abfd7dc0c24d2ad04fe0c04b42a6dff714af715d17e0fd77855f950f264542b06d48e8818de813ddb7975798b7debefcdaa5ff86beb\nP = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d\n\nModSqrt = 397996ed5c0ac6ad32e43c337e9de421b87774cc162bf7ac7bbedf4a9029255e\nA = 5aa04353321bd2de92481be740357f979da464b53aa39111fdbb734cf7af6b3857d1baa08d3a126a3dd34a2fbae2bf2b84e900686c1d31505b390185acef5fe5\nP = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d\n\nModSqrt = 2cf4b844a54ba359dc592ef1b49f43fcfeae84d1087edfefdd0b9174b43c0a3c\nA = 365a8650510bcfd8fa87432f167cf487234c215857403b9270b5eebeafa48cd6da47fd60dc311b94d1d72baad0447c31f0b212d755f46c256e16e5e015e6546e\nP = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d\n\nModSqrt = 9277c73043ff767c3fa606f0cd66b9d854a600c8c18287f191ce277758c3f31\nA = 62cec3901626d03e8df66299a87c54b1f7a55cafc99f0b6bba1b5d51a3d2b7d2171c9135a9d8a5346d436e0136b12e515e703e3cd84ecfe154eb94c6772a6d72\nP = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d\n\nModSqrt = 4189e5a90c1b1abdc1c7c05b3587e6f362e06f927b6cf5f0d271aab3d6f90765\nA = 336b8d0f9dac842c696bc020f49c6aa023842c16f2052eb02f17959006554ca0012042c80c72590f21c6bf5a3714c9cb552aa69730e33db93a56a909b273f39\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\nModSqrt = 36ccd38cb5a6bd8a73bca55936a2227c503664422c2296faf7e2b1c6a375a43a\nA = fecfd60a376befbe48d2c4f6d070d716d2f403cd5daefbce62b720df44deb605162c8f20f49fd7ec30d4f8e70d803d45b3a44b5d912baa3410d991165d7c507\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\nModSqrt = 198fc8569be172dc9b71023ed3d42d2ba94bae4099643f6517ab03f540527fdb\nA = 65bebdb00a96fc814ec44b81f98b59fba3c30203928fa5214c51e0a97091645280c947b005847f239758482b9bfc45b066fde340d1fe32fc9c1bf02e1b2d0ec\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\nModSqrt = 21b7f74c30ded681d6138cf8e6fd798f32a049e94138e982f1845df3dc9e686f\nA = 9a30b791c1ba4f394b4e3dcd5837e474237f4fe8987b255c098a47b2c14c598ec69d2beae444dd4fe9c4ede8173d2b187677cc706a3c28f3b81627d8a5fb6fd\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\nModSqrt = a1d52989f12f204d3d2167d9b1e6c8a6174c0c786a979a5952383b7b8bd186\nA = 2eee37cf06228a387788188e650bc6d8a2ff402931443f69156a29155eca07dcb45f3aac238d92943c0c25c896098716baa433f25bd696a142f5a69d5d937e81\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\n\n# NotModSquare tests.\n#\n# These test vectors are such that NotModSquare is not a square modulo P.\n\nNotModSquare = 03\nP = 07\n\nNotModSquare = 05\nP = 07\n\nNotModSquare = 06\nP = 07\n\nNotModSquare = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951e\nP = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f\n\n\n# ModInv tests.\n#\n# These test vectors satisfy ModInv * A = 1 (mod M) and 0 <= ModInv < M.\n\nModInv = 00\nA = 00\nM = 01\n\nModInv = 00\nA = 01\nM = 01\n\nModInv = 00\nA = 02\nM = 01\n\nModInv = 00\nA = 03\nM = 01\n",
 };
-static const size_t kLen33 = 832395;
+static const size_t kLen34 = 832395;
 
-static const char *kData34[] = {
+static const char *kData35[] = {
     "# Tests from NIST CAVP 186-4 ECDSA2VS Test Vectors, Signature Generation Test\n# http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip\n#\n# NIST's files provide message and digest pairs. Since this is a low-level test,\n# the digests have been extracted. P-521 test vectors were fixed to have the\n# right number of leading zeros.\n\nCurve = P-224\nPrivate = 16797b5c0c7ed5461e2ff1b88e6eafa03c0f46bf072000dfc830d615\nX = 605495756e6e88f1d07ae5f98787af9b4da8a641d1a9492a12174eab\nY = f5cc733b17decc806ef1df861a42505d0af9ef7c3df3959b8dfc6669\nDigest = 07eb2a50bf70eee87467600614a490e7600437d077ec651a27e65e67\nK = d9a5a7328117f48b4b8dd8c17dae722e756b3ff64bd29a527137eec0\nR = 2fc2cff8cdd4866b1d74e45b07d333af46b7af0888049d0fdbc7b0d6\nS = 8d9cc4c8ea93e0fd9d6431b9a1fd99b88f281793396321b11dac41eb\n\nCurve = P-224\nPrivate = cf020a1ff36c28511191482ed1e5259c60d383606c581948c3fbe2c5\nX = fa21f85b99d3dc18c6d53351fbcb1e2d029c00fa7d1663a3dd94695e\nY = e9e79578f8988b168edff1a8b34a5ed9598cc20acd1f0aed36715d88\nDigest = bde0fbb390fb05d0b75df5bd0d0a4ea29516125f19830e3b0c93b641\nK = c780d047454824af98677cf310117e5f9e99627d02414f136aed8e83\nR = 45145f06b566ec9fd0fee1b6c6551a4535c7a3bbfc0fede45f4f5038\nS = 7302dff12545b069cf27df49b26e4781270585463656f2834917c3ca\n\nCurve = P-224\nPrivate = dde6f173fa9f307d206ce46b4f02851ebce9638a989330249fd30b73\nX = fc21a99b060afb0d9dbf3250ea3c4da10be94ce627a65874d8e4a630\nY = e8373ab7190890326aac4aacca3eba89e15d1086a05434dd033fd3f3\nDigest = c2c03fe07e10538f6a38d5831b5dda9ce7478b3ed31323d60617dc95\nK = 6629366a156840477df4875cfba4f8faa809e394893e1f5525326d07\nR = 41f8e2b1ae5add7c24da8725a067585a3ad6d5a9ed9580beb226f23a\nS = a5d71bff02dce997305dd337128046f36714398f4ef6647599712fae\n\nCurve = P-224\nPrivate = aeee9071248f077590ac647794b678ad371f8e0f1e14e9fbff49671e\nX = fad0a34991bbf89982ad9cf89337b4bd2565f84d5bdd004289fc1cc3\nY = 5d8b6764f28c8163a12855a5c266efeb9388df4994b85a8b4f1bd3bc\nDigest = 5d52747226f37a5afcd94d1b95867c0111bcb34402dad12bee76c1b7\nK = 1d35d027cd5a569e25c5768c48ed0c2b127c0f99cb4e52ea094fe689\nR = 2258184ef9f0fa698735379972ce9adf034af76017668bfcdab978de\nS = 866fb8e505dea6c909c2c9143ec869d1bac2282cf12366130ff2146c\n\nCurve = P-224\nPrivate = 29c204b2954e1406a015020f9d6b3d7c00658298feb2d17440b2c1a4\nX = 0e0fc15e775a75d45f872e5021b554cc0579da19125e1a49299c7630\nY = cb64fe462d025ae2a1394746bdbf8251f7ca5a1d6bb13e0edf6b7b09\nDigest = a1ab56bd011b7e6c7e066f25333d08cf81ac0d9c1abfa09f004ab52f\nK = 39547c10bb947d69f6c3af701f2528e011a1e80a6d04cc5a37466c02\nR = 86622c376d326cdf679bcabf8eb034bf49f0c188f3fc3afd0006325d\nS = 26613d3b33c70e635d7a998f254a5b15d2a3642bf321e8cff08f1e84\n\nCurve = P-224\nPrivate = 8986a97b24be042a1547642f19678de4e281a68f1e794e343dabb131\nX = 2c070e68e8478341938f3d5026a1fe01e778cdffbebbdd7a4cd29209\nY = cde21c9c7c6590ba300715a7adac278385a5175b6b4ea749c4b6a681\nDigest = 8ef4d8a368fad480bac518d625e97206adcafa87c52aef3d179cbfa9\nK = 509712f9c0f3370f6a09154159975945f0107dd1cee7327c68eaa90b\nR = 57afda5139b180de96373c3d649700682e37efd56ae182335f081013\nS = eb6cd58650cfb26dfdf21de32fa17464a6efc46830eedc16977342e6\n\nCurve = P-224\nPrivate = d9aa95e14cb34980cfddadddfa92bde1310acaff249f73ff5b09a974\nX = 3a0d4b8e5fad1ea1abb8d3fb742cd45cd0b76d136e5bbb33206ad120\nY = c90ac83276b2fa3757b0f226cd7360a313bc96fd8329c76a7306cc7d\nDigest = 28fabbac167f3d6a20c2f5a4bcee527c96be04bdd2c596f09d8fbab7\nK = 1f1739af68a3cee7c5f09e9e09d6485d9cd64cc4085bc2bc89795aaf\nR = 09bbdd003532d025d7c3204c00747cd52ecdfbc7ce3dde8ffbea23e1\nS = 1e745e80948779a5cc8dc5cb193beebb550ec9c2647f4948bf58ba7d\n\nCurve = P-224\nPrivate = 380fb6154ad3d2e755a17df1f047f84712d4ec9e47d34d4054ea29a8\nX = 4772c27cca3348b1801ae87b01cb564c8cf9b81c23cc74468a907927\nY = de9d253935b09617a1655c42d385bf48504e06fa386f5fa533a21dcb\nDigest = 50dd74b5af40978e809cee3eb41195402ebb5056e4437f753f9a9d0d\nK = 14dbdffa326ba2f3d64f79ff966d9ee6c1aba0d51e9a8e59f5686dc1\nR = ff6d52a09ca4c3b82da0440864d6717e1be0b50b6dcf5e1d74c0ff56\nS = 09490be77bc834c1efaa23410dcbf800e6fae40d62a737214c5a4418\n\nCurve = P-224\nPrivate = 6b98ec50d6b7f7ebc3a2183ff9388f75e924243827ddded8721186e2\nX = 1f249911b125348e6e0a473479105cc4b8cfb4fa32d897810fc69ffe\nY = a17db03b9877d1b6328329061ea67aec5a38a884362e9e5b7d7642dc\nDigest = 9fee01807ab6c43a794abf6dcd6118915252ca7d3a31a1ff96b88a8d\nK = ab3a41fedc77d1f96f3103cc7dce215bf45054a755cf101735fef503\nR = 70ccc0824542e296d17a79320d422f1edcf9253840dafe4427033f40\nS = e3823699c355b61ab1894be3371765fae2b720405a7ce5e790ca8c00\n\nCurve = P-224\nPrivate = 8dda0ef4170bf73077d685e7709f6f747ced08eb4cde98ef06ab7bd7\nX = 7df67b960ee7a2cb62b22932457360ab1e046c1ec84b91ae65642003\nY = c764ca9fc1b0cc2233fa57bdcfedaab0131fb7b5f557d6ca57f4afe0\nDigest = c349032f84384b913bd5d19b9211ddce221d66a45e8a051878254117\nK = 9ef6ebd178a76402968bc8ec8b257174a04fb5e2d65c1ab34ab039b9\nR = eef9e8428105704133e0f19636c89e570485e577786df2b09f99602a\nS = 8c01f0162891e4b9536243cb86a6e5c177323cca09777366caf2693c\n\nCurve = P-224\nPrivate = 3dbe18cd88fa49febfcb60f0369a67b2379a466d906ac46a8b8d522b\nX = b10150fd797eb870d377f1dbfa197f7d0f0ad29965af573ec13cc42a\nY = 17b63ccefbe27fb2a1139e5757b1082aeaa564f478c23a8f631eed5c\nDigest = 63fe0d82cf5edf972e97316666a0914432e420f80b4f78ceb92afd1d\nK = 385803b262ee2ee875838b3a645a745d2e199ae112ef73a25d68d15f\nR = 1d293b697f297af77872582eb7f543dc250ec79ad453300d264a3b70\nS = 517a91b89c4859fcc10834242e710c5f0fed90ac938aa5ccdb7c66de\n\nCurve = P-224\nPrivate = c906b667f38c5135ea96c95722c713dbd125d61156a546f49ddaadc6\nX = 3c9b4ef1748a1925578658d3af51995b989ad760790157b25fe09826\nY = 55648f4ff4edfb899e9a13bd8d20f5c24b35dc6a6a4e42ed5983b4a0\nDigest = 9b44ee16e576c50c0b6b37ac1437bf8f013a745615012451e54a12f2\nK = b04d78d8ac40fefadb99f389a06d93f6b5b72198c1be02dbff6195f0\nR = 4bdd3c84647bad93dcaffd1b54eb87fc61a5704b19d7e6d756d11ad0\nS = fdd81e5dca54158514f44ba2330271eff4c618330328451e2d93b9fb\n\nCurve = P-224\nPrivate = 3456745fbd51eac9b8095cd687b112f93d1b58352dbe02c66bb9b0cc\nX = f0acdfbc75a748a4a0ac55281754b5c4a364b7d61c5390b334daae10\nY = 86587a6768f235bf523fbfc6e062c7401ac2b0242cfe4e5fb34f4057\nDigest = 3c89c15dee194b3223e7b53a8a5845d4873a12a2f1581d5413359828\nK = 854b20c61bcdf7a89959dbf0985880bb14b628f01c65ef4f6446f1c1\nR = a2601fbb9fe89f39814735febb349143baa934170ffb91c6448a7823\nS = bf90f9305616020a0e34ef30803fc15fa97dffc0948452bbf6cb5f66\n\nCurve = P-224\nPrivate = 2c522af64baaca7b7a08044312f5e265ec6e09b2272f462cc705e4c3\nX = 5fad3c047074b5de1960247d0cc216b4e3fb7f3b9cd960575c8479fc\nY = e4fc9c7f05ff0b040eb171fdd2a1dfe2572c564c2003a08c3179a422\nDigest = 2b7faf36fdf0e393ddeb9fc875dd99f670e3d538fd0462395ea06c8f\nK = 9267763383f8db55eed5b1ca8f4937dc2e0ca6175066dc3d4a4586af\nR = 422e2e9fe535eb62f11f5f8ce87cf2e9ec65e61c06737cf6a0019ae6\nS = 116cfcf0965b7bc63aecade71d189d7e98a0434b124f2afbe3ccf0a9\n\nCurve = P-224\nPrivate = 3eff7d07edda14e8beba397accfee060dbe2a41587a703bbe0a0b912\nX = 6dd84f4d66f362844e41a7913c40b4aad5fa9ba56bb44c2d2ed9efac\nY = 15f65ebcdf2fd9f8035385a330bdabec0f1cd9cc7bc31d2fadbe7cda\nDigest = 5b24b6157c0d1edf3a40c22a0745d23bdb59379e5e5e776ed040288d\nK = 7bb48839d7717bab1fdde89bf4f7b4509d1c2c12510925e13655dead\nR = 127051d85326049115f307af2bc426f6c2d08f4774a0b496fb6982b1\nS = 6857e84418c1d1179333b4e5307e92abade0b74f7521ad78044bf597\n\nCurve = P-224\nPrivate = 888fc992893bdd8aa02c80768832605d020b81ae0b25474154ec89aa\nX = 4c741e4d20103670b7161ae72271082155838418084335338ac38fa4\nY = db7919151ac28587b72bad7ab180ec8e95ab9e2c8d81d9b9d7e2e383\nDigest = 00c6fc53c1986d19a8a8b580ee553dc1240745d760647d1c0adf442c133c7f56\nK = 06f7a56007825433c4c61153df1a135eee2f38ec687b492ed40d9c90\nR = 0909c9b9cae8d2790e29db6afdb45c04f5b072c4c20410c7dc9b6772\nS = 298f4fcae1fe271da1e0345d11d07a1fca43f58af4c113b909eedea0\n\nCurve = P-224\nPrivate = 5b5a3e186e7d5b9b0fbdfc74a05e0a3d85dc4be4c87269190c839972\nX = 897089f4ef05b943eeac06589f0e09ccc571a6add3eb1610a2fc830f\nY = 62ba3f6b3e6f0f062058b93e6f25b6041246c5be13584a41cae7e244\nDigest = fb5dd3b8d280fe7c4838f01b2a5c28493ed3084f46b40642600ba39e43fbff7b\nK = 5b6f7eca2bcc5899fce41b8169d48cd57cf0c4a1b66a30a150072676\nR = f12c9985d454ffbc899ebbbb6cf43e3debcac7f19029f8f2f35cce31\nS = 12fcb848adbd8b1b4c72b2b54a04d936e4a5f480ae2a3ea2e3c1baae\n\nCurve = P-224\nPrivate = f60b3a4d4e31c7005a3d2d0f91cb096d016a8ddb5ab10ecb2a549170\nX = 40a4ab1e6a9f84b4dedb81795e6a7124d1cfdfd",
     "7ec64c5d4b9e32666\nY = 83aa32a3c2fc068e62626f2dafce5d7f050e826e5c145cd2d13d1b27\nDigest = f4083aebe08c9bdb8c08ff844ffc207f80fa4406fb73bdbc1c6020f71281bdae\nK = c31150420dfb38ba8347e29add189ec3e38c14b0c541497fb90bf395\nR = bf6c6daa89b21211ea2c9f45192d91603378d46b1a5057962dafaf12\nS = cb6b237950e0f0369323055cd1f643528c7a64616f75b11c4ddd63c7\n\nCurve = P-224\nPrivate = c8fc474d3b1cba5981348de5aef0839e376f9f18e7588f1eed7c8c85\nX = 66f49457ed15f67ed4042195856f052fe774077f61cebcb9efddc365\nY = 3a6e3f3423eec7308a69eb1b0416d67cc3b84d24f251d7cbdb45c079\nDigest = cb017b280093879c4b114b52ea670f14e97b661074abccc8539a23280fe136b4\nK = 5e5405ae9ab6164bb476c1bb021ec78480e0488736e4f8222920fbd9\nR = 7b7beaf9f696ca1a8051527478c4c075ab45aa4768937886dbf38618\nS = 93d4cf110a37c5a6f15c4e6024822118539e860dee2f60b8c3f462f6\n\nCurve = P-224\nPrivate = 04ef5d2a45341e2ace9af8a6ebd25f6cde45453f55b7a724eb6c21f6\nX = 8d642868e4d0f55ee62a2052e6b806b566d2ac79dbde7939fe725773\nY = 79505a57cd56904d2523b3e1281e9021167657d38aeb7d42fc8ec849\nDigest = 5f1d77f456d7ed30acad33795b50733d54226e57df4281a43d3821d0762f12fe\nK = ec60ea6f3d6b74d102e5574182566b7e79a69699a307fee70a2d0d22\nR = 2fd7fcbb7832c97ce325301dd338b279a9e28b8933284d49c6eabcf6\nS = 550b2f1efc312805a6ed8f252e692d8ee19eaa5bcd5d0cda63a1a3f0\n\nCurve = P-224\nPrivate = 35d4bbe77d149812339e85c79483cb270bdac56bbf30b5ef3d1f4d39\nX = 7924b1d7f5920cce98e25094e40f2eb3eb80d70b17e14b3d36c3671c\nY = 26c5af35f71e61858582b7cc2b41790597c53ee514ffdf7a289d108c\nDigest = cce0671ca07521fdaa81eced1dc37282bd9a6dbbaeb8cd00d13d4cf75cef044c\nK = 751869c1d0e79eb30aae8fbfb6d97bfa332123fd6b6c72c9cd3c1796\nR = 26bb1b92b0f01e94eba5fa429271371db527ce857abba13bd1103f64\nS = 836aba9c63e1252c2b2d72a21e6a41b82241ebe32647e7f814652bcb\n\nCurve = P-224\nPrivate = 2c291a393281b75264c9b8817af684fa86a1cdc900822f74039dc5d6\nX = 18cb5826ad60e6696bf07655032a3749f6577ca36da3ccd6e66a137c\nY = 194e14820fe02d784fd1363ff7a30399518309765bd3f4412d646da2\nDigest = 4ee903b828f54f35adab0bfec06eb064abde530d8ed0384730aa23e8e9664801\nK = e2a860416229dfd3f5a5cc92344ca015093a543943a0d8f73bf2b2fd\nR = 00e300c1ef4a8c4ca5da6413856f8981db49de29bdf03f32ffc3ceab\nS = f250f18a51ba5f63e1584097841099fa6ae4e98ee458c061d1d5aed7\n\nCurve = P-224\nPrivate = 831ea25dbeda33d272a1382c5def0e83929170ab06a629eed6ee244b\nX = 076518e393940d42dfd09819409d66966d8c9189c83d554a9cc8a082\nY = 44d0ceaf4c0f50e46bea4a52e30423ce3ada19edd363ac5694c65cb8\nDigest = 215e9817eccaa125e0c053fed373f4605de292d27a692bd4f744e63215fd8705\nK = 6be6dd9f6a083915ccba54626caf12d246d3aece0a7eda7d8d85599c\nR = ff1460946e06fb6f5d35e8d2625ca70ffb9b45308e3fabf6ad8351b1\nS = 6029aa3990918e8cb8a388d53b0772e5cdfff49c3405fe0d3a95933a\n\nCurve = P-224\nPrivate = 70f74c7324ef137318b610ead8ddc5b964e0eed3750b20612fc2e67b\nX = 279649e2a2918e683520cde3fc98b0ae58a7100e8de35e7c9cc797b6\nY = aa4de6be34be61f02880139787b9038f4554a8ef1c994b887c2974b5\nDigest = 6571a344765c0512d3911a7724509b649a6ce4106823be76726f117f109ec0fa\nK = 8e984864f86f7a2a73f3edda17dbccd13fac8fa4b872814abf223b1b\nR = 3b18736fa11d04e27e2614cda03a63ec11a180f357b0b3192920d09c\nS = 2f0f3dbd570727b14fbb29155538e62c930dd51c4035275c1365dc60\n\nCurve = P-224\nPrivate = 026be5789886d25039c11d7d58a11a6e1d52cb1d5657561f2165b8a8\nX = 3fa617c50b177da1a2bdb98b780ad21ad1195c4bd24465f6187de3c9\nY = e3fd8d8876dfd03a4a4e31a1acad3a08d983826d286c250c4e5620c1\nDigest = 95914b17ff0362e12305d71657bbc9d919ae4aa746bf4ebe95b2d2fe7ca3f022\nK = 0128b8e3f50731eb5fcc223517fc0cf6b96cd1d2807eb4524bc46f77\nR = 3a6b633f96f3d0b6d54f7fb29ac33709e4f0dd8fa0e51606ed9765ca\nS = 63e8c119dfa51784decd864f6911f2210a80f8f02d472d88df10d119\n\nCurve = P-224\nPrivate = e79c18d935c2839644762867aa793201f96a3cde080c5968412ce784\nX = b7ae1e992b1c7fde1141f40bd913358538ca0f07f62b729f13cea327\nY = 811252d12120e04805fc171a439d382c43b68a21e1a0bdf5e4ec1da4\nDigest = 2dd97b10b2ac90709062989f57873e30696bf8376957e68f7de95aa333a67685\nK = 7abedab1d36f4f0959a03d968b27dd5708223b66e0fc48594d827361\nR = d35047d74e1e7305bb8c1a94e8ae47cb1591c3437a3e185e00afe710\nS = d9c425c9d5feb776ac8952e6c4eee0ecd68aef2f0e7bff2e49c9185e\n\nCurve = P-224\nPrivate = 0d087f9d1f8ae29c9cf791490efc4a5789a9d52038c4b1d22494ad8c\nX = cd95cf8fb1cd21690f40d647f2353672a1076cc6c46bddaad2d0fc56\nY = 934262f74d9ee0f8a2754f64cb7415923d64bf00c94a39b52803f577\nDigest = 7c74a2e71f7bb3101787517394a67d03f977c95519526b47854e417b95bf8d1b\nK = 557d0e3995dc6377b3911546dd7aeaeec62a6d8f2af6a274382fc37f\nR = 56df0ea6afdcc232ceb41729eec00cf906b69b6e28423a36d3c92cc5\nS = f4f70fd948c9a147f55317fdea7b8a84c33e721014552d5800d63edc\n\nCurve = P-224\nPrivate = 0830aebb6577d3a3be3ba54a4501c987b0e0bb593267b9bbadb66583\nX = b88652020e083ccc1c43dc83d1881884dd4c7e3b4e3460b344b1ea64\nY = 22b69b517f86d7c26dc37c0f8feb4bb07fe876149fbcc3334fd2805b\nDigest = ccc04666744685c57d2256f21cee0f53857a0528a96d59bb13cdeb92fd786d4f\nK = e4f4a3280574c704c2fde47ca81ec883d27f2c5a961a294db7cda9d2\nR = b30b8a0079d9a134b5e1618c2ac63e3fbe0e95866b9dbc5f423f2707\nS = 3dc36746610271ef66e0aa52cc2ccadc5c9b08dc769e4dc4f6538c11\n\nCurve = P-224\nPrivate = 2acc9b97e625263e8e4cd164302c7d1e078bfcdd706111a13ccda5b2\nX = ce1a06f82df874dded37cca03b56c0648e4e8917ecd40ee73ee61588\nY = ceb6177b8f1ac7c5c6e6e1f7737cc3026952ee392badd2cd7af32f9d\nDigest = 9e7d5f30677692b669e21cf5461fa7f2e887dfcbbeb2db88d666bd591a944e00\nK = e401fa80f96480d437ed4f61a783888062ec33d530b188fd48016a6d\nR = 28674f447c4742e4087bbccfb522fbad4e18b56031d2ce8f532b078a\nS = a5a7a13d15b423dd17771f73cea98d89dbffa846cc209b45c0e29b76\n\nCurve = P-224\nPrivate = f4e873d4fb944fb52323406f933815092b7672221de4d1c45917f3fc\nX = 0dc2cdddb990341adb1de73f02d87fc3822485a659a15145f4251d5f\nY = cf78b2a83c7352eda1af2c74e1804ea04b35f76c04e89d90281dc2bb\nDigest = d8978f697bef71b062d4b3211e8ab5b993c09920af803614dbb9437f6e261b70\nK = 5d1476c682a64162fd2fdc82696fc8cab1469a86f707ea2757416e40\nR = 82982b38ed465138df4018d7cfb835edcb591cb57446ca49d163782b\nS = 8ef1d7b326cabee7f7ab95b7b98d3c27a069c0fd95a1599c0ccb422b\n\nCurve = P-224\nPrivate = 62c572ee0d6f81b27e591d788bfc2f42b5105d2663078dfb58069ebd\nX = bd6ba605639b98fa8113a16a3bb004ddfaec901c98a931206165f4a5\nY = a3190b10ef39e88abd60b2293b4707512b45c6c5ed5794cc11454427\nDigest = 1a9fc0195bf0f53cebba8aa7ccc8567c680d75187392d6d8201854ec4a6e6abd349037d831809e9f3add2fc09d27e4a4\nK = 0f0bb1e428bcdebf4dc62a5278068efc0f8ce75f89e89b3630f102b2\nR = aac0ea27e129f544abcc77f110e70bbdd5aa3e425dc39d5e8887025d\nS = 10e5dd06aee6b8419a04aa33d9d5678b0039c3acc3c4b61fe106bfdc\n\nCurve = P-224\nPrivate = e2f86bf73ba9336fa023343060f038e9ad41e5fe868e9f80574619a3\nX = f5d5346f17898ea6bbdfff19c216a8757a5dc37b95315f5481628381\nY = ae61fd172ac8b7a4f13870a932dece465834cbd4f50bbcfb802c824e\nDigest = 0f236d9a43edd55dacf5ff9f93ee805395e130ca2c8ad2eaea0fdd68e2ee2fadae9f41aa46f881485db208bd9cdc463b\nK = 35724ac043e3b44b73b5a7919cf675190306d26aa67c27c28c873534\nR = 535147c265af138eec50c7fb570bcc8d2e6f675597b0fcc034e536bc\nS = 743812c188a1dddf9fb34b90738f8b2e58760d6cd20ccceb1bb9c516\n\nCurve = P-224\nPrivate = b0a203438e2586d7575bc417a4a798e47abc22aa3955b58fc2789f17\nX = dc5d217862a1e5b00c95affa9d8b925a72b9beaeb7a86dc397e788d8\nY = 5f05f8e976ae1eb1036eca6d683a82850795bf9127dee5f8b2859445\nDigest = 525b6241eb2a6dd00b55b172708aafd0775e959b7c601903f44ffcfc17ee979f34f204680f8a71044a6d7e3679a50576\nK = 408e9c8b1f33136d6ddb93ff3a498bc09d4eee99bf69cdd5af0aa5a2\nR = 1b5a964c8b1fc634c6e2b82322499df1d7f0c12a4d2a77723c816ab8\nS = cf54599a36ca064fae0aa936de5266f87704409d22a15d28c01b7f2a\n\nCurve = P-224\nPrivate = efcfa50fad6fb2065f9a55f28c0c42fa24c809ccb19b6fc6d8ffb085\nX = 61521a0cfb72be77ba33cb3b8e022743cd9130ff49e97093b71aa178\nY = ce0819aedaf6fce639d0e593f8ab0147eeb6058f5f2b448231584ea9\nDigest = 88c4b7ca396f17e82c92596c301e41d7f01810bfeb33173cc0d1fedf3fd5ace6892ba9a788de13417f0ef00ff87344fb\nK = d1eea821f286eae6ebc1f61b08f9ad4323a3787e94af4c32cd31351b\nR = b37caaa71103752ac559f9eb4943324409ebfa8b585f684dcaa5c411\nS = 7c28e7619e2944ab4b7be022878c8052ebdf2cae5dff4f976c49686a\n\nCurve = P-224\nPrivate = 61a17816937987764cdc064dc7b5b4f5b16db1023acdfe25902957dd\nX = a7e975c0a8f87c683bb8e31bc160843a7b69c945f4850bd60e1c08c0\nY = 8930a454dcc2aa13bed7ea89368b2c9d689d816b2acf4e52585ee9c4\nDigest = 3babfaba30f3300171e6adcf4f62a12287031ac40078c96b2c2c063849e9a42ef3be953dc11fb319c18bf22fe511bf37\nK = 44b1fdec2629f9075f89c134ac28ff19bfddaa",
     "9db02a5d7f853582b4\nR = b0f5635d8bc9c53a1d54a3ec63de59ed66e6b2358d4ab79755414326\nS = 67c68fe265c7e5aba4232deeafb88545a2aa266fb9f2c2bb3f3ae8d2\n\nCurve = P-224\nPrivate = 79d5367314ec664aa0f6ca36f95549502a05bf8400bf532d669fab8d\nX = 3191f0237102dac159032ab2dde53cf56c9ec827b5caddfe9e83c02a\nY = b496b1bdcca4434ac0d0d91ea38ff3bc33f9f54095bfe17796d5a9e2\nDigest = 9f36da1a5653469a52f85e7e3b2a21ac3497cc00ff37e03235bbdf951695f182312ad5c8fb8a5fbd0295dc8c5acda068\nK = da529c52f5cc1f435d873109cd991d6cd7e1631d9ff1dd9521dd5db6\nR = 8e0ac63903f4921755430572c3f08bc272790639bdf1009fe2a9a714\nS = 6278c841a2d0a270791fe54b36c49d426d67907aa4e4f59c8638ad97\n\nCurve = P-224\nPrivate = 1320eedad4745121793a7eaf732b0b4498f7cb456cac8cf45a1f66f0\nX = 9fdd99906ab77fd29e9021bde947d05a7a9eb153612269bfb0899bc9\nY = 681b65b9ac8e4c2899bb622dafb253b7bf5a6e38e5f6595f997c291a\nDigest = 12532cbcfd4e80373bc235ac0bfa2a70b1044786d29f9384d555030f5df3cb5ab9f973df638b6835cb756792d1fe1a4e\nK = 66ed8d8934633f4125f593cf1b1d3745c4db1f15dde60cf46ca1c7f2\nR = 80199485a3a96447b39f7679cd47412a78675ba17dcbd10465dc5b48\nS = a251fd9f136a3cb0dd0bc80659ae032e4a761ba7045da0034553fb8c\n\nCurve = P-224\nPrivate = e18821329447d3f65ba7279e96bd4624ffa1b32b90f6e8331b1e876d\nX = 46c9ed837232c47022df2f1a1578fbe65ac9f2e81c98a74cc22ea31a\nY = 6fc5e9568ae62b31412a0b0b367242e9fd7e518c83aa06a069e1d90d\nDigest = 89030408e06cc06d3dbfb51f6725c710a2bc9db9e07ff1ec8a32a827d93d2dc951834cdb01a7afa1fe4cf4e9186ee424\nK = a4c1eb402a2fb3af26e0e14a3d2fc8ed3bc1a8b2475270356a79fdd3\nR = d478b68733d8ad44be46766e7b66af782fbdc7ff7ed0b191176da98a\nS = 5eae9160ccf71fd1d359d89cecce72ef8afaeee2365f6ba828aa450a\n\nCurve = P-224\nPrivate = f73e030d5a696b358986d3efaca121cf71f775f8835a21e6135145d7\nX = 9ca2c6ea87ac8dd3a23a5b4010841a7c8af309038882ae44634bcf55\nY = b0a347dbd5ded3b8702ac5a457e8b32bd4de06fd315095fa1b7d5fe1\nDigest = eda24262a9e64be110a6c96763e8a4b5edb38af2a084695e294593583b462c56b0db50bc014eb19278e3f3d675eb5f22\nK = e3cc786c1288ea567836c51d6d69dd0cab5c015987d936ccc3a4beb3\nR = f1234da71761b7a0f49e661a419d2a739bdc4544bf87690e3d2f96db\nS = 096d16bf8020c3d3c233894ad8eb81206010e62c6e692a215e088fd4\n\nCurve = P-224\nPrivate = 7a0789323f8741c157a1753ae165ecaf8e8b03a60561f8b80cee467c\nX = 101271a9addd4bd1f19d00bf116c8524f52cefd598e85dc381597acb\nY = 2f17d14f4d8ccb28b216553718152ba7c104646d8eca986dd9ddea39\nDigest = 983a5d16b009cc65bdf3c3badc2f21280e04f44244b70a583c2e9732534497373f51b226c3ab7bd69c6940e46bc41fa1\nK = d169f04f05b60c625cda864d187938863964dab7bb3b9dfc04b05519\nR = e4a51be686a764b709da23ab48b1985e153c6ee238d945e743907afc\nS = 118a8f1ffe3cd556ce6345bd1a398dd9cc3729b7fd6d8af9bfd82f40\n\nCurve = P-224\nPrivate = 78e795d0edb11fd9e28dc26b21e751aa89bea0d87932ef11c95c0e18\nX = 9edd544107977134bf6360d43ccabb3c94d627c03963c0a04b439627\nY = ece4c61d319a0e41f3de7863e7c355bac94395aaa74cdb5f74a87a5b\nDigest = ae7b5fde427af9c450368b11f66f49bf8c3b6e1f5abed6bb25683001924dfb005738637e1c1b7855566330d202ecc763\nK = 36f7c0f76808b826a0a974a1fd6e155e00a73f1d34674a8f88be405a\nR = 3e319444438bc2cc92f323ea842cb402b3c3c2448c89869ef7998edb\nS = 3420cc38f058f41c31e71f4b1ad488f801111c73541de69fcee60695\n\nCurve = P-224\nPrivate = bee02d8bc5bffb3fd3b4c9d6f686409f02662d10150d1e58d689966a\nX = 8848f964c847fe9dddc774618d4588c9cd56bbe588d7b1fb369c8bfa\nY = ebbb699fbd0dc08859fe9132285fe20dff3b9d561c0640b6e0717607\nDigest = 63ef787f467ff0cd6e5012b09414c00ef56dba959c4b62bf7e76a4205078d436c45591752c8d55abe728a2d28b5b0643\nK = 59f1450d857b40e5552a4b8cd4ab0df2f01716635d172c1106840f21\nR = a206d8398a16a991bc217f77f23c6f648384f254f255a8a876404444\nS = eb1169cb5b1423dc0bfaffe565ae57f986e00de06405e3e7b605862e\n\nCurve = P-224\nPrivate = dc0ddf6e501418bb8eafc5d7ccc143369e2aa441df8fc57d5f94a738\nX = 063a5d632f4144376e14cfb03ad8ccf1489b613acd184d20dff66545\nY = e77727f057b043d8a0f7458196b72e92d11f85b0891c6aaa9d915f58\nDigest = 11f0d587e82e7490af4737c272877d9d37c1e7ae7f2fd3b00d8fa0d4f2bcb3a41d5185e65604b8c411a407eb6c558954\nK = ff0e5cae2671db7a1b90e22c63e7570bdd27352d45bac31e338debe0\nR = 5bc0b4998481ecbd3b6609184a84ca41d69b08c37138097f559259f8\nS = 0df8828eb1ca85e46405b94e1a2972c34c5e620a54e2f640f04aecc5\n\nCurve = P-224\nPrivate = 229d89b2fcf8441ffc95ebb2ac2ef156e25825782044b2b8bd6a3e01\nX = de616848d8044a44789ef1ba3a6dd66fe9257ddc57f7534e59a701be\nY = 26cbf74a6d25e5b34b96d30f327abd574cff7f7dbe6686573a7d6c5c\nDigest = 537d6d3d4be3e3beaf31014dae59ca7186c1c1a32c88068ff343180a138ceb6d7c38e0ae1e9b51003b71c1a2f3a3741b\nK = 3b18ca6ec8e8e255ac88f64302745ca0b73ff94b2b2d48be95b4aaee\nR = fa94fd8b827c06115c1eefd50afc02ce5926ee0e789667783c01c34b\nS = edf766a66973cfc33e4159966c07321a7f6549c3c60e8586ef41402b\n\nCurve = P-224\nPrivate = 97d747068147c0393a0bb5c159e2c9f1bd538f6204823294883abe28\nX = 3858a576eef2ce24d01766997fb81b3f3f78b6104cd188610be221d7\nY = 95ffc677ac7bfe3e0bb4cffb17355a964c8356a807151b3cba5d1f4e\nDigest = 7e16034a71ebf52a7a6cd00fe469c6edc121b2882462176298c9443aca2a0ad6ebe2eb9e145097409873170f40d503dd\nK = c1a2ec1ef16cfd5107c892790daefbed061be78bd8576696b60f64d5\nR = 18c908541843fcdac99b9ff6bb397f3f8094d16b42670216e4eaa2d7\nS = c107a8a508ff57c5d4f78f86cc37e129c864d1c44ed5e73909613b74\n\nCurve = P-224\nPrivate = ba5374541c13597bded6880849184a593d69d3d4f0b1cb4d0919cbd6\nX = ac635fe00e8b7a3c8ef5655bdfb7f83e8532e59c0cc0b6534d810ffa\nY = 1d067aebeba66e79b28ecfe59ac6fdf5e1970dc3a84499c9d90cd8e2\nDigest = 3edbb59a32b2464291d0a96023a798c1fc6cb5ff4fcecfadcfac2be00c26fa27181aef76c96d8269aeaf2275eeacbb777abbd9571de9279edc5695a3345cad9b\nK = 187ed1f45c466cbafcd4b9577fb222408c011225dcccfd20f08b8d89\nR = f83d54945997584c923c09662c34cf9ad1e987da8bfd9be600e7a098\nS = 4ff2dba9dba992c98a095b1144a539310e1a570e20c88b7d0aa1955c\n\nCurve = P-224\nPrivate = 1e27187134d0a63542adf4665fba22f00cfc7b0a1e02effe913ceedc\nX = ecaea8ceea55c3bd418fd34a4ff2499e25e66a104eed846bc00c31d2\nY = 3933a356ab1f2dabc303ff0a5d076131e77032e6f502336883bf78a7\nDigest = 825ab979af5c263d9f074a2d771d1d1cdfa435e7938245a3c9ee30cb77ee8c1475051d2f09d7d11d920a6c754bfd253903131c491994679cafdb8cfbf32b763d\nK = 34cb597deae9a3b1cada937abcd247161b19b2b336b20e2e42ae01f1\nR = 58177ba46fb291490b39368774accf72736412c1fb5ee0f27b9b1e02\nS = 58337d78b95a080bfcabb5809bee012501b4da84b8ef310a4628f11c\n\nCurve = P-224\nPrivate = 0905b40e6c29bfcbf55e04266f68f10ca8d3905001d68bb61a27749b\nX = d656b73b131aa4c6336a57849ce0d3682b6ab2113d013711e8c29762\nY = 6328335ffc2029afbfe2a15cc5636978778c3f9dab84840b05f2e705\nDigest = d0db7c20c201cd8c63ca777293543750d7f6a9e375b056e74cfe9fb2c95b2cc9807d8a9607a5b0fad6eeda86e4f73ace139e77a5356181b8cbef3f88173253b6\nK = dc82840d147f893497a82f023d7d2cbf0a3a5b2ac6cc1b9b23e504be\nR = 583af080e0ec7c1ba5a491a84889b7b7b11ccfe18927c7c219b11757\nS = b23700035349df25d839f0973bef78a7515287de6c83707907074fa6\n\nCurve = P-224\nPrivate = afbaede5d75e4f241dd5b53220f3f5b9c1aa1d5d298e2d43236452dc\nX = fe83e59fc8ea8b939355d3258fe53a64d45f63031a0716b7cc416173\nY = f151d23060f1c856eb7f1f58be72a7228c3af89e43b56e9695b558c7\nDigest = 37d9091eddc6fc34b45cf97140e956a42ab659f6bd442e81b57c4ecfbdab45f7380a7efdbac5400ceb1bf683194232cd086c1b4e09fc9313f1bc38af731f1a98\nK = 0fbbe7b40136c81a8fb894498d5502157a1cf5a89d0643de92cd38f6\nR = 24f3f457c7b72b7e759d5a8afbf330e31c5d8d2e36f92c0e79c5d87d\nS = 36fd1193def34f12a960740fd79fb38bf2b480726ccad540eb42cdf8\n\nCurve = P-224\nPrivate = 950b07b0c2b7539a21b5135bfede214733f2e009647d38d8b21d760c\nX = f43d13bbfcee3b724063b3910fea49fd591b81e86fdb813b1a492d0c\nY = 6b4c8d6fa5dc661889e3cf5ec64997a78222837885f85d2fe9b684fb\nDigest = 8ddf64c9c67289a76c2f5b44a30b8365f4adf487b4edadada5749cad9e5765c57a348a750817a53e5c2ff551e003747ca1e3438b2aa1952c6876fda8fd8f4de2\nK = 83e110d0d1e700d2f36543028737d2a2f1474aa3b4b28998a39e4793\nR = 2685265bc878e85d10ab13293dec190881a57c4a467f8fc2170432ea\nS = 80a347bb49036522369339bd6485a967cdda818915d8eb947302fcf9\n\nCurve = P-224\nPrivate = 015bd9f5dfef393b431c3c7fced24385d861ccb563542574a5d2a9bc\nX = e868690641e2cda13b289a6c5d2fb175940396044d9cf27b4f2240af\nY = 4c78c9abdf2b7fc67ed4497001d7bcf1daca1739dc14a661f91d7c40\nDigest = 7c22f34d5897ccdf7d807f68a7f16e3093a4413625e7853401a4e0384d26893f1997c84557515f2ea66afe7629f62415e6b98e18e97dcb4fb2dec97cf2dd68d9\nK = e2374350f47c08f3c1359d4edf87e61d1ba4e7dd1540d8d9062efa79\nR = e12dc088d2bc032bb214c77d0e0fb749fc8e61ebe1ed72996f1084b6\nS = 0ab58aa31e0bba5fbc76855e6549",
@@ -2542,9 +2562,9 @@
     "1d2f3d15e51352\nY = 0014368b8e746807b2b68f3615cd78d761a464ddd7918fc8df51d225962fdf1e3dc243e265100ff0ec133359e332e44dd49afd8e5f38fe86133573432d33c02fa0a3\nDigest = a6200971c6a289e2fcb80f78ec08a5079ea2675efd68bcab479552aa5bcb8edf3c993c79d7cebcc23c20e5af41723052b871134cc71d5c57206182a7068cc39b\nK = 00bc2c0f37155859303de6fa539a39714e195c37c6ea826e224c8218584ae09cd0d1cc14d94d93f2d83c96e4ef68517fdb3f383da5404e5a426bfc5d424e253c181b\nR = 01a3c4a6386c4fb614fba2cb9e74201e1aaa0001aa931a2a939c92e04b8344535a20f53c6e3c69c75c2e5d2fe3549ed27e6713cb0f4a9a94f6189eb33bff7d453fce\nS = 016a997f81aa0bea2e1469c8c1dab7df02a8b2086ba482c43af04f2174831f2b1761658795adfbdd44190a9b06fe10e578987369f3a2eced147cff89d8c2818f7471\n\nCurve = P-521\nPrivate = 014787f95fb1057a2f3867b8407e54abb91740c097dac5024be92d5d65666bb16e4879f3d3904d6eab269cf5e7b632ab3c5f342108d1d4230c30165fba3a1bf1c66f\nX = 00c2d540a7557f4530de35bbd94da8a6defbff783f54a65292f8f76341c996cea38795805a1b97174a9147a8644282e0d7040a6f83423ef2a0453248156393a1782e\nY = 0119f746c5df8cec24e4849ac1870d0d8594c799d2ceb6c3bdf891dfbd2242e7ea24d6aec3166214734acc4cbf4da8f71e2429c5c187b2b3a048527c861f58a9b97f\nDigest = 46ff533622cc90321a3aeb077ec4db4fbf372c7a9db48b59de7c5d59e6314110676ba5491bd20d0f02774eef96fc2e88ca99857d21ef255184c93fb1ff4f01d3\nK = 0186cd803e6e0c9925022e41cb68671adba3ead5548c2b1cd09348ab19612b7af3820fd14da5fe1d7b550ed1a3c8d2f30592cd7745a3c09ee7b5dcfa9ed31bdd0f1f\nR = 010ed3ab6d07a15dc3376494501c27ce5f78c8a2b30cc809d3f9c3bf1aef437e590ef66abae4e49065ead1af5f752ec145acfa98329f17bca9991a199579c41f9229\nS = 008c3457fe1f93d635bb52df9218bf3b49a7a345b8a8a988ac0a254340546752cddf02e6ce47eee58ea398fdc9130e55a4c09f5ae548c715f5bcd539f07a34034d78\n\nCurve = P-521\nPrivate = 015807c101099c8d1d3f24b212af2c0ce525432d7779262eed0709275de9a1d8a8eeeadf2f909cf08b4720815bc1205a23ad1f825618cb78bde747acad8049ca9742\nX = 0160d7ea2e128ab3fabd1a3ad5455cb45e2f977c2354a1345d4ae0c7ce4e492fb9ff958eddc2aa61735e5c1971fa6c99beda0f424a20c3ce969380aaa52ef5f5daa8\nY = 014e4c83f90d196945fb4fe1e41913488aa53e24c1d2142d35a1eed69fed784c0ef44d71bc21afe0a0065b3b87069217a5abab4355cf8f4ceae5657cd4b9c8008f1f\nDigest = 6b514f8d85145e30ced23b4b22c85d79ed2bfcfed5b6b2b03f7c730f1981d46d4dadd6699c28627d41c8684bac305b59eb1d9c966de184ae3d7470a801c99fd4\nK = 0096731f8c52e72ffcc095dd2ee4eec3da13c628f570dba169b4a7460ab471149abdede0b63e4f96faf57eab809c7d2f203fd5ab406c7bd79869b7fae9c62f97c794\nR = 01e2bf98d1186d7bd3509f517c220de51c9200981e9b344b9fb0d36f34d969026c80311e7e73bb13789a99e0d59e82ebe0e9595d9747204c5f5550c30d934aa30c05\nS = 012fed45cc874dc3ed3a11dd70f7d5c61451fbea497dd63e226e10364e0718d3722c27c7b4e5027051d54b8f2a57fc58bc070a55b1a5877b0f388d768837ef2e9cec\n\nCurve = P-521\nPrivate = 018692def0b516edcdd362f42669999cf27a65482f9358fcab312c6869e22ac469b82ca9036fe123935b8b9ed064acb347227a6e377fb156ec833dab9f170c2ac697\nX = 01ceee0be3293d8c0fc3e38a78df55e85e6b4bbce0b9995251f0ac55234140f82ae0a434b2bb41dc0aa5ecf950d4628f82c7f4f67651b804d55d844a02c1da6606f7\nY = 01f775eb6b3c5e43fc754052d1f7fc5b99137afc15d231a0199a702fc065c917e628a54e038cbfebe05c90988b65183b368a2061e5b5c1b025bbf2b748fae00ba297\nDigest = 53c86e0b08b28e22131324f6bfad52984879ab09363d6b6c051aac78bf3568be3faeade6a2dda57dece4527abaa148326d3adbd2d725374bdac9ccb8ac39e51e\nK = 0161cf5d37953e09e12dc0091dc35d5fb3754c5c874e474d2b4a4f1a90b870dff6d99fb156498516e25b9a6a0763170702bb8507fdba4a6131c7258f6ffc3add81fd\nR = 014dfa43046302b81fd9a34a454dea25ccb594ace8df4f9d98556ca5076bcd44b2a9775dfaca50282b2c8988868e5a31d9eb08e794016996942088d43ad3379eb9a1\nS = 0120be63bd97691f6258b5e78817f2dd6bf5a7bf79d01b8b1c3382860c4b00f89894c72f93a69f3119cb74c90b03e9ede27bd298b357b9616a7282d176f3899aaa24\n\nCurve = P-521\nPrivate = 00a63f9cdefbccdd0d5c9630b309027fa139c31e39ca26686d76c22d4093a2a5e5ec4e2308ce43eb8e563187b5bd811cc6b626eace4063047ac0420c3fdcff5bdc04\nX = 014cab9759d4487987b8a00afd16d7199585b730fb0bfe63796272dde9135e7cb9e27cec51207c876d9214214b8c76f82e7363f5086902a577e1c50b4fbf35ce9966\nY = 01a83f0caa01ca2166e1206292342f47f358009e8b891d3cb817aec290e0cf2f47e7fc637e39dca03949391839684f76b94d34e5abc7bb750cb44486cce525eb0093\nDigest = a9e9a9cb1febc380a22c03bacd18f8c46761180badd2e58b94703bd82d5987c52baec418388bc3f1e6831a130c400b3c865c51b73514f5b0a9026d9e8da2e342\nK = 001e51fd877dbbcd2ab138fd215d508879298d10c7fcbdcc918802407088eb6ca0f18976a13f2c0a57867b0298512fc85515b209c4435e9ef30ab01ba649838bc7a0\nR = 011a1323f6132d85482d9b0f73be838d8f9e78647934f2570fededca7c234cc46aa1b97da5ac1b27b714f7a171dc4209cbb0d90e4f793c4c192dc039c31310d6d99b\nS = 00386a5a0fc55d36ca7231a9537fee6b9e51c2255363d9c9e7cb7185669b302660e23133eb21eb56d305d36e69a79f5b6fa25b46ec61b7f699e1e9e927fb0bceca06\n\nCurve = P-521\nPrivate = 0024f7d67dfc0d43a26cc7c19cb511d30a097a1e27e5efe29e9e76e43849af170fd9ad57d5b22b1c8840b59ebf562371871e12d2c1baefc1abaedc872ed5d2666ad6\nX = 009da1536154b46e3169265ccba2b4da9b4b06a7462a067c6909f6c0dd8e19a7bc2ac1a47763ec4be06c1bec57d28c55ee936cb19588cc1398fe4ea3bd07e6676b7f\nY = 014150cdf25da0925926422e1fd4dcfcffb05bdf8682c54d67a9bd438d21de5af43a15d979b320a847683b6d12ac1383a7183095e9da491c3b4a7c28874625e70f87\nDigest = 7e324819033de8f2bffded5472853c3e68f4872ed25db79636249aecc24242cc3ca229ce7bd6d74eac8ba32f779e7002095f5d452d0bf24b30e1ce2eb56bb413\nK = 01c1308f31716d85294b3b5f1dc87d616093b7654907f55289499b419f38ceeb906d2c9fe4cc3d80c5a38c53f9739311b0b198111fede72ebde3b0d2bc4c2ef090d2\nR = 000dbf787ce07c453c6c6a67b0bf6850c8d6ca693a3e9818d7453487844c9048a7a2e48ff982b64eb9712461b26b5127c4dc57f9a6ad1e15d8cd56d4fd6da7186429\nS = 00c6f1c7774caf198fc189beb7e21ca92ceccc3f9875f0e2d07dc1d15bcc8f210b6dd376bf65bb6a454bf563d7f563c1041d62d6078828a57538b25ba54723170665\n\nCurve = P-521\nPrivate = 00349471460c205d836aa37dcd6c7322809e4e8ef81501e5da87284b267d843897746b33016f50a7b702964910361ed51d0afd9d8559a47f0b7c25b2bc952ce8ed9e\nX = 000bbd4e8a016b0c254e754f68f0f4ed081320d529ecdc7899cfb5a67dd04bc85b3aa6891a3ed2c9861ae76c3847d81780c23ad84153ea2042d7fd5d517a26ff3ce4\nY = 00645953afc3c1b3b74fdf503e7d3f982d7ee17611d60f8eb42a4bddbec2b67db1f09b54440c30b44e8071d404658285cb571462001218fc8c5e5b98b9fae28272e6\nDigest = 4541f9a04b289cd3b13d31d2f513d9243b7e8c3a0cbd3e0c790892235a4d4569ef8aef62444ecc64608509e6ad082bf7cd060d172550faa158b2fd396aa1e37b\nK = 000eb2bd8bb56b9d2e97c51247baf734cc655c39e0bfda35375f0ac2fe82fad699bf1989577e24afb33c3868f91111e24fefe7dec802f3323ac013bec6c048fe5568\nR = 014bf63bdbc014aa352544bd1e83ede484807ed760619fa6bc38c4f8640840195e1f2f149b29903ca4b6934404fb1f7de5e39b1ea04dba42819c75dbef6a93ebe269\nS = 005d1bcf2295240ce4415042306abd494b4bda7cf36f2ee2931518d2454faa01c606be120b057062f2f3a174cb09c14f57ab6ef41cb3802140da22074d0e46f908d4\n\nCurve = P-521\nPrivate = 007788d34758b20efc330c67483be3999d1d1a16fd0da81ed28895ebb35ee21093d37ea1ac808946c275c44454a216195eb3eb3aea1b53a329eca4eb82dd48c784f5\nX = 00157d80bd426f6c3cee903c24b73faa02e758607c3e102d6e643b7269c299684fdaba1acddb83ee686a60acca53cddb2fe976149205c8b8ab6ad1458bc00993cc43\nY = 016e33cbed05721b284dacc8c8fbe2d118c347fc2e2670e691d5d53daf6ef2dfec464a5fbf46f8efce81ac226915e11d43c11c8229fca2327815e1f8da5fe95021fc\nDigest = 7ec0906f9fbe0e001460852c0b6111b1cd01c9306c0c57a5e746d43f48f50ebb111551d04a90255b22690d79ea60e58bed88220d485daaf9b6431740bb499e39\nK = 00a73477264a9cc69d359464abb1ac098a18c0fb3ea35e4f2e6e1b060dab05bef1255d9f9c9b9fbb89712e5afe13745ae6fd5917a9aedb0f2860d03a0d8f113ea10c\nR = 007e315d8d958b8ce27eaf4f3782294341d2a46fb1457a60eb9fe93a9ae86f3764716c4f5f124bd6b114781ed59c3f24e18aa35c903211b2f2039d85862932987d68\nS = 01bcc1d211ebc120a97d465b603a1bb1e470109e0a55d2f1b5c597803931bd6d7718f010d7d289b31533e9fcef3d141974e5955bc7f0ee342b9cad05e29a3dded30e\n\nCurve = P-521\nPrivate = 01f98696772221e6cccd5569ed8aed3c435ee86a04689c7a64d20c30f6fe1c59cc10c6d2910261d30c3b96117a669e19cfe5b696b68feeacf61f6a3dea55e6e5837a\nX = 007002872c200e16d57e8e53f7bce6e9a7832c387f6f9c29c6b75526262c57bc2b56d63e9558c5761c1d62708357f586d3aab41c6a7ca3bf6c32d9c3ca40f9a2796a\nY = 01fe3e52472ef224fb38d5a0a14875b52c2f50b82b99eea98d826c77e6a9ccf798de5ffa92a0d65965f740c702a3027be66b9c844f1b2e96c134eb3fdf3edddcf11c\nDigest = 7230642b79eed2fd50f19f79f943d67d6ef609ec06c9adbb4b0a62126926080ecd474922d1af6c01f4c354affde016b284b13dbb3122555dea2a2e6ca2a357dc\nK = 01a277cf0414c6adb621d1cc0311ec908401ce040c6687ed45",
     "a0cdf2910c42c9f1954a4572d8e659733d5e26cbd35e3260be40017b2f5d38ec42315f5c0b056c596d\nR = 00d732ba8b3e9c9e0a495249e152e5bee69d94e9ff012d001b140d4b5d082aa9df77e10b65f115a594a50114722db42fa5fbe457c5bd05e7ac7ee510aa68fe7b1e7f\nS = 0134ac5e1ee339727df80c35ff5b2891596dd14d6cfd137bafd50ab98e2c1ab4008a0bd03552618d217912a9ec502a902f2353e757c3b5776309f7f2cfebf913e9cd\n\nCurve = P-521\nPrivate = 013c3852a6bc8825b45fd7da1754078913d77f4e586216a6eb08b6f03adce7464f5dbc2bea0eb7b12d103870ef045f53d67e3600d7eba07aac5db03f71b64db1cceb\nX = 00c97a4ebcbbe701c9f7be127e87079edf479b76d3c14bfbee693e1638e5bff8d4705ac0c14597529dbe13356ca85eb03a418edfe144ce6cbf3533016d4efc29dbd4\nY = 011c75b7a8894ef64109ac2dea972e7fd5f79b75dab1bf9441a5b8b86f1dc1324426fa6cf4e7b973b44e3d0576c52e5c9edf8ce2fc18cb3c28742d44419f044667f8\nDigest = d209f43006e29ada2b9fe840afdf5fe6b0abeeef5662acf3fbca7e6d1bf4538f7e860332ef6122020e70104b541c30c3c0581e2b1daa0d767271769d0f073133\nK = 01e25b86db041f21c2503d547e2b1b655f0b99d5b6c0e1cf2bdbd8a8c6a053f5d79d78c55b4ef75bff764a74edc920b35536e3c470b6f6b8fd53898f3bbc467539ef\nR = 01dce45ea592b34d016497882c48dc0c7afb1c8e0f81a051800d7ab8da9d237efd892207bc9401f1d30650f66af8d5349fc5b19727756270722d5a8adb0a49b72d0a\nS = 00b79ffcdc33e028b1ab894cb751ec792a69e3011b201a76f3b878655bc31efd1c0bf3b98aea2b14f262c19d142e008b98e890ebbf464d3b025764dd2f73c4251b1a\n\nCurve = P-521\nPrivate = 01654eaa1f6eec7159ee2d36fb24d15d6d33a128f36c52e2437f7d1b5a44ea4fa965c0a26d0066f92c8b82bd136491e929686c8bde61b7c704daab54ed1e1bdf6b77\nX = 01f269692c47a55242bb08731ff920f4915bfcecf4d4431a8b487c90d08565272c52ca90c47397f7604bc643982e34d05178e979c2cff7ea1b9eaec18d69ca7382de\nY = 00750bdd866fba3e92c29599c002ac6f9e2bf39af8521b7b133f70510e9918a94d3c279edec97ab75ecda95e3dd7861af84c543371c055dc74eeeff7061726818327\nDigest = c992314e8d282d10554b2e6e8769e8b10f85686cccafb30e7db62beaad080e0da6b5cf7cd1fc5614df56705fb1a841987cb950101e2f66d55f3a285fc75829ff\nK = 01b7519becd00d750459d63a72f13318b6ac61b8c8e7077cf9415c9b4b924f35514c9c28a0fae43d06e31c670a873716156aa7bc744577d62476e038b116576a9e53\nR = 0183bddb46c249e868ef231a1ebd85d0773bf8105a092ab7d884d677a1e9b7d6014d6358c09538a99d9dca8f36f163ac1827df420c3f9360cc66900a9737a7f756f3\nS = 00d05ee3e64bac4e56d9d8bd511c8a43941e953cba4e5d83c0553acb87091ff54f3aad4d69d9f15e520a2551cc14f2c86bb45513fef0295e381a7635486bd3917b50\n\nCurve = P-521\nPrivate = 01cba5d561bf18656991eba9a1dde8bde547885ea1f0abe7f2837e569ca52f53df5e64e4a547c4f26458b5d9626ed6d702e5ab1dd585cf36a0c84f768fac946cfd4c\nX = 012857c2244fa04db3b73db4847927db63cce2fa6cb22724466d3e20bc950a9250a15eafd99f236a801e5271e8f90d9e8a97f37c12f7da65bce8a2c93bcd25526205\nY = 00f394e37c17d5b8e35b488fa05a607dbc74264965043a1fb60e92edc212296ae72d7d6fe2e3457e67be853664e1da64f57e44bd259076b3bb2b06a2c604fea1be9d\nDigest = 6e14c91db5309a075fe69f6fe8ecd663a5ba7fab14770f96b05c22e1f631cde9e086c44335a25f63d5a43ddf57da899fcedbc4a3a4350ad2edd6f70c01bb051e\nK = 00e790238796fee7b5885dc0784c7041a4cc7ca4ba757d9f7906ad1fcbab5667e3734bc2309a48047442535ff89144b518f730ff55c0c67eeb4c880c2dfd2fb60d69\nR = 01d7ce382295a2a109064ea03f0ad8761dd60eefb9c207a20e3c5551e82ac6d2ee5922b3e9655a65ba6c359dcbf8fa843fbe87239a5c3e3eaecec0407d2fcdb687c2\nS = 0161963a6237b8955a8a756d8df5dbd303140bb90143b1da5f07b32f9cb64733dc6316080924733f1e2c81ade9d0be71b5b95b55666026a035a93ab3004d0bc0b19f\n\nCurve = P-521\nPrivate = 00972e7ff25adf8a032535e5b19463cfe306b90803bf27fabc6046ae0807d2312fbab85d1da61b80b2d5d48f4e5886f27fca050b84563aee1926ae6b2564cd756d63\nX = 01d7f1e9e610619daa9d2efa563610a371677fe8b58048fdc55a98a49970f6afa6649c516f9c72085ca3722aa595f45f2803402b01c832d28aac63d9941f1a25dfea\nY = 01571facce3fcfe733a8eef4e8305dfe99103a370f82b3f8d75085414f2592ad44969a2ef8196c8b9809f0eca2f7ddc71c47879e3f37a40b9fecf97992b97af29721\nDigest = 26b4f562053f7aed8b7268e95eff336ac80a448fae52329d2771b138c9c7f70de936ef54158446afa72b0a27c2a73ca45dfa38a2ba2bf323d31aba499651128f\nK = 00517f6e4002479dc89e8cbb55b7c426d128776ca82cf81be8c1da9557178783f40e3d047db7e77867f1af030a51de470ee3128c22e9c2d642d71e4904ab5a76edfa\nR = 01c3262a3a3fb74fa5124b71a6c7f7b7e6d56738eabaf7666b372b299b0c99ee8a16be3df88dd955de093fc8c049f76ee83a4138cee41e5fe94755d27a52ee44032f\nS = 0072fd88bb1684c4ca9531748dfce4c161037fcd6ae5c2803b7117fb60d3db5df7df380591aaf3073a3031306b76f062dcc547ded23f6690293c34a710e7e9a226c3\n\nCurve = P-521\nPrivate = 01f0ec8da29295394f2f072672db014861be33bfd9f91349dad5566ff396bea055e53b1d61c8c4e5c9f6e129ed75a49f91cce1d5530ad4e78c2b793a63195eb9f0da\nX = 009ec1a3761fe3958073b9647f34202c5e8ca2428d056facc4f3fedc7077fa87f1d1eb30cc74f6e3ff3d3f82df2641cea1eb3ff1529e8a3866ae2055aacec0bf68c4\nY = 00bed0261b91f664c3ff53e337d8321cb988c3edc03b46754680097e5a8585245d80d0b7045c75a9c5be7f599d3b5eea08d828acb6294ae515a3df57a37f903ef62e\nDigest = ea13b25b80ec89ffa649a00ce85a494892f9fb7389df56eed084d670efb020c05508ac3f04872843c92a67ee5ea02e0445dad8495cd823ca16f5510d5863002b\nK = 00ac3b6d61ebda99e23301fa198d686a13c0832af594b289c9a55669ce6d62011384769013748b68465527a597ed6858a06a99d50493562b3a7dbcee975ad34657d8\nR = 00cef3f4babe6f9875e5db28c27d6a197d607c3641a90f10c2cc2cb302ba658aa151dc76c507488b99f4b3c8bb404fb5c852f959273f412cbdd5e713c5e3f0e67f94\nS = 00097ed9e005416fc944e26bcc3661a09b35c128fcccdc2742739c8a301a338dd77d9d13571612a3b9524a6164b09fe73643bbc31447ee31ef44a490843e4e7db23f\n",
 };
-static const size_t kLen34 = 160910;
+static const size_t kLen35 = 160910;
 
-static const char *kData35[] = {
+static const char *kData36[] = {
     "# Tests from NIST CAVP 186-4 ECDSA2VS Test Vectors, Signature Verification Test\n# http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip\n#\n# NIST's files provide message and digest pairs. Since this is a low-level test,\n# the digests have been extracted. P-521 test vectors were fixed to have the\n# right number of leading zeros.\n\nCurve = P-224\nX = a100d410ce497e991070285c439cd361a1a9c6c973fd6f5e1ba9ec66\nY = 0a8c3a2f909f212c84441b8c0030529cbd731304d86f771d89d7cc29\nDigest = 6a02c84186eb132d8e91ab6fea2e066f6f8de1a5\nR = 1bfcaab01e47addd4733369320364ad208169ffb15e6aac33c2d7c06\nS = 07fb33465e7b7b373feda2ea35ab7cc9477156a1335ecad942f99627\n\nCurve = P-224\nX = a6cd3d14cd5eb188a9f59d9c32e93d890558de382f6fba5ff5c6e395\nY = 7a76734a0afead9e5e4aba65f1ae353d6445b1689b5ea402de5f9af9\nDigest = ab1205b7f9f591a013c70cb645435b38689644c1\nR = f0f670963c3d2a3281d639f850f3781c6402d99a1bf07cd9f35b2975\nS = 758e84920c1b744502cd787cdd64ec58364ccc6917258a2580097492\nInvalid =\n\nCurve = P-224\nX = f5fe7875a517207f1336ec2bb4fe5cc7eb80ee2b0f8ebeff4c56e620\nY = 0b7ac24ea9092d03b28904d89714b517be023235abc9cffa297cf4ad\nDigest = d62c7a42fcf3738276a6e0d27160328e9f27e5aa\nR = 88617e694e361d2cfef6b0658d444607fba030ad31fe8dead14db22e\nS = 5b0bf37c4a583dd75d99aec20943ea02617cecdbcd295d35ed01cc32\nInvalid =\n\nCurve = P-224\nX = 8a6a77179ffc0ff5d412cf859cc82aa19cd18e5224ab997e9c2e46b0\nY = 3d67c177ca7cc12c7b05a3bf55fb78549ef5400a566efe8ae3580c9f\nDigest = 0b5a025a4038b6f9f995001c0b8d7a660e6766c2\nR = 107b7442e6569ddde54b5da55a9dac9bd348079358047a19a3de0b91\nS = 92359be39353cb263946294fb728eecf1880f50a43637f391d3e7824\n\nCurve = P-224\nX = f9f23388d573562f29e7e7c9a98f27e7a1ff02d2d66e177c6506466f\nY = 4545937caf1878fbacc34ca38a0e5e1f6ad2b25ddd796d06c8d12351\nDigest = cf670c7589b91dac6a131fe2e863e86ee790ca75\nR = bc1db32e437c67439c27db1dc607e3c505210c984bf707a8e87abb70\nS = b760f4943a2397311e54e888a1ad379ad9c45d1fd09b5389ce1a00ee\nInvalid =\n\nCurve = P-224\nX = 8781e5a98950092570d685964e9ed27760fb7dcff8d3b6f3c8f77151\nY = 9207cef64b7c2ed181c57337001f45f1e800e0d1bc8adac296e454b5\nDigest = e5e5e8c8b3f7146c72ef86ca1b75f422181b5729\nR = 79826ae5b0297b9404829df0f02bbb7b8acb35459e13a4045c40f242\nS = 2a629dab19c9e5cd0a551a43851fe6d8409469f86cbcf6204b41e5b5\nInvalid =\n\nCurve = P-224\nX = 03c78c532b8767784fd45e75027abce3371181f8f54914811588cbb2\nY = 166c7b70e98fa11ac361d827557676ec07e553370a462b4fe502dedb\nDigest = 270606c9c9b136ffada9588f15f9786455369422\nR = ff18b493b166d832c9c25ee491525e4c188ff2b804e38b5964941c48\nS = bbf4291db484b4e4143c01a284c03543bbdaa2db1f1c571f1e5a5e2e\nInvalid =\n\nCurve = P-224\nX = 99fab11464484cee96d72dfcf0327d671787a2f6ee32f9b184c48fec\nY = fe8ec3d660cfa3f3e09e5cfc2c3298d4de2f464416deb5b4a27ac062\nDigest = 9c77c796ba619aedef68b2d30b4ba00c4972488b\nR = 714c48c143cb259408c04f77a38d6484e788cb268fc9789d5e871491\nS = 542793d5dbcabcebc83a809cca02b8e95189c93fa4e330d66d5a62ef\nInvalid =\n\nCurve = P-224\nX = 014e8e57388eba32ebdce80df60c481e5c7758374f90a92e0a82f1b9\nY = d1aa8418f992283c5b6bb0461f05dc9103050dc55e0265e1c99b935d\nDigest = 82b45d1fb3bb502c7c20ee1e2d63f2aaa9f492ab\nR = a159b83e80e656f54f614e8437821bd87f6f13264ac8eca1b3ddde29\nS = b77b7bc8cf374f012ee15f9f9224a46a560a5b689cfc92ca4fa03459\nInvalid =\n\nCurve = P-224\nX = e0b9e3cadca81311923d6d6adcfc326b62fac9c4b8d61c5f960c88fa\nY = be505338108f8d3f0ee80aefa304d51dd4a4035477934a98a6111403\nDigest = f4da99fee346e572906e6dc8083a3d0c2e09b773\nR = 8dba585dc3312056a7be61161c7af8ba8b538f0c125c80cf9af2682e\nS = 1b5b1adac4d66c7045f3f79c3aa154a0274c4a994ac7a093e2482eeb\nInvalid =\n\nCurve = P-224\nX = 29197e94a3617e62d9999c859640871a4537a073ca4f12a4c324dcad\nY = fe198969ac7cbe49df2c61c4cc6fa502c2207a7da10acdccec7b1cad\nDigest = 58fab970cb7c1f0dac21b7c7fd67d0ad169688a1\nR = 261670b09afaeee71c590c5658e3f57d859b18a887f70fdeb90e57ea\nS = d1d12c11cf7f4a9dd015ead4bd245793cb37ffee1f4cf109b7b68394\nInvalid =\n\nCurve = P-224\nX = 0fac352c1c444435e6aeb1d60f28ac773b0170ae902afb0944ef0a12\nY = ac3ca693a7c5347a074808b43edea94059e2b1d0571d935fde3f5841\nDigest = 4b69dbfac12f1b974566d8170d1672d0f5fc0506\nR = c33c7a4de313ff856d2f51cd9e3d173bd10668c296f0e6b208c036ef\nS = e562d30822b5cc69713a57ce8c70f83827add85a06c88109505ebf7a\nInvalid =\n\nCurve = P-224\nX = b0d4298e998b7d9d4509322a1ac974c6180956533debafd3d9e7f2fc\nY = 185a64ca840d4b6a2800e72433f26dd523f97daadc18d6d01533f0ad\nDigest = b84805c37e76e530729ddcb59a68ad69d40c82f9\nR = a5155ce53050cbfe84b67d62ce118c6004564087f2fe1cdf44e9c945\nS = b6894b050d77a3ff4d191ddc0c9fc7009a7472e31739949193d7cceb\nInvalid =\n\nCurve = P-224\nX = 59996a4a06658e553fc2993f0f55e3fc8ca2cb52d30f882a37729be4\nY = a5f68f26ea6608fd1f350d8da7c187c7e70f23363177a5aa41508fce\nDigest = ef0a69578d8a1dc930803a7ad2a92c3c19ab6513\nR = 704ef49e0a43c61ef5b325899acb9d12287883a849976c8b9c950634\nS = 73da6e3a26d5c512405fc09fcfdf650dd8da748e6c3dfc05032d7a9f\n\nCurve = P-224\nX = a0cfdfc5a096b0b23ba6748ebaad17e60228b204aebdc01057a7154b\nY = 9f6bd5369d21d88d7b5c3ce221af530fb9a8fb91e751cdb855ff32a6\nDigest = b05f0232e6d44151e249e7b75c7c9ab05c14d44b\nR = d68aa9048e84b8653b8ff3ab31bc73884c6ac7df1fd1bd3c38c16b0d\nS = 38ce58afe5fbc6af892e06a4ddd978c745d5ec700cab825c11dd8fd1\nInvalid =\n\nCurve = P-224\nX = f1eb36b3e1c96a18d87878d5fa8b79d77afce9d2ce40d26199f33482\nY = ae819af474f3efbd62401a407036505c5a2d60449274593865de3374\nDigest = 1dd27c95dd6fb3f080afebdf5a1ad906502e12ab8f64e5f38f67c386\nR = 003122e976bac378c06ec95fd73290b067e7ff022d23493c40663ec9\nS = b99eb4220146a282c7a34f98a9a4fa38ed3f48ca2c7983cde2d3235f\n\nCurve = P-224\nX = 3bdcc7c6112cde3c0522f1a4863f1d7b6727c5bff67598ba2f1bafc1\nY = 47acb6b254e0e8747e0039de471d0dda443cb09a592c678717d83200\nDigest = 19b39292f4e862ed3ee90c35e709587231191632dc8b35611dd24abe\nR = a5aab7768f549f8fe3c7e650154c865b71ea5089bd6303bfdfd19316\nS = ee4989c4b96bcc802464fe44b2adeb1b3506755a3f4fb3f9252bf21b\nInvalid =\n\nCurve = P-224\nX = 6d5bacf458cee3ded627d0ff14fd2aeb54fe1455d6daaf7bb43faeea\nY = caecc8d3967ca1c8889607e9ed975b8a335a17c0acbcfbfed721ee1c\nDigest = 328ab7d2a7c56d09cb72cedaacc23a6da46d5cf984dfdfd16af60964\nR = 80e7024bf30ecddf7a658785ae51cd6e5a23963c89ee96a82346d889\nS = 561252dc8d9280fc54da0046da494fa5e4b7aed213923e8b894a1ae3\nInvalid =\n\nCurve = P-224\nX = 7f9789c729355516588a5c75cb2cbcf85a14c35e14a5d03b4ef920d7\nY = 49e95c49e62dd20f02ed16594f35ebf3415ed50e6efdc0c548101a9d\nDigest = c5bb2d7ca9b37af1f4bb572ae6b6e69e8fcab9ac1cc5a6e1b6d1f8de\nR = 3c7b664413c2a0e4682a9d1c88243a96196fbd03f72cb873b9bee8b9\nS = 8f7f81ee9d3a2660ab1d666bac6cc434143ca9b04ff638ca7b4aa1ea\n\nCurve = P-224\nX = fd3efc7108edbe155adcd8686d8605e811fa79756c7e2dc8c1c04212\nY = 59edea73a4e5f91541fb4cabce539afffa85b6b0113289f049ce60a0\nDigest = 562d1a8fa642dd8bbb4f4801f2d9fc8cf3452be916c0ecd6c8ddc4fc\nR = 4907884b8b7d0eb9a7b24420f69c58e3a17314e101da0280c0ceb130\nS = f7629bed92e5c40f35d7731912fb45a3cee06eab3d409a62997f2282\nInvalid =\n\nCurve = P-224\nX = 8b3f3e31d9c8408a39997455ffe0240fe128a5f1be9b3a33a97b0910\nY = d74ac6ad8de2407887c335bd66f684454dee175a2af713bb334cb3fe\nDigest = b57ffce01c72221c6714e4a38c76746c45a8cc685f37c55a69f6773f\nR = d28ae763c22f50ae9ee9fbe5bab682fd8d820b99ab70677cc46624f7\nS = d9fa54d0300a6ac74936e7a47fbacadcbb4b25ae3a5b550aaf53991f\nInvalid =\n\nCurve = P-224\nX = f4fd02f3d224727e156a2cd7543483f3e35eb65219e32c7923f93ecf\nY = e7aa734828ef326259f98e0e8c3f30b62bd3295c6d1af2c429a087f6\nDigest = 8e70efc206d69d1bd1dce263a29a56030ad5602046bc61848899474d\nR = 9f57e28f69d2ebd96f6d98903156a4e795730e09fb67963771b0a851\nS = 8cfe716488479e04500c8eccdc86fdd54ff00258639f7177169e2030\nInvalid =\n\nCurve = P-224\nX = 0fdb8faf52d8f46229cca1e0f22e869a91bd56eb6dccc547151f9c68\nY = 96c8d1946528bdd2c14c3a0a9c17a088d3f0599752d095ba9de9ffa6\nDigest = db452771046d4b64ba673771b49df905881df9c4b6a1292a11f87515\nR = c53c0ce7d408278552a5fe5854c05641cbe93b1dc18eff1c68af53c1\nS = be7453a12693ce7812fe58746323882bc14eff972480b49431cb10b3\nInvalid =\n\nCurve = P-224\nX = 240431da69703b32ba2ae501d2458b355b66170725806b45996db195\nY = 13beb5198ee00abdcfb2cc5454416d4f7c795e97a14bd93cec3f0a56\nDigest = 3598d7d7b2cd9e482fd3bbebb9ae4549a4b452c81b89f3da6f6f2e85\nR = ad03bdf64e3450407a2a977e1985853d6ea41568c3a394d696de6739\nS = 7b55db9abf2045e2dc7ccfa2e8fb501883c494662d400590c74d100f\nInvalid =\n\nCurve = P-224\nX = 8c80c86f91b1e330f86f5177fdba839e625a27e8531f232efb10a484\nY = a24deab897",
     "8dfe7398f7a1da0633ff7cf5aa7b7365ce2d840ce81c80\nDigest = 44603667b2251cf051cd67b927714d67a25295679d884c4b79099a80\nR = 0c422b292308f31af78b1261d12765cced1cf96a83a6bc3bd90330fc\nS = db34f4462d0bb1927cc99273dc92d3fe654c85a3b53c6d74ed900621\nInvalid =\n\nCurve = P-224\nX = 3a5d1b7ee6749630c9619789b256f6bad5bc4b09950cd53b78d5ef30\nY = e85c7ee707df680eeb5fd78451f7302ae653f96721443826096f62a3\nDigest = 2ed9e7077df2ca2f8a96dfea2127b1b34147fcf963f9d73e8aff9df6\nR = 671ad280609364b0e26c92b13891f677db7c83499d0a3d7b6d80affa\nS = 7c4b9c5a3937d540ed8bd59e340c13f02313445e06b2bf7525f5726a\nInvalid =\n\nCurve = P-224\nX = 350f59509abc9f7f9b35a8b80065258727a8ffc27e6dac635ed68900\nY = 634fceae493b200cc7680297fd940dd86a5111da14bed68c797ef254\nDigest = 012a6edb0064f2b734b0297ab924efcb0e653be9e6ae97c371d59680\nR = 13a302b200555a0e80584e6ede32c0f9c5a199125b219c3e8d0fbf96\nS = 13f1d7b0c87acea6290cd9d36f1820f546f83dd8d7d9abe9da5812a9\nInvalid =\n\nCurve = P-224\nX = 1fdb820003a2fe61deef2b68b92ac711abc76200c534ec3abc99a187\nY = 32f87d0554b6b5e389311fd3c86825fcd42654a0b6f5d4d5ba73031b\nDigest = 2afe40d5042eb4020b14053e9ead6774d566e0b536912b7de4450090\nR = c03e551abcb12eadbc291b2d5fdd53bf725b785933e0766969f0355e\nS = 94826a8753cb949e0199be3220b4f90318f1c835cdd67efc50df7fbd\n\nCurve = P-224\nX = 208dcc6c87e7c38bd914bc9b350602ff62ac62fa4fd633c1af5b8cd7\nY = 0263587c7692c8be1f78de88ed6dc99ce1198ecc53a77ae6cf98a323\nDigest = 3f95e73294defecfc125a2dbbf322d31f323c030adf244c07a7c8746\nR = c12d3b396e1a894dfe4a28971ce4983547596879956504e1a3aed75c\nS = 067b729ca23be6cd520fbe9b972b9bb3d00c9ee96832a5c35e20e0e0\nInvalid =\n\nCurve = P-224\nX = a66a652fa36413dccd72c83febedda051182dc5758a1466366197f5f\nY = dc813a79e0fc647d8892dcf4f2132c90914a520cbbad65f458ee0fae\nDigest = 8a8942761ccd4ac7c88c4afcb6bc69d431cc3d10e6ad7a2b8610892f\nR = 809d1b4557eaf36b6eab3449dad56e61d572bd8b63d51b63af1b0bc6\nS = 8bf88226a463606ab57c27ed78f1b71ccd61732fa58b62ee845fd3dd\nInvalid =\n\nCurve = P-224\nX = 8856fb8b81a4eacd971a954560018f33cbb71cc1fc243d03f63cabcb\nY = 28afa26baf31b4d89de1dadd2289006f836f23a11383817ec7e4e799\nDigest = d8454640ad1f4632cc667823418ae56c62028825d727adfc84afdb0842b0c9a4\nR = efccef331805e71bbf876cbbc2342a6bc4508aea7c691029c8396aef\nS = bed544d09e28dbf01a30b2cfb61b98ad6201a9818f22b4f543f3e7f5\nInvalid =\n\nCurve = P-224\nX = 34c5ff3de565b85bfdd9f0a8b3fb0d46f924c57b276bcc830a1ed580\nY = 609d22200ef38b410da77f7a8ff2f58448188042978fd9ae1b2b4477\nDigest = 831979405db4eb9dadf01249fa15f68d4846e0ece70a320d3022f75f3dc281cc\nR = f0138024fe0516738f3bd0e0fec10defaca8c3b89c161a77489cf2b7\nS = 4ae0934266d9e3d64c2a12f546b132ba0f33ef50abc90e7ef5974805\n\nCurve = P-224\nX = 465afb14f4bf85022ac1f635f46c0b2f6548bace9352d32f74eab012\nY = 036371a3246dbf1069d2d268ca431553d1f2bf0181225145881b7be0\nDigest = 489cd3c10d94f7f284bc4ea472634a5d7f0d280d5abbf139c110ef80c8bf463f\nR = 9bcd57a2fec2518903e4b13dc0a7b84bafed5c4908546e94ffae87ed\nS = a337e06582f6b3973df38b93a0fb2a63f7774b62db50dba557e5cfcc\nInvalid =\n\nCurve = P-224\nX = b8b7f923c05ec95ebd484db7c58d219cfd26ee6b66149631f25ffe4c\nY = 6bda5f4f988784555a80b5494eca51ad2c7f88ce94d2090ee0c76fba\nDigest = b100feed0121d9d0471e5bd94a659510c2f84e313f476431deac17ca6d87bd79\nR = ce4d86bf5a7543d1cba8e4470a297e9a48d0096d7788c6284b1c0af3\nS = 229eb0636ee62508ce3719396d7577ed892cec70a66857fdee0d1fa0\nInvalid =\n\nCurve = P-224\nX = 13e84ec2eb993818d7d78330855ee2fbe8ddb548a5e4198e2087b3b2\nY = c95dff249e10c506fb547a92ade53c61ddbb667c760e4127a1a7f806\nDigest = 21a9f65d4cdcc287e0bf330e4f76f1168d16d0cea796dd6c0e13cd2837decaf1\nR = ed26f00ed696e114305c546ed04db5fc35efa43059c0d8bbcd418d0c\nS = 6e16efbe9501e3055d74966a49232cd76b5d1241468788b4cc7378b4\nInvalid =\n\nCurve = P-224\nX = 16c23c93699cf665a5da8b2d4baa72c36158d3433b1b945e47204b0d\nY = 12023703e1b59ec9054ff22d15567b9f74058b47cc13f2ca08ab77c1\nDigest = d62496d0ee0453e7f13f8d9c57adcd33442a5365f626381ed665f95f528aa198\nR = ada849b673a1bd2949a8b4d8fdfc239ec53524a356d37da3c9d17ae2\nS = 698de3a3d8697c2e8e5b2c85fceb8796750c5b44154f01ce86d99e24\nInvalid =\n\nCurve = P-224\nX = a580f9a0cd15abff8e1e712f16b0fd4142d0d773af3c657abc06c2a6\nY = 22c6286340dc072e64274209eda60503047700571caee64b4a2306c2\nDigest = 25ef291dd6a2047ea193f8aedd3f4692f2c135cb519922a17cba3e969423b030\nR = c6fae06274dc052e482102520b49d4ccc4cb7eb8a3ea41bd3680ddad\nS = 50d66b75a2bbd0468be1f9e61bfda85b6329505b0134d60846cbe4b7\n\nCurve = P-224\nX = 0b4fb6fe5f6cf6adc7d28683628d4b9c569d21d2397533f5bd121a23\nY = b44d60a3414b9b7b6e4ad735ce2f9cb05593b0874ada5e65acdead4c\nDigest = 7d53ebba0424c4b6731806407f97af4af863a5a87c759626830c9e8753ca50fe\nR = ab5ac2039b49690c6436793decb1a6a58ac34833a8091005312a93a7\nS = 98fe955cd836501cef78c7a05fa27edf2fb3afea80990028ff64e984\nInvalid =\n\nCurve = P-224\nX = bae2b3634c7854c932551ece8dced2139a51705059503881a9239c78\nY = 094d5e455bc9296202618d7022512b0f9ce53d796c7294e6eb076a29\nDigest = bb5c0917ec5376b2c685f3a530a9f8ef1ef1c1b398ab66f479d936cd662efc1b\nR = 2fbdc7e9e98aed5dbbcc5b034e17a95209e2fe1b01515426b8b372c3\nS = f2b19226528f10be6ef0d27ec3703db690261206b7e42f93a691192e\nInvalid =\n\nCurve = P-224\nX = 49d9ff4f4bbd4320b6806a7fbaaedd962283c766a6c130e4b62139dc\nY = 06dbe8e7fb8fccf9758101ae46939c6fd4d3afc526ba6c8156c6b013\nDigest = 9a113d3d73543e17faba847981e0b7fbc5647e547bfc989921ddc987133692d1\nR = 2d83aa59bcfc8a0237884826e08dbd78a56733598e379f2a9d51e9e2\nS = 485036c74618d0e665775fbe2d614a313c550f9826b955d3e5636fd1\nInvalid =\n\nCurve = P-224\nX = 78451cca49655978b65d8ddd45ff367c47f321f5d55ddac7969ab82b\nY = 25b77f820aa9ec93ec89d7fc84285f3f3deed496e0cd3fb9ee4a5c99\nDigest = 352afd36279bee1ef5727c55c7428bb79db949a9f1953eb98cfd38c4a4a458af\nR = 998789490e008ed11febdfe2981a55c733eb9739d7f37fd5c2a7ec96\nS = c3ec8afade81860ff23cc1e7d759d32d9a5775886ef17bfb719df4aa\nInvalid =\n\nCurve = P-224\nX = 18ced60b7fd9ebf76c3aa5976dcbdef40bd3e36033c013553043dd84\nY = 30398582dbd2004064f8055e7fe0fe8df11b2c9d9e2931ad12d09628\nDigest = a1e3668af6307f6a2b7414079e73308ee0836b588b92a48bd5baa9a62f45b0f8\nR = f880143960e812464810c175001b5d39592fe63aab544deb9ca301a0\nS = 1e0657df071a25dd791264b411c8964688f4fe17ce024e659836ebe1\nInvalid =\n\nCurve = P-224\nX = 5d67c1fca848ba7f3d9de5b1894d3993ac4ebe68cdb0b49553b3b0e9\nY = 07c219a8323273c81f5694306d0dd1d133a49efce5003bc90f05578f\nDigest = e8f714f901cd2390c66f9fa9cb81ecc5f17a82bd934cf19c5ce2bcbd3a985de9\nR = 767cb6b2efa7a40739830659b0cc24fe3de771d00104b3dcc0f640bc\nS = f2e7268bc011d79d33f3551d2edd3c95f324955479b8e29e8aba629b\n\nCurve = P-224\nX = eac72b399cb791b3ed25cb0a49eb157e69603197e0327eac5448680d\nY = bdab3a2270066e74e8210eed7b5d43fba1e26845b6c037a8a7e2a13b\nDigest = 74aa7c8f25644514582fa904cea1ea88a0b262ffca43cdf6536ad97d8550616e\nR = 55485947e9e3c194a29c8ecaddb18eefd16fb6919aeb0bbbd8c12369\nS = 6309a2cc7fdd9eccb32b86d5577aa54ada79899a9645f2e299630d31\nInvalid =\n\nCurve = P-224\nX = 17f741267bf3e8143046707d41eafc9555953fe5f57d6c035452b232\nY = c667554d9a55fc8ab1062203dcbcd2bf9769c696a295350cb28aa01a\nDigest = 3b997a1c220593cab4301e07886db745436911b8abfd9d1b03cc12e1c7fa4510\nR = 57408bfcc68e60ad000eddbfe6eccbe5f87b98c95de0e0a2e065da92\nS = 51249bddc149f0942be001b2f3d6f6d17a0cc36fefce147058944667\nInvalid =\n\nCurve = P-224\nX = 3297edac34cb802df263f8d366f62a8b746c316adfb1c84a1c79c58c\nY = 79fe82e87ef5879c12eda6adda198a662fd77afa6a1fb5696cb7da9d\nDigest = e71dc3ab7ce73995d053bc6361bbb3f20e39ec2f295d97fa2bd229ed31a56dde6bf2c9cf6b0a9cc7e65962c57f3662a3\nR = 9993defdcf83965723c03e04ce6c33b3972cef3c449cdf1bc69990db\nS = 553b22a4164549f16aa1a928eee74548fc141fd3c16f213318965974\n\nCurve = P-224\nX = 2bc010527ea7427cedd213aeccf0c62dc513785888c6373740139d8b\nY = 2e9eb7ddf027ff7678ca880511be147098b34d8e77acb4389fbc6e50\nDigest = 781195b6396344146fe8b73a2526b4b1c981d26b9adcce0123176be1239f798c847495fd714661d1ba8e41f2ccfd052b\nR = 70a7cb04295a53b4a3a695ccb5d87856fe9152fce11987d4c43207bd\nS = 49f4094368f2de9327ca2913ef940e17c5801e8f589413838831083f\nInvalid =\n\nCurve = P-224\nX = 55c6217adbefff6e21bfb5d1b75213ce7b20c900d514ee094f27ad0d\nY = a68ae9f86eb9c10de3e7d9b03868518f33f571f85c3529d2902575d3\nDigest = a318b24bbb5ba46e6656f8ad68201c024e7b3b3849d6a70f3abce8c20f5b98ae43a326f5f48994045f0ff27098837b5b\nR = c073fba87267b45853e693910c1de791908ca7a25c1716ec2d3cec71\nS = 6138c86daf1021ae4af0faaf0abd5958f93944d5b0d82c40214bacca\nInvalid =\n\nCurve = P-224\nX = 4d0cab0dae88fa0cf53a2a6562934e0cf",
     "0271cc7fe54a30109a232be\nY = 70835833cf9e1f989a18d419e7bee9eb5cef1fd145cf62c4411c372c\nDigest = 6abbf2557f2e9b4e020126f4a87fb0262a1ec59bd3b569581048c5692f8a1cd381ee9c3cf195fa1a362a87ab604d79b3\nR = 3b8548eab4dc123e236133d826f2badbde96f92249f456e33ccc9739\nS = c82b2e41b9e2b21594cc03b1c0de216f183403c6025e18bb29bff421\n\nCurve = P-224\nX = f55a53b818b3ec4b4402a2c63429c1d78f2cd0d8d202e33812878a03\nY = 5a2b1a00615c56b4313828bd70526b12f402df1d40fa4900c994af8b\nDigest = da8d2571bea9840494a41f03c6c357410de030a7b5c023a0487020bb5b7c45fb6c5ed0e3dc66e4c0ab8460d9bda68c94\nR = fa934f9fdb765fabb5693ccb1de4177f172a8de108805a48f4bb989c\nS = 12994f2a26252742667044a01b509b0f315e8141629f760267b850e1\nInvalid =\n\nCurve = P-224\nX = 40a5c52dda7de858a2c17d12856c552ab820023336b9b4fc196bcd67\nY = 301e5368f59c00f15e6f3a91510444fb75a4ead8efb0778b4419e7db\nDigest = 0f88ea2d9dd40c19cd31c7a7cff71379431c9dc0a3092041a5fcbd2c20a05a8cb6e5a8aa143f1dfa169d2eaf87d01e26\nR = 0fd8773fac425a2761b954c946020615336d3e350ae40743641917fe\nS = d59f2b806ccecc444f9387f511c7f9926fe7f045c0ea633a51b7db47\nInvalid =\n\nCurve = P-224\nX = 372a134eec0dae3322de8836b89dde11a69e0379a60b10343abd478c\nY = 65921970ca8cf5a75f044db0e29802afe1726d18b3e07b61c768c242\nDigest = 1547d49d33566f8c05f68b9a980e113f919bbdef8d6d53046456a2c2ebe27ad86eaa52d05677fadd5ccc3e84b04c0f94\nR = be6474845a42fd4e85b91238f1e3ba11cc88e216d295c1b07d855987\nS = 2724242ffb5775f614ee06eaa4c985358f64869ce4ae4bfb16b5271d\nInvalid =\n\nCurve = P-224\nX = 9ad2cee0d92b00b11157a18fcd752f43e772ede7a46475a50e7ad8d2\nY = a6edfae6c5589dc0db6353b8655fe3b0f7dab2aa8400cbbd72d1a572\nDigest = 60942be3ff8d2370481b04fa07743482e08a61d3724010d7edd49bcf12e1463ae059696c825ac0505f079625b95310a1\nR = c31a40b6c245572457a19efac0da0db22b2a0818de716b6fdc5bdb32\nS = ed8204de94f1d92ae3fa6e10c727eea38d0e12b58133fda1a15559bb\nInvalid =\n\nCurve = P-224\nX = ed071a20d76f81c776875f8d3307841d33b70523ea40abd691d55d21\nY = 34ca47d8ba0a984d0d728c4d8c6b9aacdded03c6070616680aac162c\nDigest = e0776a80c616b8e596bacb0391a19956b2f0e2c566c50dd2ba99f9e59ff3dfa6197622c2a64cb4d02780a39c68d249e0\nR = c7a5dce4733a81bd738e0a6e0667dc1fade86db119e7f3cde57d6dc6\nS = dfb7f43343941cce331be27047b131617910f68393630fa53d137df4\nInvalid =\n\nCurve = P-224\nX = f51097e1e4b4f3b32e92fded0b4c8b7240a62731292e615a4cae0dcf\nY = 0549003f18e67076bc68110a75252072fc29b6d4a336d152dac2c3d1\nDigest = 48803bce00fe101650dcc83b290c49a524b21422f1f6a3aaa6e2f201863ffc355346d167dcb0ac552007a46cf8d6e4ad\nR = 6875a118dbf586a51af2212d5f32908c9f31110e9e9a7e4cdf7494c5\nS = 1542ab4260459e82070bbad405193a1894ce717af158daf1d096bc01\nInvalid =\n\nCurve = P-224\nX = 5255e4fdc816044389e9c6f5e09b85aedbe1c85b1cf9b7190ef7c2cc\nY = 683c8cb6f31e4cc1e2a5361eb47e305d5d8bfeaf94e261a341aedde6\nDigest = 995229c018cd0ea061672c46ec30c99693fff1cad491b13b4093df0154872adf946644dee6192657b436931c30b7af9d\nR = f1b0f8a3fbf7d4de19cc1d3b4c525c31bd97c2e2a94eb8a27c7c197d\nS = 936d3f49a9aa58935cfe227b22db83314ffadcc4751c8e26853d8cd0\nInvalid =\n\nCurve = P-224\nX = 7cdaf519f6b1254cb8da4668a2dd2015857ceec17f838c15d7d34b27\nY = e29f80fa4f830af7737126d4454b6498905e2c633fa61ad6acb30823\nDigest = c7d8d1f060287ec402092be54ca6e06895e91f9d0c29010124c0d9bd54007d8039b7328ec7b3a29e1d5d4d8fb78807e4\nR = e640f3e676a11007e73efd00b23087adefc9b9407ae8b79b47c397f3\nS = 66b7860a0ca35c2f1c65d50f99def9f2bfc0a6cad2008dcc38d6b3d7\nInvalid =\n\nCurve = P-224\nX = ca1a04f08708ae714b7dfb3db509970d30b7e01be7fd6181613894a7\nY = 1d90a2fcda7dd6ce8b207eef48340e58cd439a3ce17658f6f82be778\nDigest = 1f710f925826bc33c0da91798cb7d7d0700883da685a1fb9503179f0a06b589bf92eb4b67496faf21cd74c8e3d560d77\nR = 9e810ec2a0bc205df6a75bd6410e0c8ea1c738e71af060e2eb271aa6\nS = 9d05eeb46258c468b0398cb6e421149bbea5ed936be3fde3380111cb\nInvalid =\n\nCurve = P-224\nX = 558c323d8259e055a025fbbe6ba8b525b02f32caddfd31e5b08219d4\nY = e1d6398b1c47132632cd3f3fae14fc3ee3092faa619074fd951a5870\nDigest = 4b662138833a976051b20ddfb02e67339715b77046bedeb1e30b9dccbcd84204e76da722bb3bd020fbbe33a182792e0f\nR = 05d8b0bcedf287a4740bfc548570b1c1fff71058e0a9d88476bbb6a1\nS = 769321d50e34939e622a727855501e25a7ad44ec979985e7389aa3f9\nInvalid =\n\nCurve = P-224\nX = 9237e61ad9ffafc61cc1c72b6d2f96d69b588c8feee4074359f694f7\nY = db25a18f1eee72734c640313f5c6c0441358611406cc62619113b4ba\nDigest = 4e7bbf78843a767536977b240e9d1516c73c0fa19bc91448280fd85361b06fdd11ee413f956ca4ea3d67c0e325a1d53a\nR = a58225b10080dab26644f10d8a817ffc4ed4535011729491b6ad5d00\nS = ddbc010e295882e0731ff240f15ed82fa3e81b7552c690cc5b40be03\n\nCurve = P-224\nX = ea7efb9a7e7bf693dc0249504ead70dd422ec86806cd649ed57a7ffe\nY = 33dfb17b1cb244279990019286ab477a2aff2b55c08959deed0b1a28\nDigest = 330f78db9f217f95d99cbcb5414a32523025b85c87ed5aaa3a5e6b006c53cecbbd446166bb9b98e944626332c3266e82356e72110bdbf7df2431b8e7faf59e45\nR = deab574de1f971419b7ba9e169866c3a6233fc627c13dc6a8cb88bdc\nS = 8d4c542bb0046da1b3912652a2c84542668cd89920808785d04e4352\nInvalid =\n\nCurve = P-224\nX = 6fce4d789b1240f2ab1c23051aa03e219da99943a18864e7876d4d11\nY = 3e84a6bddea4a28cf8151ae73aa7b1964c37e654241353a9fa723f67\nDigest = 0088e4cbf3eddb6eaf108fd3937c439684ff8fe5595f2032948423a2a15811b34b0def245bed3b4b4ca90d3f497f3aaa2577a7154d22d7254dfc4755eb9b7b17\nR = 2d1b4f1ccaebc0a929598b650ee364abfd6091a542ba426886d75f38\nS = 44f3d7afe84ae33ab5f9426dfc85248ebc7e0df434d35980ddec75e0\nInvalid =\n\nCurve = P-224\nX = 72013dd6f5b1eb709b3b7da234987f9a36c6f0b095620b8c31f02381\nY = 319d54c719b59d91900b3c20d963ddf1a10d80d6601ac155094b075a\nDigest = 3cba2980faf5579c7ddbeb31c3318a162a882129a1efe1fc9acc3219a617c460701f22fd7a5c46b017bd9ec9c40587127319ea14b148d2be4df9875d5bef6e4e\nR = eb38db9b757b3cf04020f09188c789bf0258cd0467cf7d67368e8703\nS = 7664e85f01e67881712b24083f89e838c8b818de4d665494e7016833\nInvalid =\n\nCurve = P-224\nX = c6a65011926eb64e02bf472d5ba37841d49cfb7f17a20fb9f59355de\nY = 386ccb33d944fd7be6b8531863d2b6200cd602d300d7e7681537e53f\nDigest = eaa81b1236121db12f2036611eb6d3e5386f5733125fb26844cb4188109aae402525fc63bcd73494c36c170d1934b108739d79b0c4f184bd85ffce93b1beecde\nR = 9e7c637a699dd52512faea847079f0ad41b20cd7a5461c36d01e857e\nS = dec6e9ef361de3f6ec7d87de3129eaac5fd0b43b5f7f58ce46c29173\n\nCurve = P-224\nX = 5bcdbaeb2f6c57e8a9dffe94804e74daaf9db8452d13c6a8bc2a4966\nY = a564072356c5d86200e979291a19d5e73d8bcb701cf84d9012824bf6\nDigest = 4a5de84f304f0c83365ae4213fee71c0944d8580f9d8e7455fc961e9f98bf3d51b7fc20aa44e36c0bdaa09e365767742e9bd8bc868d5c6cd8e1cd2ce2968e3dc\nR = c58436fb77aaa4468dee284e1220141ce9ff4426f75daadf5a898a6f\nS = 87aeee1229a50921d8e77e7e3478061f5c051097defb104a0455ed81\nInvalid =\n\nCurve = P-224\nX = 6c6a7deef8b3dee2eaa98d8ec877dddb460365968e63ffe5c249a421\nY = 1ad1715797b5e47c4be24d7ecb8141f1772344a2f643cc66fbcf3f9d\nDigest = f59946dd73887a1fb945ae3e5b44b574512e36dd7d35925b0bdc3a3f69a88e50dc6ebaaac86092679961a99d7ba5724363c5886e7c2cd566433c5a9d59e2515d\nR = f778faa2dc2cee7de2af0bbc4339239dc240907e59ac034464ce986b\nS = 2ac929588a8dc8785808c9d4366bd7b1a81e0fc5be0c63e62344c251\nInvalid =\n\nCurve = P-224\nX = 0ee33a134feae6ee1488bf10edf7cf7c318a2d709080a24818619b91\nY = d7d39536e42652baf55159847f475ded075385a3c1af5c3dcb17ee6a\nDigest = 00fc4992514c1053eee7facc5199161a2b0f69dad2770326371ba42c2c12ffdb4ff6bd86fc440dc8dc1354dad42ff0c2a055b61137532a62521b0f3508ebe611\nR = 34bd0407f80cb6fc759036e6d4522eb6da94874c92ce0f02d8f5f2ad\nS = 3a2dd970050ff990162e5702b06905d03e3c7bb2771050de6d84eece\nInvalid =\n\nCurve = P-224\nX = 31d3c62a4305c37a15e9102072e287a8e0ac027f9189cb9d87ecbea2\nY = 26449ca391af6a2a9f8daaa036f2c9044b336773ee48bcbd9cad59f0\nDigest = dfafbf96b70ead7e91dbf48b8efd062bf2bc0aac6d3e90a7fdf61aac13a74b304bcd0d0c23c88df269d45bdd31d50f0fccfc0324698af4dbcffef04ca05a119e\nR = dc33e8f7b52f584aa3f091aba10c2a9a23be6835e1551092652e1bbc\nS = ae84a6d19f6bad3f9886930c0a1406016fae813673db1516b31b638c\nInvalid =\n\nCurve = P-224\nX = a6e4470712df583d0c795237ff46c9df5718ba2aa24139a2d99721b4\nY = 9edb403a8c10807e8736af665dbcf6052bd4b43bcdc8b9eb8d4394fd\nDigest = 36cd6716cbb8b7f96df4617143be7b74f42bc94e468e79e6658d00b092e24d6de82f207693427fb439dd13bcf49665cac343ea35a79b5963cb21273094ce28fd\nR = 4e9ba5bc4f4fc4e507c1e5cbd0d688da4237385b16ff06601436d8ab\nS = 4e0450a57d802d0ea7b0fb57eb162267195bc4248a831a0ee8b0380d\nInvalid =\n\nCurve = P-224\nX = 350fa782e1cf7254b18cde30683e54edf2c1b4782525fd081bed5920\nY = a77de5b4139ff63e108b6fbd3a7e6c0",
@@ -2564,15 +2584,15 @@
     "6c8acb8ed9136b1c5adf6f11bfb5f3dd8bb1e208ca8329a0aff9bf286e3be90e4d61d5147bcaf2293f934862cca6aead51d6e0a083093\nY = 01963e84a2f06a9cb273a424ee5fa1ae5900fef348371cc91c99323f58bbcd8742a4495a4f7ef52677501a4d5d663658c1f6c8f6edef8b7880e6894ff9e52bb617da\nDigest = c55e6d3091b6eb8f48794749ae0c7e9394ca3cb7b083ad65177f8f8db938a76ed6d3c1286a3d51b333c74d1c0f8032b7\nR = 012fc3e0c18c4edbcda4f82b5136c893a6307c3f60affa15d0d99fc0e4a3576b7daefa363b3a362014d14f631c35619f6861bdff9a7b503825bf9f027fcb9a31fd8a\nS = 01a138d6b02fd2a7ba45f7f952b2f329ba6a8e25697379330dddd91d1d6e865d3df1541bc4717d3e09b10a57cf38dcef587ac31b4a8abedef43e4f6cdf6ec3f49eea\nInvalid =\n\nCurve = P-521\nX = 01efc81c1efc7a9bc36ed49a5ef6fa1ba641360fa5c0f96cc1e4a3f4d973c95e86935d979fc2101370777637ab210a56fc4173a50a758725d60e9f925f2066d2bc00\nY = 0108225fc94ab33c74aff785dcc68c45cfc3cbbdfa3481fd2a3f97308be671fb32fc8d268c129d97f140210def188dceecc9d712ac397793dbc39c5cac332671ec54\nDigest = 5fe56235e4684bd7419e321db508565d30cd351086ef67d943aa5b932f93efdce875be295920ce5210b7d3f092f401e6\nR = 00480c48a24e7a7ef832547d107769254fcdb4e7982d0e6abd16822837fd4f3b66d81e1d4a018606881abebd220ed8ca865d7e00499ac9651a98c65502baebf34a98\nS = 00ccd22d1b44a1701c99f662535aea9abff7e27f73628101f42708737db8b07effdc2b0b05d4ef233c5910b6261ae9d9c540115f27d2af766c0494c33d31bd56b3db\nInvalid =\n\nCurve = P-521\nX = 00a15c8040f94235b8b444f7a74ca293ed1b718449911eefbdb74332687850a644395394c690aa98e8064f6eca600fc3f659208c0f8a21a1e7113bed0c6e00e3176e\nY = 004bebea7037b731d175043dec3630b2ee85c680a81256921a89407c14507c10ac043deb5d474602211ad58cb569a8b805686bdac3ef7ff62a4d25b27200706b603d\nDigest = d27a626bc9154bfc85b03724329b8a06454d5dc005997bd565f64a80134c865e73a2e123d2b433927efcbdfa3eafa827\nR = 00c1a70919025aceb29dbabdfc2a43715192cc60fc3d1ceababb40f91e3110b2cdd8f6e9c1bafe7415a26fa4179f8fc261b143ddb094fe61117afb13adae9db8943d\nS = 00197d7f87aea8d6ccd2178614b147b290ec780c8075f8439137803c0e9a589e415d84fa23f5f31d61c1674f87142d4ba4f8473fc92d7715c281dcf3f1ee5c2f1390\n\nCurve = P-521\nX = 012a593f568ca2571e543e00066ecd3a3272a57e1c94fe311e5df96afc1b792e5862720fc730e62052bbf3e118d3a078f0144fc00c9d8baaaa8298ff63981d09d911\nY = 017cea5ae75a74100ee03cdf2468393eef55ddabfe8fd5718e88903eb9fd241e8cbf9c68ae16f4a1db26c6352afcb1894a9812da6d32cb862021c86cd8aa483afc26\nDigest = 7679eaaf0495725fa99c51a2dd0c35c8882b840e1c2340ba793013b1e2567471cba35c0dd6247cc2c2ca14f6556912a5687023fb2f0ee02114393bed4c598742\nR = 01aac7692baf3aa94a97907307010895efc1337cdd686f9ef2fd8404796a74701e55b03ceef41f3e6f50a0eeea11869c4789a3e8ab5b77324961d081e1a3377ccc91\nS = 0009c1e7d93d056b5a97759458d58c49134a45071854b8a6b8272f9fe7e78e1f3d8097e8a6e731f7ab4851eb26d5aa4fdadba6296dc7af835fe3d1b6dba4b031d5f3\nInvalid =\n\nCurve = P-521\nX = 01d6aef44370325a8a5882f4667c21172cdc8fa41d712562883ececff53883ac8ee276124e825088c79d6c9d96323cb7b8c0b7ea44d3f0026e2538f4b62d785bb1af\nY = 0027203959a6e944b91fe6306debe74dc5dde9831fd0ec27e8be2d0b56807d63151b15f6495b8632e919e1e6b015f5ae5f2b6fb8cf75b5f848f00cf4ee457cebed3a\nDigest = b99c410653ce928e365d3613331b5df067020e92f634696279d5cee80f1f4a82f7d976a059e318b36eb25314b56f8765a81070d0944f4c86e8407d9c3e2aa7da\nR = 004417ff74889dde6bb1820b5d13da5c81dcf9b0723ee89bb1ff0d3faa90d497685709f315b2cbe55481dee43ebb6d25b1501ae69494dd69e7bffb72f987d1573b93\nS = 00fd7aa027c665458c7ac11d54d4f32cb4a1e727b499ce27b08d3d647c636cc3222a4f0a6057732249ddc22574d7cb80c3769c3ea9de3d33db3edd8ea90cb3f8dc8a\nInvalid =\n\nCurve = P-521\nX = 0153eb2be05438e5c1effb41b413efc2843b927cbf19f0bc9cc14b693eee26394a0d8880dc946a06656bcd09871544a5f15c7a1fa68e00cdc728c7cfb9c448034867\nY = 0143ae8eecbce8fcf6b16e6159b2970a9ceb32c17c1d878c09317311b7519ed5ece3374e7929f338ddd0ec0522d81f2fa4fa47033ef0c0872dc049bb89233eef9bc1\nDigest = 97ff5a81fc88f7ddd3bc58154ffd2695912fe50ce7c63b62bd798fb673c6aa49f54bc7301fb7bddc6edc51b7e0d0b4dec9f80851fff02a33671ad9a406bbabe5\nR = 00dd633947446d0d51a96a0173c01125858abb2bece670af922a92dedcec067136c1fa92e5fa73d7116ac9c1a42b9cb642e4ac19310b049e48c53011ffc6e7461c36\nS = 00efbdc6a414bb8d663bb5cdb7c586bccfe7589049076f98cee82cdb5d203fddb2e0ffb77954959dfa5ed0de850e42a86f5a63c5a6592e9b9b8bd1b40557b9cd0cc0\n\nCurve = P-521\nX = 01184b27a48e223891cbd1f4a0255747d078f82768157e5adcc8e78355a2ff17d8363dfa39bcdb48e2fae759ea3bd6a8909ce1b2e7c20653915b7cd7b94d8f110349\nY = 003bd6e273ee4278743f1bb71ff7aefe1f2c52954d674c96f268f3985e69727f22adbe31e0dbe01da91e3e6d19baf8efa4dcb4d1cacd06a8efe1b617bd681839e6b9\nDigest = ee21776d7174103b7fb65f03fd5d78744d2706c6726ece81e3943cf90f60fad6d8978af6cae9bc059aee2412ef86d0600694447a10b9d21079b9ca77500634a9\nR = 004c1d88d03878f967133eb56714945d3c89c3200fad08bd2d3b930190246bf8d43e453643c94fdab9c646c5a11271c800d5df25c11927c000263e785251d62acd59\nS = 012e31766af5c605a1a67834702052e7e56bbd9e2381163a9bf16b579912a98bebabb70587da58bec621c1e779a8a21c193dda0785018fd58034f9a6ac3e297e3790\nInvalid =\n\nCurve = P-521\nX = 01d9020b8e6717254eebe619d46dd5a9dda7ba5491a7d1b6820fba888e236fafd71179200437f4d61284fb5a3dfbada66bac3e6909ccbeee03c2b93a8bebe41a73f4\nY = 0048a5f09174fda12704acdd8ed560695dec42864b6300a030768a0be7f09d25f82d7b126125e41417a145641937807ed8d1af7a53f5bc3fc3c57427d755dcce3e25\nDigest = cc4e8efb1e9061500bd2dcc5233c2bfa3d3bd89067c26cfee4fff4a5a7c9c9b15151aec1fa91e78b67cfe3efd966ce65681dd3daf36b887d844033a473be592d\nR = 0092df2dcb457fc7578eaacc98ffd73ade07d764e9553506f3dc958cdb3f65d37665528cb2f5f8bded0db0a57e6fa73bfad1aaf94718379d1655db4f32d4c505a785\nS = 010e0c31479c2b29dc2726fe9f75b397d9e37a17619e96bc631c62e9ece71f05b199804cc803940d43ddee41171dd7787668c7db05049dd5b63e4f63562aa700ca81\nInvalid =\n\nCurve = P-521\nX = 0007067d2cf7b7619b9fcff2c898246ae0950439b8bab92d809624970eda18456cb99953ce1ae45ee5d36ef02fcd5caa4d951de8581f0c21e572caad56d6dce60da3\nY = 01913c59007a309005f226b6a30122828d60b4d0390359e1977f88b5347dacf2056dd362648e8b1d6fc038a3bd3fde6f1140c740efa9075ab8b4a64b334c5cd43f09\nDigest = 996010910456dee59309f1631f30e3dbf7ac2da7d5d7f69223c8a18f491cb18f7e11d0ca09352b715354a071e6d392a8c1dc0751569bdfcf36c158c8b07a5ba6\nR = 012aa4a532c108aa3cfb1753f95ca626bb72bd96a423d727656d4ebdc3f406d6cc6c44d3718f9abae8a0b46be9b57f8fd3a540326b63d0d4a8a93165715920437787\nS = 001badaf38e16efd75915f4806f054d40abd2d11e402039bd48c832f66cbfd145e4dac93357d476b7e608d7b75a017374ae76eee86c505f2cc16eaa19075827ccd60\nInvalid =\n\nCurve = P-521\nX = 00365388d9589c18ae608124b4cf746ff488183a912e07d26b6e867c5defb552a5a0df5a16b6342014dd1b0b6760072bcd60045d6a9a514fc74d16047c2e8765636d\nY = 01a5319b26fd555f2a12e557418f6aa65a3461aeaea5c0c6d8698ceaa5495eed7a7d2fed0b76e77b5be11834f36e413d5288e47231c0eb0e9007d4b042bb7a1b6014\nDigest = f8e150be2f657c8266fadc9bdb04648fc5a51f3c3f7521022aaf58d24165f8af4ad66319d8aa2dab48fe8a2f773c8d0e6c8c4f732e0fdfbae4b91918530c1f91\nR = 01d9ef377063a592cf81e27815a2c20789ff9b60f7f125e618b52d90b35abdd41cd7f437cfad337953ab0314fe8e79a2f2d27fa08597d4b28313358f714a737321fb\nS = 00f01d4f150e0a174674a6a61a58a4ba781406024f6dd1b5252e04807b8a807a4ff8d52883eaa258286e506ef4b04ca890e6f81a79ed9a0cd5ed585094fea0bc5c43\n\nCurve = P-521\nX = 00fd0cac24aeb75ca50c50a72340256b43649050e0fa155f72342877bf49c3d57ac2b51b828385ee6aea94bae38587e63390f5ef4ac5540a9e6fc6f1c1e79b524693\nY = 0107b227bdd307efd7a8d4034f733d150c41601215e76eea2bac62ad2427dff52f75f46da3d5fe31bfaedf071d2a8bb5e3c82bf6c84ecdf89ca233c92d599d376309\nDigest = d0d8c24bc5b6f34bf35b08f25dc2d6ebcd36b565f96bee9c1b47030428f10c3ad2904de19247b29650690c08517404e8ca55f366ab176e5089a4c9c661f90eb2\nR = 01c00196aa5dcbc4c4404fa76504a5eacbc96aa66c3ba531a3a679f3fb675ce58f863e08b0d2bdeae74d96ad93a39a78ed4bb3749e26567d0ca5c48a71079925b617\nS = 00f1188eba4f0943f4003ddad6a54606c13af26014db2eb8e60534fad3dae8f07c021cea0990987f1e02dce03fe53360472c3dee3c305bb3ef4b0b53ea6625bf152a\nInvalid =\n\nCurve = P-521\nX = 0104a96beea09d88ea6789a9925880c8a9ece8d764be931675640c1bf847ac8e7a8b14f408ba6722c2bf6295db9132d6ad2fe287fa6e6855f7c58ed238148a896944\nY = 01b5e8e643fae552261427ea7d521f380adf605579462315c75e9203203ebdc9ee33dd7ba885b6cccccbd2327462988223c4b31485311c935a341ee87ba1ee820ce0\nDigest = e9ea3c8aeae3133be537da09b98c096b9a9eb287a02b3542efd30f0026ea9cb3f242b842b2cedbf02e70b44ff8a0b1bcf6f31956eaf6c0dd9a023bea36440068\nR = 00ba2c57827baae684d2c637590275c782a6db263a5358c8e1a08b5460ca3cf0f5ff8d4119a6b0d55fc68a75c793098e0a5622a0b4e2",
     "fcb0f17943440138d751797b\nS = 01594beb73b2ebb7c573ff07b5c43e722dc05979df0eef53587e9fe06a920f61d2efcc7671e6cb875df4e4d92cd4d37cc3eadcb9b6aee8f2097790ce24d6dcda8706\nInvalid =\n\nCurve = P-521\nX = 010d587aa82a4d8e690672c00e3fd71826d892862d14dc4fbad4935aaab86924dc7ee6f7fd3e2bbe86a8652589448494dab83d363d1d623cbae59f6c2670706a0576\nY = 01a9734c99b6ff21267050738937c30971d0f6fe07e29794748a5017ea1036c975c9a52e6d3739ca0e8d70e784529cc1a7437aac5d75c69121b69020a95356137f1d\nDigest = 8814a9dbef9e6d9b8322bdf8d471b207388bb7bf831d9fba8ad29da52d528d5d5108c01e4459f5ca13e26bf5da3c848195558828d7a00f53abb9fce47ef35091\nR = 0188dcb840dfc573a97117009226d58dbb930ba8ec848931786abc770611f3519c8ba73cceb5b489170805bcf04974672fe66c908ba379aca99fa67fec81a994c2d1\nS = 000b1a185512dc6a65e454ea2bdb8049ef8f012a53ae87b759fb5d9edba51ea32e254e80545a99eb4b7c58af96b7c433535fa3f009cc644b1c97666d88355af9fc19\n\nCurve = P-521\nX = 0182c957a62e2e27aa28acee2e2f7b1ed6aef81c68001d2648da47d2b621e8b8bd18d991cd1e3fb9afb84f639fbed1050584428cd2a1d50f877532ffdefdd4e6f7ba\nY = 005fadeef58cc0d79362b599e94636f9c70e3e5580c085b7ea52a5fd24fe4a892120b8f28ba53ec249c42d6d3b36268b8ca8464e54b72d37327d7504d9b7ce534d95\nDigest = e1838cf6ab5daf5ed28dc1b3365eb03466e01cc30f6fec9756c966cc7b89ef5ddb32754302a33b5aa309c871f98de082a21cf734ba8a368794d89b0cde1cfcf7\nR = 01e3a78e973fef6b6de8a0356401e89f435ae5f49c0173f073c4dbb9c91463e420f5265eade8305f11d30fa8d97e5b4c5ab33975f73385aea81fbdde2f7ddf7fdf16\nS = 00efeca10b5362e05a8f2e3df6661d0d536b32ca1e0a62515df2d94eb314aadb5eb40468483e24b16efe85c503d6c231ef860aabe674b72ed1ddd93853338e5e4e50\nInvalid =\n\nCurve = P-521\nX = 009911b41f9af525c874e05bfdf050331bf830296911bcb18eec16275027d63fa106c8989b07921c7e58b02711b5b5880cc4e6d9174e0d31060548cf643bf7ed4f0c\nY = 0184fc0fac3c2c80c69c1c0293f4e5e22fa08c267b1f36ac5ad6dfdf4da1754f7942f48cb56f56cba05e22b91508fe4db3703066e8f697aca56f974f3fe530c9640c\nDigest = 365868aac67d82cc0510bcfb012f9035f99b5841329344f1b45f0489463cfe22c2f3641f7d6c59a3703aa2804323db8fec4fb3804f521149e5f7d38c9e1e94f2\nR = 017b8a22fd8f73112310867909f234fad6aa82999c28ea5a2e74b4b4bc79b2f89008b4d361ef7e797c7656f7d9317eff3e5a4982799b8cc0db82618bd2aa3959f617\nS = 01edacc6d1c0004b2090d2025d615de1fd53a96e826a3930c7cafaf3c87f34b2583997534cfa127485600a7ae04e6af4a2e98c77fd04507195e520e80014aa982a3c\nInvalid =\n\nCurve = P-521\nX = 006da3b694e3123ef96b3fd2ab964f85a36110590720dc1724a5d50d3050498957211c6a1535032cf1f31240bfab967cc0cf3b442c35a1bfa3e72470df1863d2593a\nY = 017d0a5dc460c85d0365c7bdc2e9300e276b8aa97368af9972744f4422442afc601ecfe7903a33b0354c901c7b61f29d2d3c5610192cd188291c5651754b385b87a8\nDigest = 4e992e9e5403eb9822958f2737b70fa8096474a845a0f37244af744a6009e3b6e6e008faa7192fc01755bb785e03e4e3d2caef03eeadfe32a7fbc7e3bda49f5e\nR = 01f9cb1f4e2e65282a929acd8b685ab34da176f5c73bcb374fd1b09bc995385ce3902d6c5496b02916fd5a28f6f8bb662828a76aa0ad14b01bc24a63b328c7bb949b\nS = 001d6b3a2f34e3b7bf63d06b11ace172ca61ac5a911a4b408d766eb586c9ab820d42f555e546d892643e12a6752465427c213e3839e4f8cb3a7e4fd83642843e8544\nInvalid =\n\nCurve = P-521\nX = 00b7e03f0d623a0998add5360dfb0bfe836fcb0a46b0d6f697ba6b3766bd8698ac8c7af62f50511c6aa5e613f4a99fa28f70b220ba1cddb22482be74c969953ae6e5\nY = 00d4ee40ee4441dc85356760f87ba32e2e7c269a2e53a2e8425d5ff02f5e4fe8d65cefe20e162c3915d2eb9ad1354bd28595a86dbdc94a5d40c5b44b1e3aa3965455\nDigest = 8ebb37c7b60ba4622070391864a70b5e797dc2464151304b1d9614b77f0bcb92fce230f42cf98f9b2612f481c21f70564f5cbfc4e81e48e08ae27b466f717e02\nR = 01fcba4781de6506f7c3f26521f0e036b5225f651e69e115d6784b2176a666edf69d759627468400a73a136f599fb8db4643fcc16bdeeef6384a1875e1c81c36b962\nS = 00a21cfaa7e1ee0eff7efc3d7e936378500283b00687363070974483ad474c58c6b55b77f678d78e7cb44d9745f79394659bdd26b72663608384b5ae9cac1c888d13\nInvalid =\n\nCurve = P-521\nX = 001bb7c623fde41beec7ddfb96f65848c2f52b50b39576bf06de6ccf157b8ec49889528728480928236300447da7171f58c8f0e0ba8fd3e2cf378b88619aa6c1e0bc\nY = 01f8b20a1a7df319bf78c2cee03581a1ffe8ca5107fbfd40760fbd5ef5247e2df1092d5caf504a9ee653ded2995f0cdd841d6af29c9f720770056ebbc128705f68e6\nDigest = c18be2e3f935561d1ad1cacf6ae06e733a463c7e5063cbb0cfaf162a579522786755dff879d2bb0b63d4eea9120a2ed648d601a5cb2dee936dbada679bcc134b\nR = 0000db4c31f316912295c5b9506aabc24b0b2dc2b2358e6b023148889d9200bcf44762e88575e359b4868b2d93ba7bdb24800b09fc22eade0744b9832b71ee784e9c\nS = 018c84437fac7cd82099a2a4230084ac27ec7ea9c92e1c9d9a71290df9b37dc881f9ba59ed331c22dca4b2cbb837cd916e0a78398d2b7aaf8e88f113a942beac48c0\nInvalid =\n",
 };
-static const size_t kLen35 = 143692;
+static const size_t kLen36 = 143692;
 
-static const char *kData36[] = {
+static const char *kData37[] = {
     "Key = 00000000000000000000000000000000\nPlaintext = \nAdditionalData = \nNonce = 000000000000000000000000\nCiphertext = \nTag = 58e2fccefa7e3061367f1d57a4e7455a\n\nKey = 00000000000000000000000000000000\nPlaintext = 00000000000000000000000000000000\nAdditionalData = \nNonce = 000000000000000000000000\nCiphertext = 0388dace60b6a392f328c2b971b2fe78\nTag = ab6e47d42cec13bdf53a67b21257bddf\n\nKey = feffe9928665731c6d6a8f9467308308\nPlaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255\nAdditionalData = \nNonce = cafebabefacedbaddecaf888\nCiphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985\nTag = 4d5c2af327cd64a62cf35abd2ba6fab4\n\nKey = feffe9928665731c6d6a8f9467308308\nPlaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39\nAdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2\nNonce = cafebabefacedbaddecaf888\nCiphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091\nTag = 5bc94fbc3221a5db94fae95ae7121a47\n\nKey = feffe9928665731c6d6a8f9467308308\nPlaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39\nAdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2\nNonce = cafebabefacedbad\nCiphertext = 61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598\nTag = 3612d2e79e3b0785561be14aaca2fccb\n\nKey = feffe9928665731c6d6a8f9467308308\nPlaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39\nAdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2\nNonce = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b\nCiphertext = 8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5\nTag = 619cc5aefffe0bfa462af43c1699d050\n\nKey = 000000000000000000000000000000000000000000000000\nPlaintext = \nAdditionalData = \nNonce = 000000000000000000000000\nCiphertext = \nTag = cd33b28ac773f74ba00ed1f312572435\n\nKey = 000000000000000000000000000000000000000000000000\nPlaintext = 00000000000000000000000000000000\nAdditionalData = \nNonce = 000000000000000000000000\nCiphertext = 98e7247c07f0fe411c267e4384b0f600\nTag = 2ff58d80033927ab8ef4d4587514f0fb\n\nKey = feffe9928665731c6d6a8f9467308308feffe9928665731c\nPlaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255\nAdditionalData = \nNonce = cafebabefacedbaddecaf888\nCiphertext = 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256\nTag = 9924a7c8587336bfb118024db8674a14\n\nKey = feffe9928665731c6d6a8f9467308308feffe9928665731c\nPlaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39\nAdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2\nNonce = cafebabefacedbaddecaf888\nCiphertext = 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710\nTag = 2519498e80f1478f37ba55bd6d27618c\n\nKey = feffe9928665731c6d6a8f9467308308feffe9928665731c\nPlaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39\nAdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2\nNonce = cafebabefacedbad\nCiphertext = 0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7\nTag = 65dcc57fcf623a24094fcca40d3533f8\n\nKey = feffe9928665731c6d6a8f9467308308feffe9928665731c\nPlaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39\nAdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2\nNonce = cafebabefacedbad\nCiphertext = 0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7\nTag = 65dcc57fcf623a24094fcca40d3533f8\n\nKey = feffe9928665731c6d6a8f9467308308feffe9928665731c\nPlaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39\nAdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2\nNonce = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b\nCiphertext = d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b\nTag = dcf566ff291c25bbb8568fc3d376a6d9\n\nKey = 0000000000000000000000000000000000000000000000000000000000000000\nPlaintext = \nAdditionalData = \nNonce = 000000000000000000000000\nCiphertext = \nTag = 530f8afbc74536b9a963b4f1c4cb738b\n\nKey = 0000000000000000000000000000000000000000000000000000000000000000\nPlaintext = 00000000000000000000000000000000\nAdditionalData = \nNonce = 000000000000000000000000\nCiphertext = cea7403d4d606b6e074ec5d3baf39d18\nTag = d0d1c8a799996bf0265b98b5d48ab919\n\nKey = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308\nPlaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255\nAdditionalData = \nNonce = cafebabefacedbaddecaf888\nCiphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad\nTag = b094dac5d93471bdec1a502270e3cc6c\n\nKey = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308\nPlaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39\nAdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2\nNonce = cafebabefacedbaddecaf888\nCiphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662\nTag = 76fc6ece0f4e1768cddf8853bb2d551b\n\nKey = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308\nPlaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39\nAdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2\nNonce = cafebabefacedbad\nCiphertext = c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f\nTag = 3a337dbf46a792c45e454913fe2ea8f2\n\nKey = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308\nPlaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39\nAdditionalData = feedfacedeadbeeffeedfacedeadbeefabaddad2\nNonce = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b\nCiphertext = 5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f\nTag = a44a8266ee1c8eb0c8b5d4cf5ae9f19a\n\nKey = 00000000000000000000000000000000\nPlaintext = \nAdditionalData = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad\nNonce = 000000000000000000000000\nCiphertext = \nTag = 5fea793a2d6f974d37e68e0cb8ff9492\n\nKey = 00000000000000000000000000000000\nPlaintext = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
     "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\nAdditionalData = \n# This nonce results in 0xfff in counter LSB.\nNonce = ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\nCiphertext = 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c\nTag = 8b307f6b33286d0ab026a9ed3fe1e85f\n",
 };
-static const size_t kLen36 = 9174;
+static const size_t kLen37 = 9174;
 
-static const char *kData37[] = {
+static const char *kData38[] = {
     "# These test vectors were taken from NIST's CAVP tests for CTR-DRBG.\n# Specifically those for AES-256 with no derivation function.\n\nEntropyInput = e4bc23c5089a19d86f4119cb3fa08c0a4991e0a1def17e101e4c14d9c323460a7c2fb58e0b086c6c57b55f56cae25bad\nPersonalizationString =\nEntropyInputReseed = fd85a836bba85019881e8c6bad23c9061adc75477659acaea8e4a01dfe07a1832dad1c136f59d70f8653a5dc118663d6\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = b2cb8905c05e5950ca31895096be29ea3d5a3b82b269495554eb80fe07de43e193b9e7c3ece73b80e062b1c1f68202fbb1c52a040ea2478864295282234aaada\n\nEntropyInput = edfdb55e77d418a63e4414dfd42225ed257cf74e99325fba26e8f3a4524a71bc80a731af23256908cb4675a9c253ea6f\nPersonalizationString =\nEntropyInputReseed = a9372fea93d607fbbc75a97b7f65f2d4ae8c06bd184981572e888a35c5794d2bb380a4ae04bba27f2efcc9e7914b96dc\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = 11b1a0f0bb935ec0c54e089e0cd20832d1f00e7069f30e9ea2e35b7f15ecf0577d0e90035bf0f91ffd9e8a1fa8a507503739afbec19393e02c9b7c230cdea36f\n\nEntropyInput = f253fd442b105434c0f47ba9b6798bc20c8832a142a2a6d965678485a3ac52393528a5e092341d60ad74429f4005f8bb\nPersonalizationString =\nEntropyInputReseed = 600c822b198dbdcd9d13ee25bd4b846e5d8665725eac5347b4cfe7512c1f3fbdc4c51c85d977ca58e9e6485a17c533bb\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = 076419bdd354d6a1f1415a0a71bed94db29cad22f0205d983c841874497875a4857404e573545366850fe6eb5286e0deb87ddd63bb3317b4556a82920412aeef\n\nEntropyInput = 8dbf2c37dbbf3862f05af4b32e98edd3d8cd7bd34d8a23daa2d15200daed6e9d238387ba85ddfd35a2986bdf5790e1a7\nPersonalizationString =\nEntropyInputReseed = f67aed05dea08baa16cbb669ae310a0b8e019da0a7fe2762abf684121292186a50bc13d568576ce5d7aeb080e4604a1e\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = 69666e65c5623140da35927ec39189fcfda0891674efdcd2a7d6f2628921a37bd49a164590413c04f6090a50336f040b015dd8c45452991bcdd96994c5ecc6bd\n\nEntropyInput = 2fac25dcea5274a7dbd6af112d757b59a4447f5dcbda972666af071c5d8f71583ec6914a1e685f610b8a43ffada0b411\nPersonalizationString =\nEntropyInputReseed = 52f5b1f927c0873ae375d6a6e140fe594fd474a63bcdcd6a98109e32ad980ce534714ec626dad7acd43101415e5817d2\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = 3096cf20137eb6f94d9d26a4871eddf10285c6984776847105ca9294aafc68925ad8bd7f36bb68fe371476114649ead11b926f9f0fc1d21c744342ff5c44c8e3\n\nEntropyInput = 4133a0e6ce837125f46f2a44e05c4f64d76879156ea16a1d16db1d3ec460cc53609fa9e4b3081f9dde0b79f00c93ac5a\nPersonalizationString =\nEntropyInputReseed = 4613b2327dc9054f34faf933d62bf7b12ec8b34626c07ef7512cecd8aedcbd4023f26b859a941c5af77ec1e2e02a1d9c\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = be02e94fd18c488741fd90b6980118dffba1cda5bd25aa23d44414392201c5a78c3ea68252f92afaaf540b298d3f80a94818f1d1ca84c2be5f66a46191a7548b\n\nEntropyInput = e312fd67b5009ab1c896ba8f85d53fb29517ed2a26d20a4b9d09505ec004bef5739cc94e7f368989c675eee1f40501a2\nPersonalizationString =\nEntropyInputReseed = 176ec11c0d4462ea26b1bdee41208e3ff3b430de11f12567ebe982c16d709f681fcd9f5bd5309f3f2a9d80b3a426929a\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = 07cb9f51e34be38fe1d1c18858ee44db227c1e6a6c2f7d09e9143e87e9e09df0af9a5cb7a183e5d26359509fe619e52e59e3333d3620373d3ae5a008b51ef786\n\nEntropyInput = 3eaf30117135d9167c829e35bd8da227a6302471b649381858085e67c65496058ded0ab176a38b3888f4e3c2e65269dd\nPersonalizationString =\nEntropyInputReseed = df60a1b9fb2f8501756edd09e489fc98a60ed08646f5a2e018f55b71c76b9b7718ac4ae61b41241593829108ddeb0ef0\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = 29c4d540354e97f50f3fb1de84eef471192cd76a670de34176c6465523ff249ed5eafe2c09f091f5ed101cf8a971d782f150a2642ed291e850906e29328d6b8a\n\nEntropyInput = 99d5543c192c6a1069bf548d80d678bc42c1f020f0b29a0ceeba424c03f8a8aa38df1c0fe100ee4c1b0bc870b4afa3d2\nPersonalizationString =\nEntropyInputReseed = a0fddd29c792f6f411b5d532fff2564d492ca15ac8b7fe1b4575e9b59806823665ad7ac4e2adcd2803ccaabe87ab75ed\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = 3d58e98a1f4beda50f84f773c405d106b28f4be6da2a2942098403843bffa3323c53661a7f072a020c68f55ea2b3a9cf9157b7c4cdff5e642ee9be1f436f9c18\n\nEntropyInput = 2151ba6cf2ed6a7366991e516443162b6ed4e7f8ef2d6c81ec5e5feb0061e20ced65da27847956194dc6177b5e0befa9\nPersonalizationString =\nEntropyInputReseed = 73418efab1c6039145dc6ce09b84abde4ef4f8eaccbac250213bdd75e2a5e8b42ffb1367bd8d1281e3b0051651f78a05\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = 5b219cb285c820f3bce52b9eff15afa042de3036f1a52896eab34e4476c28c60127cf8daddce0809efafab03c9269cd220a49f79220e14db9d208311d2a22a1b\n\nEntropyInput = 7c7321b69fdefdece32c45e47cce07a0d599e83ea8ee5781e2f2ff341f292c0bdb848e5ab379771639e811fed45f63d7\nPersonalizationString =\nEntropyInputReseed = 4b04652d3d0515b305f4da346754c0d398c8cfefe8e5c1edacb79cb8396018bda12ad7d42bf86e801159bb62c34fff68\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = 379c12dc2c8a884c6f40df5353047d74efbd9c626795b86256abec4a6f42ba26529f19e4b043f53776180c7ab16a3817b4a50c09bb3355234786e714edb9e2b4\n\nEntropyInput = 3a56329b07dffb8bc7761c0c2b4ec4ec3b7ed2513f0cc3d9be3eb9a153e8e1605d9392dbb951e4b0989ef473301f6f57\nPersonalizationString =\nEntropyInputReseed = ff6efb9b946748af0992bdc38eeb15d4991bb610692e1fe53ff828405924a544ee0e4da70aa1d0ae55e7925a58cf5597\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = 9f32e40391217833176ca768beedd2839892c6fc17dec5c250f0820c576e4ed615729653515ae13292a2e4aedaa2df74c6535d8c625dd1cab479d3c5ae7bf955\n\nEntropyInput = d550f48af436ae42ea48a8cb0cd615be8db51691b365ef20ed826b28561fbacc9deb28cd3d83655033068948c55683da\nPersonalizationString =\nEntropyInputReseed = 76ea2e732f77b337ddd402e367c158dacc3433feb40d7b4376fb8dc449891336b00841580ea189583ada95cef783d540\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = 8433b2ac45da6fdcbeaf3e6f76e66beb5b90a89a9cb197cfbe405ed53b1dd51a42cfc9aec5fe7cf778f88031fb7b15b0874d4d1ea87ef3895848721b34fb1a35\n\nEntropyInput = ce6137f720affd106396d9b66540580ae216d5d7dab48ed2729cdb3e587c7d8da13ce39ea8d9d8c22220a96b74e7ee9d\nPersonalizationString =\nEntropyInputReseed = af9f12fddeef001b08a5993f62da5e7c3aff23f882ae874b9f66f28eca1106e6386dd82f07ae1fb6868f186e2ec4f449\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = 219fc160dbc136cdc9a7c3407eafde4639602cc58101c512dfbd85cc26b61fc9a94cdf76f15a1de7a46e36ab64aca3eeae36acd6e3d0b3fe59b75958b3eddd24\n\nEntropyInput = 1accff5a19861164c5d2cf542cf41a789f143c7956518ae158d4449ff0c257a00966faa862ccbb363bcf4aeb31089134\nPersonalizationString =\nEntropyInputReseed = f2fa58209759d84bf38a1656bae655669767a902ade22a830df56b32ef9e1c992335eb4cb27eeb142bfd21b5d31451de\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = f214b4055d182cb258d9e9b61251bebc9bf090db662c4e36023cc156964fbbe1cedf691cd0c3d7db4262fb65a5d34b942f909b0f31fc18009766413523dcaf40\n\nEntropyInput = 99903165903fea49c2db26ed675e44cc14cb2c1f28b836b203240b02771e831146ffc4335373bb344688c5c950670291\nPersonalizationString =\nEntropyInputReseed = b4ee99fa9e0eddaf4a3612013cd636c4af69177b43eebb3c58a305b9979b68b5cc820504f6c029aad78a5d29c66e84a0\nAdditionalInputReseed = 2d8c5c28b05696e74774eb69a10f01c5fabc62691ddf7848a8004bb5eeb4d2c5febe1aa01f4d557b23d7e9a0e4e90655\nAdditionalInput1 = 0dc9cde42ac6e856f01a55f219c614de90c659260948db5053d414bab0ec2e13e995120c3eb5aafc25dc4bdcef8ace24\nAdditionalInput2 = 711be6c035013189f362211889248ca8a3268e63a7eb26836d915810a680ac4a33cd1180811a31a0f44f08db3dd64f91\nReturnedBits = 11c7a0326ea737baa7a993d510fafee5374e7bbe17ef0e3e29f50fa68aac2124b017d449768491cac06d136d691a4e80785739f9aaedf311bba752a3268cc531\n\nEntropyInput = f963096540d0023d6703e18248755ad16aea91852a2db0dd0f6a414d2a5822f3224ac8b1d47b01aaecc93ae299081d7d\nPersonalizationString =\nEntropyInputReseed = 399ed54bd846de00d42fb1f92d1ade93e81e32cd6ce73825f0bf86179dd46fd79bc8cbbd3b8834e58cc86619e19b08b4\nAdditionalInputReseed = ee073f9f6145d0a7c09a5e4a12d65baeba360bc9b5d7cadf93e7d2454dfde507af37e49782cf8550dd3a548e8cf98563\nAdditionalInput1 =",
     " 6a42ffe56dac0b4dc5d84b49698859b3645c920151565bf29f56b6322244bcaa7cd1ebb8ee9936d8ee1d280f547ae245\nAdditionalInput2 = d057c418a758d99a8ee855093da9bc1734a5168a6df9d9c9924e8bb472b5945563d86350dcf3e11aebcbd06a22b9ef78\nReturnedBits = a0cd72e63f49ce4c1d64e21e92546afced2af268549ef48d3ca88afe4d4097f91a52ecd0e7ad12ec0a1f67dd8c5325b78ee507c0a63cf90d64e9c47862acedf3\n\nEntropyInput = 333a0269eb0fb1d9d1e92f55de9e13cd7e24de64f5f276382d3eb2ff356a66679a9a75d2da31d39a940a09cc85d9d531\nPersonalizationString =\nEntropyInputReseed = cbf504cc473c9a6e66493b71b9684e8df458e65d2cc676e4e6ad43eb59172932c0956d0623134a6a3bba23906ec9da0a\nAdditionalInputReseed = abc86c71ae0585827ffe0d19a9fe97f23cdc4afd67978e553e0669d4635ca1df30250843fefd4d1288f6fbc3bfe04a72\nAdditionalInput1 = 15d15fbe7c060e6811bf47c21e93639c00cdcc562f4e02c88f7e347ec14a2c8410fdb2ddc3dfa62ba9ed1758f12017df\nAdditionalInput2 = fff311ea4c5cbd8ce53c45fe8d8106c28eb06d01ec9d8245c29f95b50b13085a0ec28803d733bd0d8a75193e63e21d5d\nReturnedBits = fcdb52bb6e2ba8d896973b9284b32af6364a34a2b80b3e3c7684c200c9e0a02f7bc6c3cd32b159df9b98da07a17baab9b0b07eab214544d5c562e454ec643de1\n\nEntropyInput = 86e4c30c5a7dfcca86eda7723930ab3272635f0ad9e2fd70a2d7a69b6a07dc0cddeabffa9c411198e3cb7589cb29d3f2\nPersonalizationString =\nEntropyInputReseed = e1af1c42cd29dd002e10e5839e8b679d3c5192da5e1b655123132ff1ade22b35651ac6df66fa14f36e1832be7a176895\nAdditionalInputReseed = 5f619073fa2e98b9f06bb4676bb972379ceb727e1e8768ef09e532cf3d8fed5ce92a7528eb55ae552959d74f75dd0324\nAdditionalInput1 = 330e316bec4955d907d7d7bf2b7149f0aaf4285ed1a2b7e387376ea1a4e0858c114ec3ddddf7a1edd7c8a29b1f12b998\nAdditionalInput2 = 405911cf7c6779e02e4740fa9737f189370292494c80621cfaa9f7d16d68219e72d474f8d5a54aa8ea8020dff9c36650\nReturnedBits = e359c3e23315c9c1d69ab2ec96ec3c6c5aad868e58709e101b0fa08c4041248e4d538d038993250d395d9651513514fca5760dcb9970dce53d2d1c2712bc56d0\n\nEntropyInput = d8cc5d13badedbdc2fd41852247a9f2879b0103b4a8186f0a08da7d55453b7484f642a9e5a5182340584d2ca7cd5ed10\nPersonalizationString =\nEntropyInputReseed = 35788b8369fdc3dfd206efb873b5c5215f5b8ecb0541fc0a0e027e868a91053b5d58cc8ca0751e0c0893c868e2322471\nAdditionalInputReseed = 6afcdc760fe62b080f141886b516623971f8014ede86e50d62d307a90cf3512da5fefd37b3932d3d9d86ad0c03447be4\nAdditionalInput1 = 72105702fbf1da4c10ff087b02db764804963fd986de933b757b8fe5a6016e0f2700573925aced85c09e2ad9f9f7b2c2\nAdditionalInput2 = 65f9a3fe4e1953b7d538f6d6ca3c0a73bda2276fe8f80860c07b7ed139d748c3c45db5d96598f77ff863a43977ba390c\nReturnedBits = 7c2b600c3f550671215b03ad7aebf71086ec59aa4f45cf6b3bac9bba2e108f801f6478b098fcc4e063454cd3f64a951ed70f619866c1a4e70b5c47458c09e083\n\nEntropyInput = 07d14a0d9fbc76a155047a93bc0bb2b578fa7dd75cfe9a44bb8709fe3cc2302fdcc06a9c6751f4602a3a4955c0f38c7e\nPersonalizationString =\nEntropyInputReseed = 8babab6b9f8429f554156da3905122cb48c0b901fb6eaad8df771e8d583ba885dfbad02e47524b1981768593bde88260\nAdditionalInputReseed = c185c45cb07e8c8ba8eb31d3bd48a7c864137c689214c2fb3b1d6d6abcda84f2922a862a0955e67695391d60d6f2d1bf\nAdditionalInput1 = 326a5c9c4a1a2b6fdc369fe2a171bf625dc26e23d1a34faacf59bd33be98ff7ac7f16e485b6da3145ea4db37ee4ffefa\nAdditionalInput2 = de096ad13dcc1ee1449c3a0661edee028603590f087474161a7ab8fcfac896a924e14b0a57aeac17fed676f4b9c7168c\nReturnedBits = 60911e6e6455bf4d85a4f76378390f6cd537d7cce88228cf34e4a4889adf62a9cc1070dfc39c254e81a8557bb2c350fe3f462199e377d3796ed139117b6b0f45\n\nEntropyInput = b3458c6b38ca70c44fc6c601e088863fafc953c6b5d3ee57fb1a07f3f65dd5e6dc19aed17aa5530913aca598b26a40c0\nPersonalizationString =\nEntropyInputReseed = faa8d3feabf972e482e5a0b3821c23ba067c45267e3715a4c10f65716a348030d7fa5637e9f000b3e47d786c013fc035\nAdditionalInputReseed = 901ef89ea38203b83249a34a1a8cbd0da4773ccd503d60a395be3a3db113613e6c571a49960a4e99d302b6f237f64d54\nAdditionalInput1 = f2f87693d1f28f95b0a6459c538e82be99a8cefe8a2c7ca037822072e63670dd141873f3dc9e309c6ead40783f46794e\nAdditionalInput2 = 93cfefbb7624a137cbd7b177918823893e77251fc5660a76ab0cfaa3b340ae822a8a75365056f06b0a7e76afc39f6819\nReturnedBits = 5bbcdeb5d7d1ae19e4ef7878abd1ca4f2641d42c765b94a7689172a4e90baae46ebcfa5427a882c1614cab36f186a98dd3a15febc4b23add955f69dbfd5e5d2e\n\nEntropyInput = 6dbcf6f2f3997ed55471f779039982bc84a1c052fbf5883d6f62c0a61db108386e74759d7237bb0efca030aac76bc7e6\nPersonalizationString =\nEntropyInputReseed = 1a16753c195fed27a1abbe067b2b22aff4c49ae7832d18d01cef5ea5c7d5833008036f71e9c77c1629b6f61370b57f7b\nAdditionalInputReseed = ec54395931ac0aea2a8739d4c51e33c8425906005c341db373247e73b968c2c79257cf7ac74353c00fd81a80f4c95b8c\nAdditionalInput1 = dbd6bb5579a10e395b534431f3ab7c8025527bf99e4f7c162d681f8d35a56f6a03729f07ab43897ad0e80146044b1614\nAdditionalInput2 = 5d35742c25620bb795eae41178d7fc86d9cbe050ea702573ae6adb61e16c411b7445548dc535d57371bb11e2cdd59597\nReturnedBits = ba3905bfddcabf6dae311d1fc19fff1f6fc1ce779e38f864b7ccd2aeb1b3d6ec1845305c29d39b8736b3977277ecaf5735d0e4acefccf7778ac3542af815fd41\n\nEntropyInput = 3a9e8099007c67f6e5f98525cc4295a68c5d5135d01f5f66305c7048ca02525caa3f790b2d12a8520e9963a9cdd597a8\nPersonalizationString =\nEntropyInputReseed = 15993dba9775db8a5bf79778a316f2910d4dc0be59c3b21c650e3aa89c8c89b33fc69e9e5d642e7fee16d61b691de2bf\nAdditionalInputReseed = 946121bae27e5804daeba0d7dc7ae0c1c397bfab106e13b8b7c5462b540d147119af5b7c4f9c198161e5aa9be34e2d28\nAdditionalInput1 = e9799421e75bae7086731a21242dc101c93b768fc747734a357454fc0f7c082cfdb79b8bbcea2d1122d89316a7bfbd3d\nAdditionalInput2 = caa04f94b4b9d694e2c4bfa1e8e708b9c00d9c3d645243acfcb879d2e2ba723d9e48908738114eab7d15f8cf36b043ae\nReturnedBits = 9bd50f3c5384eb28d931f03a64eb97ef140e1e81f4c1d9c910cd7d79a40494e1fcc53d82cd32df35d53b05a450e54b7ec71e28359c1273848e5ab117d5ded88f\n\nEntropyInput = 7f2a0213de6738ec62bedab769a5f01732dad2d35dd4cad7a765dbbb6f9101f57b65ec8fc4e23fb3479ce6211ca3d84e\nPersonalizationString =\nEntropyInputReseed = aeb097e9ddc4dfe87874ddb1a856ec3d00fff1b38c8f954681c11e61bac8b6b2e2d8d010e6820f9c4d807b295acb8ab0\nAdditionalInputReseed = b33ad3dec7d529b71e39d59147f79b4884039d1112804fe8c70e174fdd9828c06a4d44d20aa5fc1918c3ee8082a2bf93\nAdditionalInput1 = 8632d221757132bb7b883b7dc26755f62ec2ffab0876168d11ea7b92774c15c553b11320393d64a2262133608ca92a18\nAdditionalInput2 = ccaf3bc3ae9cdbfa885aa8414c1f823c6a3ecc020b619201a52ce0b7516ba1f49755c450c532bfe11c06b9d0e049ccae\nReturnedBits = 4b1c065a288e5eec56b67fb341e25fc7521b794b52b94f9570bdb16583bb6f7a780aea5297496355ffb4bf5a444c277c96394619cc33cbb5a3b2a9f49b00f9df\n\nEntropyInput = 80773d0272ff48ba84b98c817365b097f21258624d0de8529381977950a5e49ff2b79d0f2522269970ea6d484198922c\nPersonalizationString =\nEntropyInputReseed = 9b101ac018be88da3611a236dfb1300c0049947e9f6ebef7a3ad6e1499efeca0b142826fa06f427e271865232a18dd29\nAdditionalInputReseed = a67ee22453dcaa5e4726e3084872145ab60489bcb6e83346c108f3efcce5b3d988b84d58786658d87c2dc3b9035e9d88\nAdditionalInput1 = 546515bf86e48dfb2b4dd21c2b46f10c1e797ab799b51822e8e7cd99ccebcca00b8899ef6af5cb395168aada9056a6c9\nAdditionalInput2 = 57bedda63fc5f792a608be111141a12e522496c086194515909bddcd868be997e718e7c5899e28dd6b123cbcc3f2a8f2\nReturnedBits = 4075461e459f15cd32030551be47528223693c2f44e32443cbe9271eefe74fa0a6e1ec04f4b8f41d7ed6c5f455281a3cba56d952b08b7753f6a3d7da3517317a\n\nEntropyInput = dc132c15af0e214d1b56eb88849e96b81dc17f238eb3d1bb9a659219dbd77eba38ca2796a8011e29cfad76f8cbbf099d\nPersonalizationString =\nEntropyInputReseed = cba23d4fdbb6c11e38012b71ca264bff9d1264bb20a39bb27d86dcdf7d72ce7a4f5c124cdf2aca6aaee20832495181e6\nAdditionalInputReseed = 07e043add7cc14612a82926c09934dea092f4618cce25674972b1f50b2907c7e3d40a25722ea49b0c7ceb6b57ff2d870\nAdditionalInput1 = 0017ff834967cff8827598ff6c00a9c97f0347c34f2523a85dd7d18ff5575756c1f5383de50338d0ab0505841d70a193\nAdditionalInput2 = c404dbc3cb0851b08530f96500f5a2c10d8985c82dec2ba31d4199fd07687ccf124382fbee3fa119938f0c72ac586102\nReturnedBits = 1935cce86bde7087fcab30b5dce0e072ad741c2f281902e1801e56c08ae8b256d27514de92dd48a838ca426820002c1206f86cad37cfd99d3a935e05f56a7507\n\nEntropyInput = e48495930a7fc86ecbfad807d40ca84ba35e346c812090def8f44d9e48b0a40704ac67ec80ae15b12e858ae85a7ed9cf\nPersonalizationString =\nEntropyInputReseed = f4735954d17e99077061c9604e8f1734d61dd662e54e37256c0f8bf276e025d59d21cacc0869ededb44a2aac9fcf2ccc\nAdditionalInputReseed = e796322fc0ef503251f6d4bd72dc5ea8100",
     "c5a59f1a4fe4837fa8eb2623bc650a0cd48c306f139e0ecd169a51deb2cd0\nAdditionalInput1 = 1c844d24b7cd9512e5035bc457612ebf6d3df6867aa909038bcbc1f474f7d0783ed474e34525a817bea1fbc883961e31\nAdditionalInput2 = 5c5671ba79bd0b83f74d0ed98e9c8b369a2de34188d8b7cada20b3363738d1252ece1e6a26d007acdfc5b6108412766a\nReturnedBits = 40f17e2bf6084a6447f2c40d601e16a43098dadd9f9614d518874623e8e684438c02e127e582b000dfd46df03dd5435edc4f0f47098320fd311afdbb8542c4db\n\nEntropyInput = df4a888ec7363fadd99ce2223ed39577a41bc220d20b253f98dbfc617aff8fe4ac66e5da1b5097228422cf8242baaf53\nPersonalizationString =\nEntropyInputReseed = e16dca80b2061706e8180dce8f59e888f150836a0bbceac179a4b8d882eead78709ed9951102728abbbbf9226a2d913e\nAdditionalInputReseed = febc9f6b9f2b90b4320d5d41e5c5506fa32b164d86d5e7f91d4a360fe179c127bd2bdeb78fe760174e856a5e04ed898b\nAdditionalInput1 = 0aba74cd299e75886c9e7e5293e5915d720da2c8c1cca7f0e1d6f2b672b4014eb4582e97a877121c87956185736ba0e9\nAdditionalInput2 = e451eac802660ac843fc72b66d59f1e1ca831f22d6a361929043f7626f1d82133f512fb1f2d8ca51004f80ed600609e4\nReturnedBits = 968b708ed6b54d2e5a66d46f22998748dfb5cf47e817732a40938bf3593fb251ccf8f2076837715d14b316bfb52560135602ff98338593696bf80a462b214c4b\n\nEntropyInput = 43bc561c4dd1b904a5333a092a670d0d1b61128a13be2e538a329094574819284e414b938dc8b1860b385c293c03010d\nPersonalizationString =\nEntropyInputReseed = eb362136f4ccc9e302505d525befbfa99d8c3336187d5902b03ed75641913ce973743757f97dae9366874ba62bd87013\nAdditionalInputReseed = a901f4daaa638804177a0b263e8cbc81688df3beb218b02316da83b729230a9e5112fb3896b727298755bb9ac6b6250a\nAdditionalInput1 = e33d181f3159fb0874eff5ef8ddd2b51a60b13ccf046f7e637ed27bed81bb604277f7345e6b8f0e09f925793ce417fff\nAdditionalInput2 = 3ecf6233820e6cceddac7b024c490c5ee14c73d5b598c92cda30940471b6ed450019120689aaf157fd87b71b13afea25\nReturnedBits = 9d793dd96b870dfa0267623bd1c2d8bd3e2c63e9f211340f630fea01358011394154145a10659c4d98274a525c48a90da0126a99b85ed5b4b903195f0dddc762\n\nEntropyInput = ffad10100025a879672ff50374b286712f457dd01441d76ac1a1cd15c7390dd93179a2f5920d198bf34a1b76fbc21289\nPersonalizationString = 1d2be6f25e88fa30c4ef42e4d54efd957dec231fa00143ca47580be666a8c143a916c90b3819a0a7ea914e3c9a2e7a3f\nEntropyInputReseed = 6c1a089cae313363bc76a780139eb4f2f2048b1f6b07896c5c412bff0385440fc43b73facbb79e3a252fa01fe17ab391\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = e053c7d4bd9099ef6a99f190a5fd80219437d642006672338da6e0fe73ca4d24ffa51151bfbdac78d8a2f6255046edf57a04626e9977139c6933274299f3bdff\n\nEntropyInput = f1e0d7b1ac7e4e155bb588500f57d0c59969267ea5427e2d7fde1f9c54e67b7f6562bfc1019b8b5799d2a833fdccac79\nPersonalizationString = 86da37245d9bd1fb59a4bc7abd289ea2999258042c5fa696f2da7344bb6ebc5b770ca284bfe642570b52ef47b780d5c9\nEntropyInputReseed = 9c2c9c07cab12cf50f8846148034a416c83366c1e20776073751553cae69da8d1f6bce6bde27087659d69a62e2ba7c3c\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = e0ac06d7eae89469b6c14a31e7f0464ee21f7b30d2264c2de3e435cb40d0e5043ee13dfbc0342156750880b2d5dddb3bebb43b162a8478235c8b87f96d0284fd\n\nEntropyInput = 1dbee767e9916ab322ba461fbf9f7515cfbcb45944a7b471577da087690d94d967018b631e0c1f64da3c805d049f449a\nPersonalizationString = 966b5cd94019d4d90b48ea7f540a698cfe30d7eb25f5f7e5fe42d9f53ebed6e94e733b0794fc6bf30627911e20cc18e8\nEntropyInputReseed = 96e828128f183c76c90ec8341a43561368b77114048ccb05db66128d54c9539d1adc1d72f7fb0950e41b1343a9e4df76\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = c4d3f5c55d3979b174020650ad7a46b423ec446dff2a9e9fe0a782bf65a72d5fcb1896bc1092a8c73f41295e2e7044434f88aa0aca78f7eac40e322cb7c25563\n\nEntropyInput = df588bff3a1fc97a908067da6a7fef08c889ac29ad7d639bd047157bacab4dbdee3dffe575f37d071af94cbd7628d398\nPersonalizationString = 548715cfb28c1bc56453b8c39e24cfd64077c0f6e9d959d51b9f0667b97d3c4e1a179d1a554df845b24c26daec85845a\nEntropyInputReseed = f8c165b5ebd8347a2ffef2218f993877027e977598b4fdac2f65d8d994c7432900f8407ab5aed1885dee5aa2458f5998\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = deed18220bd8f72a34559924f3cad925ee717690f76bc223d5ffeebbb554b61b9d9eb6ac5697b06331e236672677e2e01d6e3fd581a4fa1ebad289797b68955f\n\nEntropyInput = 98555093e443fe8e2bc8d2eb4d3a7abb8eba00b25683a6b31191fff7c043665ec2cad3e99e55bbc241b8edc699dbc9ed\nPersonalizationString = 5627a0a55457db05e3903d4b69ce15f55f933168d6eb374c044e8f1040f61ed7eb24f87f91c68cde050f504b8965dd81\nEntropyInputReseed = 18d17e1b68378801f83e7aa9a6d4b84d3960022c740e6c845869a5db553d2e02479cd92f3c0d8abd3e92fc9c9fbc6a3f\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = 7a7f0ab07a540b4e9a3eda3f8bd1262015d8ea6d512dbea05942421f5a73242ac236009ef083bf2e51b19c40d1a019367a6b96fb52d254e4d881550aef0549ed\n\nEntropyInput = 07793bac6461f23e5eb0d1bc60b5f735515458d1530540df1c8e6fc5c3ebfb06b9db60a8947eb629ff7a375fe680d696\nPersonalizationString = c1e2132b77b6c15742e06e856c1549c4ccebd1b2eda93e2c43391b52cad51490fe34157f57be9eb4eff463b059986680\nEntropyInputReseed = 23e47e0c41462f7c619bbcd5b73f9ab1c68c7cdf1ec92c4c37126402958e110e329107742e70db611b93974c393936a6\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = e6dab4a887f48ec33cb293ffdab5fc69595f94c72c5a9bb43f468f75490190b7e0f14f5c04550cb62a6d0ee0c3d834be3434c8229c124087bb985a06b9a37267\n\nEntropyInput = 25cefa0512921fd4a3a4e5e7c48c6201185a6968419ae5bcc6667bb74c35de4f91988a33f25ea88a8443c65643cc73dd\nPersonalizationString = 07ddf125960c346680b4b361c0a9c6dc1008a85ce1861b45ff18907e6e7db41b046e5f016617e6c5b0ceb5575ac278a8\nEntropyInputReseed = 8cf41e5413b0c8ffacbc4dfc119f10b47569359b911448f45c7ad63dd58e872410c25176b986fee8b83966d0098d996a\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = ab58ec5c35600566dd2ee187a5b67dfa65bebe13333670d2a198fa5af0c20294c6cb69d37564d2b2587ea5587e12341e77f47f173d6cc9f9b9e5dedf0ee1a8d0\n\nEntropyInput = 929f1dec0a6d14de483a2fe114a430796d0b449fca56a4ddbbe661bdc26a8df85cafad7b677ccbf1fe4cb0d5e8cb57a9\nPersonalizationString = 0bf8c590a66653c0494750d10274b583d86e540b517bfc23bb3b0c9fde373e456558468603c2115c97d3662e6825f4f2\nEntropyInputReseed = 84030628534b7525dbd4023aed1ab08c4f2b86a7c2fa3bc9559b425cce07c34fac14e963256aea03f74f1122a7a30483\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = 199f2dce5bbe32c693151a216fb36ccea7996c313f6b78fa30ad812a0e603965023fc29706a71b753d79244cb9e8fdaff467e0f963426b10ad89a98e987af316\n\nEntropyInput = 7bc5d970186b9e1b0052b7564dbabf61c89cb3d64ff42f9a62d625112aca0486cdf0336c3612254b40cbfba83ab65b42\nPersonalizationString = a25326fef30f9c94423d99759a1ee575536a9715df9526de9a0b8dbcc3a2234cd835615f5dfe7823927355f569ec6f02\nEntropyInputReseed = ef8a0137013be212402e42b28c03ed6420881aa38b3a3e6e90a861116516df1ef732a19e8935ffcd9be7a2fc236783b7\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = 29f81ecf3f41d278c01bba9af9bc0fe6009539682f46723ce5b0ff75fed217ad71580b5dac46289e324d824094c332c3955c528257701a14ec2bfecce4f62a6c\n\nEntropyInput = 0c841a245a19295281163b07541590376d31d86a9be99e66cc22352dabb29f95e113ee233d74d3f2b7f2f608830525f0\nPersonalizationString = 28d3581054d87f153aee12edca47bad80bfc9b066ad1e8b9d96c851dc7b8ed768cad007b891d1c9447d43065b483d085\nEntropyInputReseed = 587a1dae75c2a1f2dea7fb42ef7bf38646b76a964ecd7043d8b62fdd9e6a5c007882f02f78fd040561d15a337e59f257\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = ba7bce080963fe2b4e8f0e1aa700e92b3908e18dc78728666904b0220e4077fef2cd18bbea29a2755a3499798cca445bb75269a5adca2f291dd3875457c69a89\n\nEntropyInput = f4afddabe515ca3e776730e7d44461b27e8f72407ca398d3fb578365e09ea8c24d6c4b09724907a610d755407d38667f\nPersonalizationString = 846bcbc7014ca8c6fb042a80d4a8c3aa50b6c5eff15e4b12f966ab17e6514cbb22fb2eed628ee5c2a8acde821a956078\nEntropyInputReseed = b2aeab1165b150908c9bb52c2b7167c149ea4fb4710edc8acfbc63f7652bb552d636a7e6fc3d1e74d3f65461baaac087\nAdditionalInputReseed =\nAdditionalInput1 =\nAdditionalInput2 =\nReturnedBits = 2a0335c3caeeec7c797f99fbc145654d3985c3c71025c8e4bd4b098801f15d21c272420417d805b0ad1ce68f904502a46130246315957bc07a5db4f3447a84e7\n\nEntropyInput = 6942413e05ac487cf539bc61aa6866ef8cbd9d0f15e1385f37bba5a951a29fc956d46f8740603af7c71800048c8312ad",
@@ -2594,14 +2614,14 @@
     "887d92419e3c839b8b1dc43c6507026f1f851e\nAdditionalInputReseed = 857848c62203307b39728acf11ac8462302d3a41d186778b3f112a86270252f058fbe5767496e47662186b8d0817de02\nAdditionalInput1 = 9a08df0de742fd2e2d55121a58b700dfbff250a4881b02fc3b8952b48ecd4d034d6e7c757cdf91bf7c31dfaf70b1da22\nAdditionalInput2 = 3bf0e4f1291a8bc272cc985878335882c75831510f27963c7c01a879c60c5b67a9a14a656a746a80a091adf6ffb1adf6\nReturnedBits = 69361d61f4cf5ed489888934f320a9acc5383e719f09a1e30b6029bf71d4b4cb54859798ace2d8ee5e681d4acb223b9c119dab2dd07e6db3f7f844c2b46b9c47\n\nEntropyInput = 6f45b55ac62d5ffd452d36b1e4b18cc6abd6ad93e87558b79fbe99b4f4a962b74bad00821019bd126d6f9dd73912acf7\nPersonalizationString = 913a783046baefe428346085fd640caa1874d4aa6974832cacc5b51e78514bcfedd174606bef1721df7a1194a0ccd1e3\nEntropyInputReseed = d9e19ce3197004ab3a4bf995a481149b6d8e59a3970161cb0d3917374c0c86bb5e9bc509bd01b6796fa1e77e5fdddb16\nAdditionalInputReseed = fd31068c90614e04463acdf856b034293a079a816f1c5f3de63b870a9876f7397d2f93bd3f6776b56a78f7178e1fbb87\nAdditionalInput1 = 068e3791b91adb820b27c45a5d8544eed3133486a7d2d0bc503d8abad8b7093f3df214f1e0ac4ff2d347c760b2a605d5\nAdditionalInput2 = 6c55927a349d321d1a2141aeccc3543e9726ffcf3d8fdfe1aed63c61972a213c12ea65d648e476268611e9b08486a648\nReturnedBits = 552b4c4035d964b5eb26e3036445793df67b7321d36e8d2362fe284503b587c961a33b816b40b93d4b006769177c6593c553b6e669076f25a3e2a7214156c249\n\nEntropyInput = 8d492df46257a62e717302992682e28494f84d0f3237c16439efbbd16a94b3356eb7f7c2a0206892045a0d7d36d69f03\nPersonalizationString = b915f3311feadf6676df2389baacccdafc74cf200ed7b99167b33dafa875ce4aac1a61ce54972ec54f9b0901a3b050ee\nEntropyInputReseed = 2e345fe3a471c5066b20f4aaeaaf73921426ac1bc0509e93671535a8fbc016f5967403d6d13b4760491bf973c47a8ed5\nAdditionalInputReseed = 2e8f1f01a7664890feef93152f7b7f05032b4c70c58b5f261ef0a9c2aef23f2a14ee57c3d3465af24289b1c850e52ef8\nAdditionalInput1 = f8c218c996284f757c491cba025fd84cc701f9f83a16f03c314712c2354fee39214ed5994ab24641826bc15ed1bb5f61\nAdditionalInput2 = 146c53dc4af90f26d8c85822810d9bde2949495c23ca2c7c13ceee8221cbe8105491d560e0044c8d50d7e365da41890b\nReturnedBits = b19dd18494235abdcb3b4e99c9355d19d543c7fb7e1048d63d9e25abcc12dcb31549cec2818667713ad1dc35142072ca8daa511927aca71303493e500503be8b\n\nEntropyInput = 2a595f08947d0056ed19ecc8a547867834c125cf1740230a1325b93bf29951cbedcaa6a8f5cbe69801fb9a197ad576c6\nPersonalizationString = c0fb9dbea13863dfbfdb2c0dd864887413794a07a4dd228836f0f6afab901496486a2d508a3f4b784d83382629cddbc1\nEntropyInputReseed = a3ddfc3aefc94dcaf656f4d8eef0065a6d233a76e0a4c26e2d8bbb86459c9e4a173ff8cbec85ebc14712640741427668\nAdditionalInputReseed = d4eb9b12fc2a6fc75a69701c8b5ece02e47f813effb705dbdef0294e38907f5aadf40bdbcc067d0ebc0bf3661a2e0990\nAdditionalInput1 = d3c4bf4f8a3f61413fe1953523ba83bc02ae6d7eea1c8ba288f8e06f0d0276e61667a410f90548d283c4f1ae79483961\nAdditionalInput2 = e6fc29680eef141e1372e17729c9f4407b3f7a57057be1081ce46c78693334bf56867791072d9d18a7b4835bf251712d\nReturnedBits = 08475bfb8e621e12e212f4960e737023f7a3de3b204b6ffeeb929f424ca78c6ae2e0d726237915e5e244616713e88a39df302208e3a324f5444213b70b2e9c09\n\nEntropyInput = 3d5332b91dcaad893df504c7c675b69890b28055dfd3ec7d0ba56990dcda175096ff8f8f9f9ecd6dddeb96b829b98c3e\nPersonalizationString = 34753432b3c6bedc4d2296dffce8a66591b400867f7edf10cee447046f5f767036da9f3f4a02f7b8cba7bdd4365c1fef\nEntropyInputReseed = 1a69af0ff696f9a2fe0fddd26ccf6fae215faf91804461928c884eec13b1dd1501862a738373454e1b449c6026cebceb\nAdditionalInputReseed = dc47e104175f3c9812feed9e143da5cd7e553e3423db5bc8be3b652f577100267ff795804aaf42c3991589e7688a977b\nAdditionalInput1 = e64c0cad3dfc0bf0eba3317cf37b7779b91bf3de3e0ba36d3e16feb0014286596edd364c197847e8732925f971294dfa\nAdditionalInput2 = 1ff3a6bdb7e319a86b35d062cf017ed270c6b5511bc3d63083272e76bf4db9d90e836f18d98f1f79c2e91eeb0bc635e2\nReturnedBits = fdef7e67c3d19f5f74784bdc64d2c23d0a3f027846da2b2afba940fdc2f066d89b63d27e55d3d0a88bddb97e29676894ec8a18268e4bc27d181a867c5a80fe2c\n\nEntropyInput = 156c8c0f44f4a8f17044957b572ed16d54b73a9510d2b260a036ad6ef223f45e124c4ae9dae0fdf5684792da0ff5ea0a\nPersonalizationString = 1472f56d5498564a5b53d2eae27103f41f565d7873b37c37c30472075f1d84d69a8d68c92636ae06aa61678358cc47d4\nEntropyInputReseed = 6bc2bfd44f72982b23b6d22c85f7d601d5941ebe6e9ee9d06a8efe652539ec00b1136adbc4e43aaab76c3ad6a57a267e\nAdditionalInputReseed = a83b1547fadb97e491ef0bdb8b0d006ab16638fdb211613051f0f57586c146882f1062b7f71a8c15bb27200fa83ffcaf\nAdditionalInput1 = ac188da8a895e0807bab61b1ebd73acbe43f99f375c7d29174f675e1667237cedf1d41fc50da277a0db21ee2891a5abf\nAdditionalInput2 = adf9a30b6cd9dac23f193f66df9d606a5765b96cc42c099530c53c26a6d6bcf0779ae060d188e1cc5bdab6c312892267\nReturnedBits = fcc79828bf2c9d3d799d7a0e83583c70aeb156e25df0b2fde030c2775c9986c8054e848128ba38ff5e5b0b1e5b72f9e41726b960008408f5152b1a47072fbdf7\n\nEntropyInput = 5e0dd8e37aa23d0fe79efcb8e5538ee90ffb5733decc83f7677488c4f64c2e0d2a918968a5c7351de9360f23fe606a4a\nPersonalizationString = 5161b794e4a13371b320ae4b2b6b698e4df507402a7582555598089dd9484358d37f891294948512e4198a79de8ca3d9\nEntropyInputReseed = 850ffb89bc23562f3ea03947c1afa7309a0ccdc0b714bc94ff45d66884b74fba0bffce97887f2efc178388f36f0ea95e\nAdditionalInputReseed = 50f605cb940f573c4ef3ddff8caa9a3f544f40fdf583b82cd79338523d896f72f86be1f9bb37d9aca02a2856f713c812\nAdditionalInput1 = da7bcf6810a6b3820548065edbec0fa2fd4bc03e5d50666f98a8bea6b744e04aafa0714582f11b6608852c45ee51df6b\nAdditionalInput2 = 4e9c0c770699656217a0b2dbb466a0fcb0cdb5d4a4a05da40fa2eb546f2f0f28aea575a0bdf6e89352d519db44f47dc5\nReturnedBits = 40ec0e8e3e54cd4fd78f5e006bf3134c378ba619ccf9e7530c79217da631458b5f9135bc8b0d6f2e742c53b58d0ebc18263f9d2ef37a2fa0fb086d2193857863\n\nEntropyInput = 219a364ad362fd8a1d69c1284fd64cc9ec05e6bfbdd133ac9170594b5d95946d3dda2ebcc58deeace86f9dca5ad99c18\nPersonalizationString = b0b27b03fc65effe4610e61916f2e9bd252d47efcc08b84aa505b1befd3a7e9295ca764ac88f099bbecc28301f0f298e\nEntropyInputReseed = 1bccdb4b2ce863fbee104d7a56f2cd88a44a088392883a6db30e6fc7bf5611759c71d53a61fe62b6314d7426e510a722\nAdditionalInputReseed = a06eab3b05eb3649a01be82a356030effdbf45fd71f49b1862ecf33fdb28a7191a34f104b9eda1da4ba48daf9da381b6\nAdditionalInput1 = 88b17e13e02a7e9a3f8263946fae0b6a9052692c3c5cbe858369c4d0b198b9c6a8f4c87ff5e6b2835a7944b911266aa9\nAdditionalInput2 = 828222c8a275427a5f8a963d0d65e92f6170d5089c9a162429c093a28dd69f71135342f16b3baea9a4764e2cc3762267\nReturnedBits = a739f9fee9a40049e42b00b381a1f663877abb776ec655e3a7870bd94bea1a25d3c6d380eced435e498044daf78b349bc1868e4bff6257cf2711ed08e2357201\n\nEntropyInput = f8513c2f6e46f75fce3671ccb3c69158583a873b0dda83d8b1cd548f4e5efd75642f2c23cf8792d51023f31d795f6f5b\nPersonalizationString = e94f7212257885511b15a873d0158fa5ea648846afbcf9d62a7abc4e6909dd43c671fa18bc289f47e2301e9aa69c3e88\nEntropyInputReseed = 487b9c1866ffdaaf6760cdee3df5a930196d30b0ac8db780656577ddfc1ff3508c451ef2b0b478a2cf0c73027597b2ae\nAdditionalInputReseed = 7387b59f8c78e79d36edacbb428fd515ef9e58086059bf7fd642053b0f5706cfe86eb3c35ca0b6f02e5d1304e476e3cf\nAdditionalInput1 = bafc59ef40e59d8c28851212e1c357cce0d06f02c69d14585170ca8eb18396a331d635cf0651319842cee2f7c87285c2\nAdditionalInput2 = 82d905ba69b6c45ca28107beb6698a152631ab48614235f6a9f12e019f66bf326151d9ee84e0cd42b6566dbffb46ec35\nReturnedBits = 163f48d09f3e9ebf9f8647766a0b2e189a2f3a21a5a4e31c8a4f3bd138cc50030ac8bea1c4d9e9aa0b67f34926239fbcedfd1992da165b941cf03b56737737b2\n\nEntropyInput = 0a8f092764d473d48215e947ea8a32b5da8ea86d8ed0d83bce31b1b5a21e7c5f1af2186a39caf9afa61644caef02ef9b\nPersonalizationString = 84637faba756917b0f44ba2e0e26546f5239782e4d9f952ee251367081629e71c20a7459995a7563810daeab74220664\nEntropyInputReseed = eacaded3d89a63b94a5c14c3087306e670fc4ee7d56cafef4c5aa7d553ca89ed34418056a44f5447e2b07dd541ac4645\nAdditionalInputReseed = 104a1541313fc4be9d34bced288c1c1b6fa793e9096f8be5673a2c6825dabef91fd88e45a061b2d897f9b5e8a8ae0ad3\nAdditionalInput1 = e30c9d8aba0bd5dc63d911897e4dcadbeacc3ed9392d8e361b356e02a81d65bdab91f7e9f8dd2b2bf9af0da5100e77d4\nAdditionalInput2 = 2bed42b8c05461ba2756a5f38393d5538d20eb9cf1c06775e7fef7284341f61ccd34b0148d1e870c1992dfd065560ed6\nReturnedBits = 855a6af3e6dddf194ceaafcef6f7ee91f489a61a73b759d41be4d5298510b9902f5b78b1162cba417684519634b578afda9802bd782f04b3a25106f3586ad8a4\n\nEntropyInput =",
     " ed63e3b88a2f0d6a40b7b36a06cd8d40ec10158ab6c4f8dabdb879e45d22db573320d2641bfd7db31eb6bbf4c6330b9f\nPersonalizationString = f82a5ee81f349a69dfa6a6e53b406bb560cb0339f61b3886237023ae4582b9725b8774a8044ec5134ebd4d7606f18188\nEntropyInputReseed = 7104522c2a69bec7e010d9670d7ab92dd817ac7ff05d63ab0e12d431d4c9aef4d715421c1fb5d05d3aecba36859a6038\nAdditionalInputReseed = 3b83034ea440604d0b7d04857623e9adc0eb9aad4a45b2079863eed3d72e65abf67d255673e769a2e2584eea59f1ebaa\nAdditionalInput1 = 8678e4f831887e96a27c3a8ce0963f4b34bbca25791b06526cb6c55624c33d98a0356be624238cecacba3535e872c4c7\nAdditionalInput2 = ec3452ea2722984bbe6a5b7c22ad58df37a854abc8630b9e21bcd0469eb207e5f44e044f5f666920dd55e81a393500de\nReturnedBits = c340765fe7a3479bef2d7d59e321066f8ad0db53aed4c517bf8339566bf877d53921e6de2650d0080529004a5fd32124ce8e58a040e2d55656b37d9ea827cb91\n\nEntropyInput = 882ed05487dce4b4f9e58ec4f2da1fa5d8ebb4ef9fcbf7b0a0e15c4dccb8e19788f86dcf2885e71a20cbd9ac10a6648e\nPersonalizationString = 05f5bc41687ea1e4c34a69944fbae283cfee4c42b1bbd78fddb0973d0fca948539b6843658b67c30b73191b9a0bf2921\nEntropyInputReseed = ca1603d4c8711404c7bdc12c7c75b2943a4b042ea1d2eb54506a6876952157caf3b152dc75f27f2213645a141577e8ba\nAdditionalInputReseed = 83cda53380888d53515e58154f89d5528ab69f31fbcfca34988cf03c4cae5f60aa6291f32d99ab2a726b6e08d2502cf5\nAdditionalInput1 = 5bf5ca9f964edd91e8ef491fd3cd32faf9cb9d1993d8221914d1751fb0d4252a5ca950e213f088050900b2bd74f5e336\nAdditionalInput2 = dba28dc1d8d615651547867d4ef42519045ee16378143685101da47a27b55498078e8a8f4854052f7cc6f5b02e571ae8\nReturnedBits = 01f11971835819c1148aa079eea09fd5b1aa3ac6ba557ae3317b1a33f4505174cf9d7e940821c9b0e5527a1d3e186a7a83f187c62d3223cf5964ff9526d8484c\n",
 };
-static const size_t kLen37 = 157331;
-
-static const char *kData38[] = {
-    "HMAC = MD5\n# Note: The empty key results in passing NULL to HMAC_Init_ex, so this tests\n# that HMAC_CTX and HMAC treat NULL as the empty key initially.\nKey =\nInput = \"More text test vectors to stuff up EBCDIC machines :-)\"\nOutput = e9139d1e6ee064ef8cf514fc7dc83e86\n\n# HMAC tests from RFC2104\nHMAC = MD5\nKey = 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b\nInput = \"Hi There\"\nOutput = 9294727a3638bb1c13f48ef8158bfc9d\n\nHMAC = MD5\nKey = \"Jefe\"\nInput = \"what do ya want for nothing?\"\nOutput = 750c783e6ab0b503eaa86e310a5db738\n\nHMAC = MD5\nKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nInput = DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\nOutput = 56be34521d144c88dbb8c733f0e8b3f6\n\n# HMAC tests from NIST test data\n\nHMAC = SHA1\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\nOutput = 5FD596EE78D5553C8FF4E72D266DFD192366DA29\n\nHMAC = SHA1\nInput = \"Sample message for keylen<blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F10111213\nOutput = 4C99FF0CB1B31BD33F8431DBAF4D17FCD356A807\n\nHMAC = SHA1\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F60616263\nOutput = 2D51B2F7750E410584662E38F133435F4C4FD42A\n\nHMAC = SHA224\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\nOutput = C7405E3AE058E8CD30B08B4140248581ED174CB34E1224BCC1EFC81B\n\nHMAC = SHA224\nInput = \"Sample message for keylen<blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B\nOutput = E3D249A8CFB67EF8B7A169E9A0A599714A2CECBA65999A51BEB8FBBE\n\nHMAC = SHA224\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F60616263\nOutput = 91C52509E5AF8531601AE6230099D90BEF88AAEFB961F4080ABC014D\n\nHMAC = SHA256\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\nOutput = 8BB9A1DB9806F20DF7F77B82138C7914D174D59E13DC4D0169C9057B133E1D62\n\nHMAC = SHA256\nInput = \"Sample message for keylen<blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\nOutput = A28CF43130EE696A98F14A37678B56BCFCBDD9E5CF69717FECF5480F0EBDF790\n\nHMAC = SHA256\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F60616263\nOutput = BDCCB6C72DDEADB500AE768386CB38CC41C63DBB0878DDB9C7A38A431B78378D\n\nHMAC = SHA384\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\nOutput = 63C5DAA5E651847CA897C95814AB830BEDEDC7D25E83EEF9195CD45857A37F448947858F5AF50CC2B1B730DDF29671A9\n\nHMAC = SHA384\nInput = \"Sample message for keylen<blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F\nOutput = 6EB242BDBB582CA17BEBFA481B1E23211464D2B7F8C20B9FF2201637B93646AF5AE9AC316E98DB45D9CAE773675EEED0\n\nHMAC = SHA384\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7\nOutput = 5B664436DF69B0CA22551231A3F0A3D5B4F97991713CFA84BFF4D0792EFF96C27DCCBBB6F79B65D548B40E8564CEF594\n\nHMAC = SHA512\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\nOutput = FC25E240658CA785B7A811A8D3F7B4CA48CFA26A8A366BF2CD1F836B05FCB024BD36853081811D6CEA4216EBAD79DA1CFCB95EA4586B8A0CE356596A55FB1347\n\nHMAC = SHA512\nInput = \"Sample message for keylen<blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\nOutput = FD44C18BDA0BB0A6CE0E82B031BF2818F6539BD56EC00BDC10A8A2D730B3634DE2545D639B0F2CF710D0692C72A1896F1F211C2B922D1A96C392E07E7EA9FEDC\n\nHMAC = SHA512\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7\nOutput = D93EC8D2DE1AD2A9957CB9B83F14E76AD6B5E0CCE285079A127D3B14BCCB7AA7286D4AC0D4CE64215F2BC9E6870B33D97438BE4AAA20CDA5C5A912B48B8E27F3\n\n# Additional HMAC tests from OpenSSL.\nHMAC = SHA1\nInput = \"My test data\"\nKey =\nOutput = 61afdecb95429ef494d61fdee15990cabf0826fc\n\nHMAC = SHA256\nInput = \"My test data\"\nKey =\nOutput = 2274b195d90ce8e03406f4b526a47e0787a88a65479938f1a5baa3ce0f079776\n\nHMAC = SHA256\nInput = \"My test data\"\nKey = \"123456\"\nOutput = bab53058ae861a7f191abe2d0145cbb123776a6369ee3f9d79ce455667e411dd\n\nHMAC = SHA1\nInput = \"My test data\"\nKey = \"12345\"\nOutput = 7dbe8c764c068e3bcd6e6b0fbcd5e6fc197b15bb\n",
-};
-static const size_t kLen38 = 6201;
+static const size_t kLen38 = 157331;
 
 static const char *kData39[] = {
+    "HMAC = MD5\n# Note: The empty key results in passing NULL to HMAC_Init_ex, so this tests\n# that HMAC_CTX and HMAC treat NULL as the empty key initially.\nKey =\nInput = \"More text test vectors to stuff up EBCDIC machines :-)\"\nOutput = e9139d1e6ee064ef8cf514fc7dc83e86\n\n# HMAC tests from RFC2104\nHMAC = MD5\nKey = 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b\nInput = \"Hi There\"\nOutput = 9294727a3638bb1c13f48ef8158bfc9d\n\nHMAC = MD5\nKey = \"Jefe\"\nInput = \"what do ya want for nothing?\"\nOutput = 750c783e6ab0b503eaa86e310a5db738\n\nHMAC = MD5\nKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nInput = DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\nOutput = 56be34521d144c88dbb8c733f0e8b3f6\n\n# HMAC tests from NIST test data\n\nHMAC = SHA1\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\nOutput = 5FD596EE78D5553C8FF4E72D266DFD192366DA29\n\nHMAC = SHA1\nInput = \"Sample message for keylen<blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F10111213\nOutput = 4C99FF0CB1B31BD33F8431DBAF4D17FCD356A807\n\nHMAC = SHA1\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F60616263\nOutput = 2D51B2F7750E410584662E38F133435F4C4FD42A\n\nHMAC = SHA224\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\nOutput = C7405E3AE058E8CD30B08B4140248581ED174CB34E1224BCC1EFC81B\n\nHMAC = SHA224\nInput = \"Sample message for keylen<blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B\nOutput = E3D249A8CFB67EF8B7A169E9A0A599714A2CECBA65999A51BEB8FBBE\n\nHMAC = SHA224\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F60616263\nOutput = 91C52509E5AF8531601AE6230099D90BEF88AAEFB961F4080ABC014D\n\nHMAC = SHA256\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\nOutput = 8BB9A1DB9806F20DF7F77B82138C7914D174D59E13DC4D0169C9057B133E1D62\n\nHMAC = SHA256\nInput = \"Sample message for keylen<blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\nOutput = A28CF43130EE696A98F14A37678B56BCFCBDD9E5CF69717FECF5480F0EBDF790\n\nHMAC = SHA256\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F60616263\nOutput = BDCCB6C72DDEADB500AE768386CB38CC41C63DBB0878DDB9C7A38A431B78378D\n\nHMAC = SHA384\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\nOutput = 63C5DAA5E651847CA897C95814AB830BEDEDC7D25E83EEF9195CD45857A37F448947858F5AF50CC2B1B730DDF29671A9\n\nHMAC = SHA384\nInput = \"Sample message for keylen<blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F\nOutput = 6EB242BDBB582CA17BEBFA481B1E23211464D2B7F8C20B9FF2201637B93646AF5AE9AC316E98DB45D9CAE773675EEED0\n\nHMAC = SHA384\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7\nOutput = 5B664436DF69B0CA22551231A3F0A3D5B4F97991713CFA84BFF4D0792EFF96C27DCCBBB6F79B65D548B40E8564CEF594\n\nHMAC = SHA512\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\nOutput = FC25E240658CA785B7A811A8D3F7B4CA48CFA26A8A366BF2CD1F836B05FCB024BD36853081811D6CEA4216EBAD79DA1CFCB95EA4586B8A0CE356596A55FB1347\n\nHMAC = SHA512\nInput = \"Sample message for keylen<blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\nOutput = FD44C18BDA0BB0A6CE0E82B031BF2818F6539BD56EC00BDC10A8A2D730B3634DE2545D639B0F2CF710D0692C72A1896F1F211C2B922D1A96C392E07E7EA9FEDC\n\nHMAC = SHA512\nInput = \"Sample message for keylen=blocklen\"\nKey = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7\nOutput = D93EC8D2DE1AD2A9957CB9B83F14E76AD6B5E0CCE285079A127D3B14BCCB7AA7286D4AC0D4CE64215F2BC9E6870B33D97438BE4AAA20CDA5C5A912B48B8E27F3\n\n# Additional HMAC tests from OpenSSL.\nHMAC = SHA1\nInput = \"My test data\"\nKey =\nOutput = 61afdecb95429ef494d61fdee15990cabf0826fc\n\nHMAC = SHA256\nInput = \"My test data\"\nKey =\nOutput = 2274b195d90ce8e03406f4b526a47e0787a88a65479938f1a5baa3ce0f079776\n\nHMAC = SHA256\nInput = \"My test data\"\nKey = \"123456\"\nOutput = bab53058ae861a7f191abe2d0145cbb123776a6369ee3f9d79ce455667e411dd\n\nHMAC = SHA1\nInput = \"My test data\"\nKey = \"12345\"\nOutput = 7dbe8c764c068e3bcd6e6b0fbcd5e6fc197b15bb\n",
+};
+static const size_t kLen39 = 6201;
+
+static const char *kData40[] = {
     "# RFC 7539, section 2.5.2.\n\nKey = 85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b\nInput = \"Cryptographic Forum Research Group\"\nMAC = a8061dc1305136c6c22b8baf0c0127a9\n\n\n# RFC 7539, section A.3.\n\nKey = 0000000000000000000000000000000000000000000000000000000000000000\nInput = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\nMAC = 00000000000000000000000000000000\n\nKey = 0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e\nInput = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f\nMAC = 36e5f6b5c5e06070f0efca96227a863e\n\nKey = 36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000\nInput = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f\nMAC = f3477e7cd95417af89a6b8794c310cf0\n\nKey = 1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0\nInput = 2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e\nMAC = 4541669a7eaaee61e708dc7cbcc5eb62\n\nKey = 0200000000000000000000000000000000000000000000000000000000000000\nInput = ffffffffffffffffffffffffffffffff\nMAC = 03000000000000000000000000000000\n\nKey = 02000000000000000000000000000000ffffffffffffffffffffffffffffffff\nInput = 02000000000000000000000000000000\nMAC = 03000000000000000000000000000000\n\nKey = 0100000000000000000000000000000000000000000000000000000000000000\nInput = fffffffffffffffffffffffffffffffff0ffffffffffffffffffffffffffffff11000000000000000000000000000000\nMAC = 05000000000000000000000000000000\n\nKey = 0100000000000000000000000000000000000000000000000000000000000000\nInput = fffffffffffffffffffffffffffffffffbfefefefefefefefefefefefefefefe01010101010101010101010101010101\nMAC = 00000000000000000000000000000000\n\nKey = 0200000000000000000000000000000000000000000000000000000000000000\nInput = fdffffffffffffffffffffffffffffff\nMAC = faffffffffffffffffffffffffffffff\n\nKey = 0100000000000000040000000000000000000000000000000000000000000000\nInput = e33594d7505e43b900000000000000003394d7505e4379cd01000000000000000000000000000000000000000000000001000000000000000000000000000000\nMAC = 14000000000000005500000000000000\n\nKey = 0100000000000000040000000000000000000000000000000000000000000000\nInput = e33594d7505e43b900000000000000003394d7505e4379cd010000000000000000000000000000000000000000000000\nMAC = 13000000000000000000000000000000\n\n\n# Additional test vectors that are long enough to ensure OpenSSL's SIMD\n# assembly is fully tested.\n\n# Length 2048.\nKey = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\nInput = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72",
     "c924bba2a8b4e8354188ebfed\nMAC = 69d28f73dd09d39a92aa179da354b7ea\n\n# Length 2049.\nKey = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\nInput = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc8\nMAC = d6a26654b88572e875d9661c83471c1b\n\n# Length 2050.\nKey = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\nInput = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe",
     "23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852\nMAC = 9fbbb7f7adcd0cd5b46a4a520b22499a\n\n# Length 2051.\nKey = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\nInput = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f5\nMAC = eb7cdceb97ade2a07622f8f5a4b1ce15\n\n# Length 2052.\nKey = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\nInput = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f9",
@@ -2613,7 +2633,7 @@
     "90485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e21\nMAC = c6e5d1810fd878ac6b844c66cef36a22\n\n# Length 2063.\nKey = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\nInput = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e21df\nMAC = f6eaae369c3cb5c05748e8d919178e00\n\n# Regression test for https://rt.openssl.org/Ticket/Display.html?id=4439\nKey = 2d773be37adb1e4d683bf0075e79c4ee037918535a7f99ccb7040fb5f5f43aea\nInput = 89dab80b7717c1db5db437860a3f70218e93e1b8f461fb677f16f35f6f87e2a91c99bc3a47ace47640cc95c345be5ecca5a3523c35cc01893af0b64a620334270372ec12482d1b1e363561698a578b359803495bb4e2ef1930b17a5190b580f141300df30adbeca28f6427a8bc1a999fd51c554a017d095d8c3e3127daf9f595\nMAC = c85d15ed44c378d6b00e23064c7bcd51\n\n# Regression tests for https://rt.openssl.org/Ticket/Display.html?id=4483\n\nKey = 7f1b02640000000000000000000000000000000000000000cccccccccccccccc\nInput = cccccccccccccccccccccccccccccccccccccccccccccccccc80ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccceccccccccccccccccccccccccccccccccccccc5cccccccccccccccccccccccccccccccccccccccccce3ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccaccccccccccccccccccccce6cccccccccc000000afccccccccccccccccccfffffff5000000000000000000000000000000000000000000000000000000ffffffe70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000719205a8521dfc\nMAC = 8559b876eceed66eb37798c0457baff9\n\nKey = e00016000000000000000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaa\nInput = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa000000000000000000800264\nMAC = 00bd1258978e205444c9aaaa82006fed\n\nKey = 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c\nInput = 02fc\nMAC = 06120c0c0c0c0c0c0c0c0c0c0c0c0c0c\n\nKey = 00ff000000000000000000000000000000000000001e00000000000000007b7b\nInput = 7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b5c7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b",
     "7b7b7b7b7b7b7b7b7b7b7b7b7b6e7b007b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b5c7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b6e7b001300000000b300000000000000000000000000000000000000000000f20000000000000000000000000000000000002000efff0009000000000000000000000000100000000009000000640000000000000000000000001300000000b300000000000000000000000000000000000000000000f20000000000000000000000000000000000002000efff00090000000000000000007a000010000000000900000064000000000000000000000000000000000000000000000000fc\nMAC = 33205bbf9e9f8f7212ab9e2ab9b7e4a5\n",
 };
-static const size_t kLen39 = 74392;
+static const size_t kLen40 = 74392;
 
 static std::string AssembleString(const char **data, size_t len) {
   std::string ret;
@@ -2724,30 +2744,33 @@
   if (strcmp(path, "crypto/ecdh/ecdh_tests.txt") == 0) {
     return AssembleString(kData31, kLen31);
   }
-  if (strcmp(path, "crypto/fipsmodule/aes/aes_tests.txt") == 0) {
+  if (strcmp(path, "crypto/evp/evp_tests.txt") == 0) {
     return AssembleString(kData32, kLen32);
   }
-  if (strcmp(path, "crypto/fipsmodule/bn/bn_tests.txt") == 0) {
+  if (strcmp(path, "crypto/fipsmodule/aes/aes_tests.txt") == 0) {
     return AssembleString(kData33, kLen33);
   }
-  if (strcmp(path, "crypto/fipsmodule/ecdsa/ecdsa_sign_tests.txt") == 0) {
+  if (strcmp(path, "crypto/fipsmodule/bn/bn_tests.txt") == 0) {
     return AssembleString(kData34, kLen34);
   }
-  if (strcmp(path, "crypto/fipsmodule/ecdsa/ecdsa_verify_tests.txt") == 0) {
+  if (strcmp(path, "crypto/fipsmodule/ecdsa/ecdsa_sign_tests.txt") == 0) {
     return AssembleString(kData35, kLen35);
   }
-  if (strcmp(path, "crypto/fipsmodule/modes/gcm_tests.txt") == 0) {
+  if (strcmp(path, "crypto/fipsmodule/ecdsa/ecdsa_verify_tests.txt") == 0) {
     return AssembleString(kData36, kLen36);
   }
-  if (strcmp(path, "crypto/fipsmodule/rand/ctrdrbg_vectors.txt") == 0) {
+  if (strcmp(path, "crypto/fipsmodule/modes/gcm_tests.txt") == 0) {
     return AssembleString(kData37, kLen37);
   }
-  if (strcmp(path, "crypto/hmac_extra/hmac_tests.txt") == 0) {
+  if (strcmp(path, "crypto/fipsmodule/rand/ctrdrbg_vectors.txt") == 0) {
     return AssembleString(kData38, kLen38);
   }
-  if (strcmp(path, "crypto/poly1305/poly1305_tests.txt") == 0) {
+  if (strcmp(path, "crypto/hmac_extra/hmac_tests.txt") == 0) {
     return AssembleString(kData39, kLen39);
   }
+  if (strcmp(path, "crypto/poly1305/poly1305_tests.txt") == 0) {
+    return AssembleString(kData40, kLen40);
+  }
   fprintf(stderr, "File not embedded: %s.\n", path);
   abort();
 }
diff --git a/third_party/boringssl/ios-aarch64/crypto/chacha/chacha-armv8.S b/third_party/boringssl/ios-aarch64/crypto/chacha/chacha-armv8.S
new file mode 100644
index 0000000..195e8f0
--- /dev/null
+++ b/third_party/boringssl/ios-aarch64/crypto/chacha/chacha-armv8.S
@@ -0,0 +1,1969 @@
+#include <openssl/arm_arch.h>
+
+.text
+
+
+
+.align	5
+Lsigma:
+.quad	0x3320646e61707865,0x6b20657479622d32		// endian-neutral
+Lone:
+.long	1,0,0,0
+LOPENSSL_armcap_P:
+#ifdef	__ILP32__
+.long	_OPENSSL_armcap_P-.
+#else
+.quad	_OPENSSL_armcap_P-.
+#endif
+.byte	67,104,97,67,104,97,50,48,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+
+.globl	_ChaCha20_ctr32
+.private_extern	_ChaCha20_ctr32
+
+.align	5
+_ChaCha20_ctr32:
+	cbz	x2,Labort
+	adr	x5,LOPENSSL_armcap_P
+	cmp	x2,#192
+	b.lo	Lshort
+#ifdef	__ILP32__
+	ldrsw	x6,[x5]
+#else
+	ldr	x6,[x5]
+#endif
+	ldr	w17,[x6,x5]
+	tst	w17,#ARMV7_NEON
+	b.ne	ChaCha20_neon
+
+Lshort:
+	stp	x29,x30,[sp,#-96]!
+	add	x29,sp,#0
+
+	adr	x5,Lsigma
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+	sub	sp,sp,#64
+
+	ldp	x22,x23,[x5]		// load sigma
+	ldp	x24,x25,[x3]		// load key
+	ldp	x26,x27,[x3,#16]
+	ldp	x28,x30,[x4]		// load counter
+#ifdef	__ARMEB__
+	ror	x24,x24,#32
+	ror	x25,x25,#32
+	ror	x26,x26,#32
+	ror	x27,x27,#32
+	ror	x28,x28,#32
+	ror	x30,x30,#32
+#endif
+
+Loop_outer:
+	mov	w5,w22			// unpack key block
+	lsr	x6,x22,#32
+	mov	w7,w23
+	lsr	x8,x23,#32
+	mov	w9,w24
+	lsr	x10,x24,#32
+	mov	w11,w25
+	lsr	x12,x25,#32
+	mov	w13,w26
+	lsr	x14,x26,#32
+	mov	w15,w27
+	lsr	x16,x27,#32
+	mov	w17,w28
+	lsr	x19,x28,#32
+	mov	w20,w30
+	lsr	x21,x30,#32
+
+	mov	x4,#10
+	subs	x2,x2,#64
+Loop:
+	sub	x4,x4,#1
+	add	w5,w5,w9
+	add	w6,w6,w10
+	add	w7,w7,w11
+	add	w8,w8,w12
+	eor	w17,w17,w5
+	eor	w19,w19,w6
+	eor	w20,w20,w7
+	eor	w21,w21,w8
+	ror	w17,w17,#16
+	ror	w19,w19,#16
+	ror	w20,w20,#16
+	ror	w21,w21,#16
+	add	w13,w13,w17
+	add	w14,w14,w19
+	add	w15,w15,w20
+	add	w16,w16,w21
+	eor	w9,w9,w13
+	eor	w10,w10,w14
+	eor	w11,w11,w15
+	eor	w12,w12,w16
+	ror	w9,w9,#20
+	ror	w10,w10,#20
+	ror	w11,w11,#20
+	ror	w12,w12,#20
+	add	w5,w5,w9
+	add	w6,w6,w10
+	add	w7,w7,w11
+	add	w8,w8,w12
+	eor	w17,w17,w5
+	eor	w19,w19,w6
+	eor	w20,w20,w7
+	eor	w21,w21,w8
+	ror	w17,w17,#24
+	ror	w19,w19,#24
+	ror	w20,w20,#24
+	ror	w21,w21,#24
+	add	w13,w13,w17
+	add	w14,w14,w19
+	add	w15,w15,w20
+	add	w16,w16,w21
+	eor	w9,w9,w13
+	eor	w10,w10,w14
+	eor	w11,w11,w15
+	eor	w12,w12,w16
+	ror	w9,w9,#25
+	ror	w10,w10,#25
+	ror	w11,w11,#25
+	ror	w12,w12,#25
+	add	w5,w5,w10
+	add	w6,w6,w11
+	add	w7,w7,w12
+	add	w8,w8,w9
+	eor	w21,w21,w5
+	eor	w17,w17,w6
+	eor	w19,w19,w7
+	eor	w20,w20,w8
+	ror	w21,w21,#16
+	ror	w17,w17,#16
+	ror	w19,w19,#16
+	ror	w20,w20,#16
+	add	w15,w15,w21
+	add	w16,w16,w17
+	add	w13,w13,w19
+	add	w14,w14,w20
+	eor	w10,w10,w15
+	eor	w11,w11,w16
+	eor	w12,w12,w13
+	eor	w9,w9,w14
+	ror	w10,w10,#20
+	ror	w11,w11,#20
+	ror	w12,w12,#20
+	ror	w9,w9,#20
+	add	w5,w5,w10
+	add	w6,w6,w11
+	add	w7,w7,w12
+	add	w8,w8,w9
+	eor	w21,w21,w5
+	eor	w17,w17,w6
+	eor	w19,w19,w7
+	eor	w20,w20,w8
+	ror	w21,w21,#24
+	ror	w17,w17,#24
+	ror	w19,w19,#24
+	ror	w20,w20,#24
+	add	w15,w15,w21
+	add	w16,w16,w17
+	add	w13,w13,w19
+	add	w14,w14,w20
+	eor	w10,w10,w15
+	eor	w11,w11,w16
+	eor	w12,w12,w13
+	eor	w9,w9,w14
+	ror	w10,w10,#25
+	ror	w11,w11,#25
+	ror	w12,w12,#25
+	ror	w9,w9,#25
+	cbnz	x4,Loop
+
+	add	w5,w5,w22		// accumulate key block
+	add	x6,x6,x22,lsr#32
+	add	w7,w7,w23
+	add	x8,x8,x23,lsr#32
+	add	w9,w9,w24
+	add	x10,x10,x24,lsr#32
+	add	w11,w11,w25
+	add	x12,x12,x25,lsr#32
+	add	w13,w13,w26
+	add	x14,x14,x26,lsr#32
+	add	w15,w15,w27
+	add	x16,x16,x27,lsr#32
+	add	w17,w17,w28
+	add	x19,x19,x28,lsr#32
+	add	w20,w20,w30
+	add	x21,x21,x30,lsr#32
+
+	b.lo	Ltail
+
+	add	x5,x5,x6,lsl#32	// pack
+	add	x7,x7,x8,lsl#32
+	ldp	x6,x8,[x1,#0]		// load input
+	add	x9,x9,x10,lsl#32
+	add	x11,x11,x12,lsl#32
+	ldp	x10,x12,[x1,#16]
+	add	x13,x13,x14,lsl#32
+	add	x15,x15,x16,lsl#32
+	ldp	x14,x16,[x1,#32]
+	add	x17,x17,x19,lsl#32
+	add	x20,x20,x21,lsl#32
+	ldp	x19,x21,[x1,#48]
+	add	x1,x1,#64
+#ifdef	__ARMEB__
+	rev	x5,x5
+	rev	x7,x7
+	rev	x9,x9
+	rev	x11,x11
+	rev	x13,x13
+	rev	x15,x15
+	rev	x17,x17
+	rev	x20,x20
+#endif
+	eor	x5,x5,x6
+	eor	x7,x7,x8
+	eor	x9,x9,x10
+	eor	x11,x11,x12
+	eor	x13,x13,x14
+	eor	x15,x15,x16
+	eor	x17,x17,x19
+	eor	x20,x20,x21
+
+	stp	x5,x7,[x0,#0]		// store output
+	add	x28,x28,#1			// increment counter
+	stp	x9,x11,[x0,#16]
+	stp	x13,x15,[x0,#32]
+	stp	x17,x20,[x0,#48]
+	add	x0,x0,#64
+
+	b.hi	Loop_outer
+
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#64
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#96
+Labort:
+	ret
+
+.align	4
+Ltail:
+	add	x2,x2,#64
+Less_than_64:
+	sub	x0,x0,#1
+	add	x1,x1,x2
+	add	x0,x0,x2
+	add	x4,sp,x2
+	neg	x2,x2
+
+	add	x5,x5,x6,lsl#32	// pack
+	add	x7,x7,x8,lsl#32
+	add	x9,x9,x10,lsl#32
+	add	x11,x11,x12,lsl#32
+	add	x13,x13,x14,lsl#32
+	add	x15,x15,x16,lsl#32
+	add	x17,x17,x19,lsl#32
+	add	x20,x20,x21,lsl#32
+#ifdef	__ARMEB__
+	rev	x5,x5
+	rev	x7,x7
+	rev	x9,x9
+	rev	x11,x11
+	rev	x13,x13
+	rev	x15,x15
+	rev	x17,x17
+	rev	x20,x20
+#endif
+	stp	x5,x7,[sp,#0]
+	stp	x9,x11,[sp,#16]
+	stp	x13,x15,[sp,#32]
+	stp	x17,x20,[sp,#48]
+
+Loop_tail:
+	ldrb	w10,[x1,x2]
+	ldrb	w11,[x4,x2]
+	add	x2,x2,#1
+	eor	w10,w10,w11
+	strb	w10,[x0,x2]
+	cbnz	x2,Loop_tail
+
+	stp	xzr,xzr,[sp,#0]
+	stp	xzr,xzr,[sp,#16]
+	stp	xzr,xzr,[sp,#32]
+	stp	xzr,xzr,[sp,#48]
+
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#64
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#96
+	ret
+
+
+
+.align	5
+ChaCha20_neon:
+	stp	x29,x30,[sp,#-96]!
+	add	x29,sp,#0
+
+	adr	x5,Lsigma
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+	cmp	x2,#512
+	b.hs	L512_or_more_neon
+
+	sub	sp,sp,#64
+
+	ldp	x22,x23,[x5]		// load sigma
+	ld1	{v24.4s},[x5],#16
+	ldp	x24,x25,[x3]		// load key
+	ldp	x26,x27,[x3,#16]
+	ld1	{v25.4s,v26.4s},[x3]
+	ldp	x28,x30,[x4]		// load counter
+	ld1	{v27.4s},[x4]
+	ld1	{v31.4s},[x5]
+#ifdef	__ARMEB__
+	rev64	v24.4s,v24.4s
+	ror	x24,x24,#32
+	ror	x25,x25,#32
+	ror	x26,x26,#32
+	ror	x27,x27,#32
+	ror	x28,x28,#32
+	ror	x30,x30,#32
+#endif
+	add	v27.4s,v27.4s,v31.4s		// += 1
+	add	v28.4s,v27.4s,v31.4s
+	add	v29.4s,v28.4s,v31.4s
+	shl	v31.4s,v31.4s,#2			// 1 -> 4
+
+Loop_outer_neon:
+	mov	w5,w22			// unpack key block
+	lsr	x6,x22,#32
+	mov	v0.16b,v24.16b
+	mov	w7,w23
+	lsr	x8,x23,#32
+	mov	v4.16b,v24.16b
+	mov	w9,w24
+	lsr	x10,x24,#32
+	mov	v16.16b,v24.16b
+	mov	w11,w25
+	mov	v1.16b,v25.16b
+	lsr	x12,x25,#32
+	mov	v5.16b,v25.16b
+	mov	w13,w26
+	mov	v17.16b,v25.16b
+	lsr	x14,x26,#32
+	mov	v3.16b,v27.16b
+	mov	w15,w27
+	mov	v7.16b,v28.16b
+	lsr	x16,x27,#32
+	mov	v19.16b,v29.16b
+	mov	w17,w28
+	mov	v2.16b,v26.16b
+	lsr	x19,x28,#32
+	mov	v6.16b,v26.16b
+	mov	w20,w30
+	mov	v18.16b,v26.16b
+	lsr	x21,x30,#32
+
+	mov	x4,#10
+	subs	x2,x2,#256
+Loop_neon:
+	sub	x4,x4,#1
+	add	v0.4s,v0.4s,v1.4s
+	add	w5,w5,w9
+	add	v4.4s,v4.4s,v5.4s
+	add	w6,w6,w10
+	add	v16.4s,v16.4s,v17.4s
+	add	w7,w7,w11
+	eor	v3.16b,v3.16b,v0.16b
+	add	w8,w8,w12
+	eor	v7.16b,v7.16b,v4.16b
+	eor	w17,w17,w5
+	eor	v19.16b,v19.16b,v16.16b
+	eor	w19,w19,w6
+	rev32	v3.8h,v3.8h
+	eor	w20,w20,w7
+	rev32	v7.8h,v7.8h
+	eor	w21,w21,w8
+	rev32	v19.8h,v19.8h
+	ror	w17,w17,#16
+	add	v2.4s,v2.4s,v3.4s
+	ror	w19,w19,#16
+	add	v6.4s,v6.4s,v7.4s
+	ror	w20,w20,#16
+	add	v18.4s,v18.4s,v19.4s
+	ror	w21,w21,#16
+	eor	v20.16b,v1.16b,v2.16b
+	add	w13,w13,w17
+	eor	v21.16b,v5.16b,v6.16b
+	add	w14,w14,w19
+	eor	v22.16b,v17.16b,v18.16b
+	add	w15,w15,w20
+	ushr	v1.4s,v20.4s,#20
+	add	w16,w16,w21
+	ushr	v5.4s,v21.4s,#20
+	eor	w9,w9,w13
+	ushr	v17.4s,v22.4s,#20
+	eor	w10,w10,w14
+	sli	v1.4s,v20.4s,#12
+	eor	w11,w11,w15
+	sli	v5.4s,v21.4s,#12
+	eor	w12,w12,w16
+	sli	v17.4s,v22.4s,#12
+	ror	w9,w9,#20
+	add	v0.4s,v0.4s,v1.4s
+	ror	w10,w10,#20
+	add	v4.4s,v4.4s,v5.4s
+	ror	w11,w11,#20
+	add	v16.4s,v16.4s,v17.4s
+	ror	w12,w12,#20
+	eor	v20.16b,v3.16b,v0.16b
+	add	w5,w5,w9
+	eor	v21.16b,v7.16b,v4.16b
+	add	w6,w6,w10
+	eor	v22.16b,v19.16b,v16.16b
+	add	w7,w7,w11
+	ushr	v3.4s,v20.4s,#24
+	add	w8,w8,w12
+	ushr	v7.4s,v21.4s,#24
+	eor	w17,w17,w5
+	ushr	v19.4s,v22.4s,#24
+	eor	w19,w19,w6
+	sli	v3.4s,v20.4s,#8
+	eor	w20,w20,w7
+	sli	v7.4s,v21.4s,#8
+	eor	w21,w21,w8
+	sli	v19.4s,v22.4s,#8
+	ror	w17,w17,#24
+	add	v2.4s,v2.4s,v3.4s
+	ror	w19,w19,#24
+	add	v6.4s,v6.4s,v7.4s
+	ror	w20,w20,#24
+	add	v18.4s,v18.4s,v19.4s
+	ror	w21,w21,#24
+	eor	v20.16b,v1.16b,v2.16b
+	add	w13,w13,w17
+	eor	v21.16b,v5.16b,v6.16b
+	add	w14,w14,w19
+	eor	v22.16b,v17.16b,v18.16b
+	add	w15,w15,w20
+	ushr	v1.4s,v20.4s,#25
+	add	w16,w16,w21
+	ushr	v5.4s,v21.4s,#25
+	eor	w9,w9,w13
+	ushr	v17.4s,v22.4s,#25
+	eor	w10,w10,w14
+	sli	v1.4s,v20.4s,#7
+	eor	w11,w11,w15
+	sli	v5.4s,v21.4s,#7
+	eor	w12,w12,w16
+	sli	v17.4s,v22.4s,#7
+	ror	w9,w9,#25
+	ext	v2.16b,v2.16b,v2.16b,#8
+	ror	w10,w10,#25
+	ext	v6.16b,v6.16b,v6.16b,#8
+	ror	w11,w11,#25
+	ext	v18.16b,v18.16b,v18.16b,#8
+	ror	w12,w12,#25
+	ext	v3.16b,v3.16b,v3.16b,#12
+	ext	v7.16b,v7.16b,v7.16b,#12
+	ext	v19.16b,v19.16b,v19.16b,#12
+	ext	v1.16b,v1.16b,v1.16b,#4
+	ext	v5.16b,v5.16b,v5.16b,#4
+	ext	v17.16b,v17.16b,v17.16b,#4
+	add	v0.4s,v0.4s,v1.4s
+	add	w5,w5,w10
+	add	v4.4s,v4.4s,v5.4s
+	add	w6,w6,w11
+	add	v16.4s,v16.4s,v17.4s
+	add	w7,w7,w12
+	eor	v3.16b,v3.16b,v0.16b
+	add	w8,w8,w9
+	eor	v7.16b,v7.16b,v4.16b
+	eor	w21,w21,w5
+	eor	v19.16b,v19.16b,v16.16b
+	eor	w17,w17,w6
+	rev32	v3.8h,v3.8h
+	eor	w19,w19,w7
+	rev32	v7.8h,v7.8h
+	eor	w20,w20,w8
+	rev32	v19.8h,v19.8h
+	ror	w21,w21,#16
+	add	v2.4s,v2.4s,v3.4s
+	ror	w17,w17,#16
+	add	v6.4s,v6.4s,v7.4s
+	ror	w19,w19,#16
+	add	v18.4s,v18.4s,v19.4s
+	ror	w20,w20,#16
+	eor	v20.16b,v1.16b,v2.16b
+	add	w15,w15,w21
+	eor	v21.16b,v5.16b,v6.16b
+	add	w16,w16,w17
+	eor	v22.16b,v17.16b,v18.16b
+	add	w13,w13,w19
+	ushr	v1.4s,v20.4s,#20
+	add	w14,w14,w20
+	ushr	v5.4s,v21.4s,#20
+	eor	w10,w10,w15
+	ushr	v17.4s,v22.4s,#20
+	eor	w11,w11,w16
+	sli	v1.4s,v20.4s,#12
+	eor	w12,w12,w13
+	sli	v5.4s,v21.4s,#12
+	eor	w9,w9,w14
+	sli	v17.4s,v22.4s,#12
+	ror	w10,w10,#20
+	add	v0.4s,v0.4s,v1.4s
+	ror	w11,w11,#20
+	add	v4.4s,v4.4s,v5.4s
+	ror	w12,w12,#20
+	add	v16.4s,v16.4s,v17.4s
+	ror	w9,w9,#20
+	eor	v20.16b,v3.16b,v0.16b
+	add	w5,w5,w10
+	eor	v21.16b,v7.16b,v4.16b
+	add	w6,w6,w11
+	eor	v22.16b,v19.16b,v16.16b
+	add	w7,w7,w12
+	ushr	v3.4s,v20.4s,#24
+	add	w8,w8,w9
+	ushr	v7.4s,v21.4s,#24
+	eor	w21,w21,w5
+	ushr	v19.4s,v22.4s,#24
+	eor	w17,w17,w6
+	sli	v3.4s,v20.4s,#8
+	eor	w19,w19,w7
+	sli	v7.4s,v21.4s,#8
+	eor	w20,w20,w8
+	sli	v19.4s,v22.4s,#8
+	ror	w21,w21,#24
+	add	v2.4s,v2.4s,v3.4s
+	ror	w17,w17,#24
+	add	v6.4s,v6.4s,v7.4s
+	ror	w19,w19,#24
+	add	v18.4s,v18.4s,v19.4s
+	ror	w20,w20,#24
+	eor	v20.16b,v1.16b,v2.16b
+	add	w15,w15,w21
+	eor	v21.16b,v5.16b,v6.16b
+	add	w16,w16,w17
+	eor	v22.16b,v17.16b,v18.16b
+	add	w13,w13,w19
+	ushr	v1.4s,v20.4s,#25
+	add	w14,w14,w20
+	ushr	v5.4s,v21.4s,#25
+	eor	w10,w10,w15
+	ushr	v17.4s,v22.4s,#25
+	eor	w11,w11,w16
+	sli	v1.4s,v20.4s,#7
+	eor	w12,w12,w13
+	sli	v5.4s,v21.4s,#7
+	eor	w9,w9,w14
+	sli	v17.4s,v22.4s,#7
+	ror	w10,w10,#25
+	ext	v2.16b,v2.16b,v2.16b,#8
+	ror	w11,w11,#25
+	ext	v6.16b,v6.16b,v6.16b,#8
+	ror	w12,w12,#25
+	ext	v18.16b,v18.16b,v18.16b,#8
+	ror	w9,w9,#25
+	ext	v3.16b,v3.16b,v3.16b,#4
+	ext	v7.16b,v7.16b,v7.16b,#4
+	ext	v19.16b,v19.16b,v19.16b,#4
+	ext	v1.16b,v1.16b,v1.16b,#12
+	ext	v5.16b,v5.16b,v5.16b,#12
+	ext	v17.16b,v17.16b,v17.16b,#12
+	cbnz	x4,Loop_neon
+
+	add	w5,w5,w22		// accumulate key block
+	add	v0.4s,v0.4s,v24.4s
+	add	x6,x6,x22,lsr#32
+	add	v4.4s,v4.4s,v24.4s
+	add	w7,w7,w23
+	add	v16.4s,v16.4s,v24.4s
+	add	x8,x8,x23,lsr#32
+	add	v2.4s,v2.4s,v26.4s
+	add	w9,w9,w24
+	add	v6.4s,v6.4s,v26.4s
+	add	x10,x10,x24,lsr#32
+	add	v18.4s,v18.4s,v26.4s
+	add	w11,w11,w25
+	add	v3.4s,v3.4s,v27.4s
+	add	x12,x12,x25,lsr#32
+	add	w13,w13,w26
+	add	v7.4s,v7.4s,v28.4s
+	add	x14,x14,x26,lsr#32
+	add	w15,w15,w27
+	add	v19.4s,v19.4s,v29.4s
+	add	x16,x16,x27,lsr#32
+	add	w17,w17,w28
+	add	v1.4s,v1.4s,v25.4s
+	add	x19,x19,x28,lsr#32
+	add	w20,w20,w30
+	add	v5.4s,v5.4s,v25.4s
+	add	x21,x21,x30,lsr#32
+	add	v17.4s,v17.4s,v25.4s
+
+	b.lo	Ltail_neon
+
+	add	x5,x5,x6,lsl#32	// pack
+	add	x7,x7,x8,lsl#32
+	ldp	x6,x8,[x1,#0]		// load input
+	add	x9,x9,x10,lsl#32
+	add	x11,x11,x12,lsl#32
+	ldp	x10,x12,[x1,#16]
+	add	x13,x13,x14,lsl#32
+	add	x15,x15,x16,lsl#32
+	ldp	x14,x16,[x1,#32]
+	add	x17,x17,x19,lsl#32
+	add	x20,x20,x21,lsl#32
+	ldp	x19,x21,[x1,#48]
+	add	x1,x1,#64
+#ifdef	__ARMEB__
+	rev	x5,x5
+	rev	x7,x7
+	rev	x9,x9
+	rev	x11,x11
+	rev	x13,x13
+	rev	x15,x15
+	rev	x17,x17
+	rev	x20,x20
+#endif
+	ld1	{v20.16b,v21.16b,v22.16b,v23.16b},[x1],#64
+	eor	x5,x5,x6
+	eor	x7,x7,x8
+	eor	x9,x9,x10
+	eor	x11,x11,x12
+	eor	x13,x13,x14
+	eor	v0.16b,v0.16b,v20.16b
+	eor	x15,x15,x16
+	eor	v1.16b,v1.16b,v21.16b
+	eor	x17,x17,x19
+	eor	v2.16b,v2.16b,v22.16b
+	eor	x20,x20,x21
+	eor	v3.16b,v3.16b,v23.16b
+	ld1	{v20.16b,v21.16b,v22.16b,v23.16b},[x1],#64
+
+	stp	x5,x7,[x0,#0]		// store output
+	add	x28,x28,#4			// increment counter
+	stp	x9,x11,[x0,#16]
+	add	v27.4s,v27.4s,v31.4s		// += 4
+	stp	x13,x15,[x0,#32]
+	add	v28.4s,v28.4s,v31.4s
+	stp	x17,x20,[x0,#48]
+	add	v29.4s,v29.4s,v31.4s
+	add	x0,x0,#64
+
+	st1	{v0.16b,v1.16b,v2.16b,v3.16b},[x0],#64
+	ld1	{v0.16b,v1.16b,v2.16b,v3.16b},[x1],#64
+
+	eor	v4.16b,v4.16b,v20.16b
+	eor	v5.16b,v5.16b,v21.16b
+	eor	v6.16b,v6.16b,v22.16b
+	eor	v7.16b,v7.16b,v23.16b
+	st1	{v4.16b,v5.16b,v6.16b,v7.16b},[x0],#64
+
+	eor	v16.16b,v16.16b,v0.16b
+	eor	v17.16b,v17.16b,v1.16b
+	eor	v18.16b,v18.16b,v2.16b
+	eor	v19.16b,v19.16b,v3.16b
+	st1	{v16.16b,v17.16b,v18.16b,v19.16b},[x0],#64
+
+	b.hi	Loop_outer_neon
+
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#64
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#96
+	ret
+
+Ltail_neon:
+	add	x2,x2,#256
+	cmp	x2,#64
+	b.lo	Less_than_64
+
+	add	x5,x5,x6,lsl#32	// pack
+	add	x7,x7,x8,lsl#32
+	ldp	x6,x8,[x1,#0]		// load input
+	add	x9,x9,x10,lsl#32
+	add	x11,x11,x12,lsl#32
+	ldp	x10,x12,[x1,#16]
+	add	x13,x13,x14,lsl#32
+	add	x15,x15,x16,lsl#32
+	ldp	x14,x16,[x1,#32]
+	add	x17,x17,x19,lsl#32
+	add	x20,x20,x21,lsl#32
+	ldp	x19,x21,[x1,#48]
+	add	x1,x1,#64
+#ifdef	__ARMEB__
+	rev	x5,x5
+	rev	x7,x7
+	rev	x9,x9
+	rev	x11,x11
+	rev	x13,x13
+	rev	x15,x15
+	rev	x17,x17
+	rev	x20,x20
+#endif
+	eor	x5,x5,x6
+	eor	x7,x7,x8
+	eor	x9,x9,x10
+	eor	x11,x11,x12
+	eor	x13,x13,x14
+	eor	x15,x15,x16
+	eor	x17,x17,x19
+	eor	x20,x20,x21
+
+	stp	x5,x7,[x0,#0]		// store output
+	add	x28,x28,#4			// increment counter
+	stp	x9,x11,[x0,#16]
+	stp	x13,x15,[x0,#32]
+	stp	x17,x20,[x0,#48]
+	add	x0,x0,#64
+	b.eq	Ldone_neon
+	sub	x2,x2,#64
+	cmp	x2,#64
+	b.lo	Less_than_128
+
+	ld1	{v20.16b,v21.16b,v22.16b,v23.16b},[x1],#64
+	eor	v0.16b,v0.16b,v20.16b
+	eor	v1.16b,v1.16b,v21.16b
+	eor	v2.16b,v2.16b,v22.16b
+	eor	v3.16b,v3.16b,v23.16b
+	st1	{v0.16b,v1.16b,v2.16b,v3.16b},[x0],#64
+	b.eq	Ldone_neon
+	sub	x2,x2,#64
+	cmp	x2,#64
+	b.lo	Less_than_192
+
+	ld1	{v20.16b,v21.16b,v22.16b,v23.16b},[x1],#64
+	eor	v4.16b,v4.16b,v20.16b
+	eor	v5.16b,v5.16b,v21.16b
+	eor	v6.16b,v6.16b,v22.16b
+	eor	v7.16b,v7.16b,v23.16b
+	st1	{v4.16b,v5.16b,v6.16b,v7.16b},[x0],#64
+	b.eq	Ldone_neon
+	sub	x2,x2,#64
+
+	st1	{v16.16b,v17.16b,v18.16b,v19.16b},[sp]
+	b	Last_neon
+
+Less_than_128:
+	st1	{v0.16b,v1.16b,v2.16b,v3.16b},[sp]
+	b	Last_neon
+Less_than_192:
+	st1	{v4.16b,v5.16b,v6.16b,v7.16b},[sp]
+	b	Last_neon
+
+.align	4
+Last_neon:
+	sub	x0,x0,#1
+	add	x1,x1,x2
+	add	x0,x0,x2
+	add	x4,sp,x2
+	neg	x2,x2
+
+Loop_tail_neon:
+	ldrb	w10,[x1,x2]
+	ldrb	w11,[x4,x2]
+	add	x2,x2,#1
+	eor	w10,w10,w11
+	strb	w10,[x0,x2]
+	cbnz	x2,Loop_tail_neon
+
+	stp	xzr,xzr,[sp,#0]
+	stp	xzr,xzr,[sp,#16]
+	stp	xzr,xzr,[sp,#32]
+	stp	xzr,xzr,[sp,#48]
+
+Ldone_neon:
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#64
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#96
+	ret
+
+
+.align	5
+ChaCha20_512_neon:
+	stp	x29,x30,[sp,#-96]!
+	add	x29,sp,#0
+
+	adr	x5,Lsigma
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+
+L512_or_more_neon:
+	sub	sp,sp,#128+64
+
+	ldp	x22,x23,[x5]		// load sigma
+	ld1	{v24.4s},[x5],#16
+	ldp	x24,x25,[x3]		// load key
+	ldp	x26,x27,[x3,#16]
+	ld1	{v25.4s,v26.4s},[x3]
+	ldp	x28,x30,[x4]		// load counter
+	ld1	{v27.4s},[x4]
+	ld1	{v31.4s},[x5]
+#ifdef	__ARMEB__
+	rev64	v24.4s,v24.4s
+	ror	x24,x24,#32
+	ror	x25,x25,#32
+	ror	x26,x26,#32
+	ror	x27,x27,#32
+	ror	x28,x28,#32
+	ror	x30,x30,#32
+#endif
+	add	v27.4s,v27.4s,v31.4s		// += 1
+	stp	q24,q25,[sp,#0]		// off-load key block, invariant part
+	add	v27.4s,v27.4s,v31.4s		// not typo
+	str	q26,[sp,#32]
+	add	v28.4s,v27.4s,v31.4s
+	add	v29.4s,v28.4s,v31.4s
+	add	v30.4s,v29.4s,v31.4s
+	shl	v31.4s,v31.4s,#2			// 1 -> 4
+
+	stp	d8,d9,[sp,#128+0]		// meet ABI requirements
+	stp	d10,d11,[sp,#128+16]
+	stp	d12,d13,[sp,#128+32]
+	stp	d14,d15,[sp,#128+48]
+
+	sub	x2,x2,#512			// not typo
+
+Loop_outer_512_neon:
+	mov	v0.16b,v24.16b
+	mov	v4.16b,v24.16b
+	mov	v8.16b,v24.16b
+	mov	v12.16b,v24.16b
+	mov	v16.16b,v24.16b
+	mov	v20.16b,v24.16b
+	mov	v1.16b,v25.16b
+	mov	w5,w22			// unpack key block
+	mov	v5.16b,v25.16b
+	lsr	x6,x22,#32
+	mov	v9.16b,v25.16b
+	mov	w7,w23
+	mov	v13.16b,v25.16b
+	lsr	x8,x23,#32
+	mov	v17.16b,v25.16b
+	mov	w9,w24
+	mov	v21.16b,v25.16b
+	lsr	x10,x24,#32
+	mov	v3.16b,v27.16b
+	mov	w11,w25
+	mov	v7.16b,v28.16b
+	lsr	x12,x25,#32
+	mov	v11.16b,v29.16b
+	mov	w13,w26
+	mov	v15.16b,v30.16b
+	lsr	x14,x26,#32
+	mov	v2.16b,v26.16b
+	mov	w15,w27
+	mov	v6.16b,v26.16b
+	lsr	x16,x27,#32
+	add	v19.4s,v3.4s,v31.4s			// +4
+	mov	w17,w28
+	add	v23.4s,v7.4s,v31.4s			// +4
+	lsr	x19,x28,#32
+	mov	v10.16b,v26.16b
+	mov	w20,w30
+	mov	v14.16b,v26.16b
+	lsr	x21,x30,#32
+	mov	v18.16b,v26.16b
+	stp	q27,q28,[sp,#48]		// off-load key block, variable part
+	mov	v22.16b,v26.16b
+	str	q29,[sp,#80]
+
+	mov	x4,#5
+	subs	x2,x2,#512
+Loop_upper_neon:
+	sub	x4,x4,#1
+	add	v0.4s,v0.4s,v1.4s
+	add	w5,w5,w9
+	add	v4.4s,v4.4s,v5.4s
+	add	w6,w6,w10
+	add	v8.4s,v8.4s,v9.4s
+	add	w7,w7,w11
+	add	v12.4s,v12.4s,v13.4s
+	add	w8,w8,w12
+	add	v16.4s,v16.4s,v17.4s
+	eor	w17,w17,w5
+	add	v20.4s,v20.4s,v21.4s
+	eor	w19,w19,w6
+	eor	v3.16b,v3.16b,v0.16b
+	eor	w20,w20,w7
+	eor	v7.16b,v7.16b,v4.16b
+	eor	w21,w21,w8
+	eor	v11.16b,v11.16b,v8.16b
+	ror	w17,w17,#16
+	eor	v15.16b,v15.16b,v12.16b
+	ror	w19,w19,#16
+	eor	v19.16b,v19.16b,v16.16b
+	ror	w20,w20,#16
+	eor	v23.16b,v23.16b,v20.16b
+	ror	w21,w21,#16
+	rev32	v3.8h,v3.8h
+	add	w13,w13,w17
+	rev32	v7.8h,v7.8h
+	add	w14,w14,w19
+	rev32	v11.8h,v11.8h
+	add	w15,w15,w20
+	rev32	v15.8h,v15.8h
+	add	w16,w16,w21
+	rev32	v19.8h,v19.8h
+	eor	w9,w9,w13
+	rev32	v23.8h,v23.8h
+	eor	w10,w10,w14
+	add	v2.4s,v2.4s,v3.4s
+	eor	w11,w11,w15
+	add	v6.4s,v6.4s,v7.4s
+	eor	w12,w12,w16
+	add	v10.4s,v10.4s,v11.4s
+	ror	w9,w9,#20
+	add	v14.4s,v14.4s,v15.4s
+	ror	w10,w10,#20
+	add	v18.4s,v18.4s,v19.4s
+	ror	w11,w11,#20
+	add	v22.4s,v22.4s,v23.4s
+	ror	w12,w12,#20
+	eor	v24.16b,v1.16b,v2.16b
+	add	w5,w5,w9
+	eor	v25.16b,v5.16b,v6.16b
+	add	w6,w6,w10
+	eor	v26.16b,v9.16b,v10.16b
+	add	w7,w7,w11
+	eor	v27.16b,v13.16b,v14.16b
+	add	w8,w8,w12
+	eor	v28.16b,v17.16b,v18.16b
+	eor	w17,w17,w5
+	eor	v29.16b,v21.16b,v22.16b
+	eor	w19,w19,w6
+	ushr	v1.4s,v24.4s,#20
+	eor	w20,w20,w7
+	ushr	v5.4s,v25.4s,#20
+	eor	w21,w21,w8
+	ushr	v9.4s,v26.4s,#20
+	ror	w17,w17,#24
+	ushr	v13.4s,v27.4s,#20
+	ror	w19,w19,#24
+	ushr	v17.4s,v28.4s,#20
+	ror	w20,w20,#24
+	ushr	v21.4s,v29.4s,#20
+	ror	w21,w21,#24
+	sli	v1.4s,v24.4s,#12
+	add	w13,w13,w17
+	sli	v5.4s,v25.4s,#12
+	add	w14,w14,w19
+	sli	v9.4s,v26.4s,#12
+	add	w15,w15,w20
+	sli	v13.4s,v27.4s,#12
+	add	w16,w16,w21
+	sli	v17.4s,v28.4s,#12
+	eor	w9,w9,w13
+	sli	v21.4s,v29.4s,#12
+	eor	w10,w10,w14
+	add	v0.4s,v0.4s,v1.4s
+	eor	w11,w11,w15
+	add	v4.4s,v4.4s,v5.4s
+	eor	w12,w12,w16
+	add	v8.4s,v8.4s,v9.4s
+	ror	w9,w9,#25
+	add	v12.4s,v12.4s,v13.4s
+	ror	w10,w10,#25
+	add	v16.4s,v16.4s,v17.4s
+	ror	w11,w11,#25
+	add	v20.4s,v20.4s,v21.4s
+	ror	w12,w12,#25
+	eor	v24.16b,v3.16b,v0.16b
+	add	w5,w5,w10
+	eor	v25.16b,v7.16b,v4.16b
+	add	w6,w6,w11
+	eor	v26.16b,v11.16b,v8.16b
+	add	w7,w7,w12
+	eor	v27.16b,v15.16b,v12.16b
+	add	w8,w8,w9
+	eor	v28.16b,v19.16b,v16.16b
+	eor	w21,w21,w5
+	eor	v29.16b,v23.16b,v20.16b
+	eor	w17,w17,w6
+	ushr	v3.4s,v24.4s,#24
+	eor	w19,w19,w7
+	ushr	v7.4s,v25.4s,#24
+	eor	w20,w20,w8
+	ushr	v11.4s,v26.4s,#24
+	ror	w21,w21,#16
+	ushr	v15.4s,v27.4s,#24
+	ror	w17,w17,#16
+	ushr	v19.4s,v28.4s,#24
+	ror	w19,w19,#16
+	ushr	v23.4s,v29.4s,#24
+	ror	w20,w20,#16
+	sli	v3.4s,v24.4s,#8
+	add	w15,w15,w21
+	sli	v7.4s,v25.4s,#8
+	add	w16,w16,w17
+	sli	v11.4s,v26.4s,#8
+	add	w13,w13,w19
+	sli	v15.4s,v27.4s,#8
+	add	w14,w14,w20
+	sli	v19.4s,v28.4s,#8
+	eor	w10,w10,w15
+	sli	v23.4s,v29.4s,#8
+	eor	w11,w11,w16
+	add	v2.4s,v2.4s,v3.4s
+	eor	w12,w12,w13
+	add	v6.4s,v6.4s,v7.4s
+	eor	w9,w9,w14
+	add	v10.4s,v10.4s,v11.4s
+	ror	w10,w10,#20
+	add	v14.4s,v14.4s,v15.4s
+	ror	w11,w11,#20
+	add	v18.4s,v18.4s,v19.4s
+	ror	w12,w12,#20
+	add	v22.4s,v22.4s,v23.4s
+	ror	w9,w9,#20
+	eor	v24.16b,v1.16b,v2.16b
+	add	w5,w5,w10
+	eor	v25.16b,v5.16b,v6.16b
+	add	w6,w6,w11
+	eor	v26.16b,v9.16b,v10.16b
+	add	w7,w7,w12
+	eor	v27.16b,v13.16b,v14.16b
+	add	w8,w8,w9
+	eor	v28.16b,v17.16b,v18.16b
+	eor	w21,w21,w5
+	eor	v29.16b,v21.16b,v22.16b
+	eor	w17,w17,w6
+	ushr	v1.4s,v24.4s,#25
+	eor	w19,w19,w7
+	ushr	v5.4s,v25.4s,#25
+	eor	w20,w20,w8
+	ushr	v9.4s,v26.4s,#25
+	ror	w21,w21,#24
+	ushr	v13.4s,v27.4s,#25
+	ror	w17,w17,#24
+	ushr	v17.4s,v28.4s,#25
+	ror	w19,w19,#24
+	ushr	v21.4s,v29.4s,#25
+	ror	w20,w20,#24
+	sli	v1.4s,v24.4s,#7
+	add	w15,w15,w21
+	sli	v5.4s,v25.4s,#7
+	add	w16,w16,w17
+	sli	v9.4s,v26.4s,#7
+	add	w13,w13,w19
+	sli	v13.4s,v27.4s,#7
+	add	w14,w14,w20
+	sli	v17.4s,v28.4s,#7
+	eor	w10,w10,w15
+	sli	v21.4s,v29.4s,#7
+	eor	w11,w11,w16
+	ext	v2.16b,v2.16b,v2.16b,#8
+	eor	w12,w12,w13
+	ext	v6.16b,v6.16b,v6.16b,#8
+	eor	w9,w9,w14
+	ext	v10.16b,v10.16b,v10.16b,#8
+	ror	w10,w10,#25
+	ext	v14.16b,v14.16b,v14.16b,#8
+	ror	w11,w11,#25
+	ext	v18.16b,v18.16b,v18.16b,#8
+	ror	w12,w12,#25
+	ext	v22.16b,v22.16b,v22.16b,#8
+	ror	w9,w9,#25
+	ext	v3.16b,v3.16b,v3.16b,#12
+	ext	v7.16b,v7.16b,v7.16b,#12
+	ext	v11.16b,v11.16b,v11.16b,#12
+	ext	v15.16b,v15.16b,v15.16b,#12
+	ext	v19.16b,v19.16b,v19.16b,#12
+	ext	v23.16b,v23.16b,v23.16b,#12
+	ext	v1.16b,v1.16b,v1.16b,#4
+	ext	v5.16b,v5.16b,v5.16b,#4
+	ext	v9.16b,v9.16b,v9.16b,#4
+	ext	v13.16b,v13.16b,v13.16b,#4
+	ext	v17.16b,v17.16b,v17.16b,#4
+	ext	v21.16b,v21.16b,v21.16b,#4
+	add	v0.4s,v0.4s,v1.4s
+	add	w5,w5,w9
+	add	v4.4s,v4.4s,v5.4s
+	add	w6,w6,w10
+	add	v8.4s,v8.4s,v9.4s
+	add	w7,w7,w11
+	add	v12.4s,v12.4s,v13.4s
+	add	w8,w8,w12
+	add	v16.4s,v16.4s,v17.4s
+	eor	w17,w17,w5
+	add	v20.4s,v20.4s,v21.4s
+	eor	w19,w19,w6
+	eor	v3.16b,v3.16b,v0.16b
+	eor	w20,w20,w7
+	eor	v7.16b,v7.16b,v4.16b
+	eor	w21,w21,w8
+	eor	v11.16b,v11.16b,v8.16b
+	ror	w17,w17,#16
+	eor	v15.16b,v15.16b,v12.16b
+	ror	w19,w19,#16
+	eor	v19.16b,v19.16b,v16.16b
+	ror	w20,w20,#16
+	eor	v23.16b,v23.16b,v20.16b
+	ror	w21,w21,#16
+	rev32	v3.8h,v3.8h
+	add	w13,w13,w17
+	rev32	v7.8h,v7.8h
+	add	w14,w14,w19
+	rev32	v11.8h,v11.8h
+	add	w15,w15,w20
+	rev32	v15.8h,v15.8h
+	add	w16,w16,w21
+	rev32	v19.8h,v19.8h
+	eor	w9,w9,w13
+	rev32	v23.8h,v23.8h
+	eor	w10,w10,w14
+	add	v2.4s,v2.4s,v3.4s
+	eor	w11,w11,w15
+	add	v6.4s,v6.4s,v7.4s
+	eor	w12,w12,w16
+	add	v10.4s,v10.4s,v11.4s
+	ror	w9,w9,#20
+	add	v14.4s,v14.4s,v15.4s
+	ror	w10,w10,#20
+	add	v18.4s,v18.4s,v19.4s
+	ror	w11,w11,#20
+	add	v22.4s,v22.4s,v23.4s
+	ror	w12,w12,#20
+	eor	v24.16b,v1.16b,v2.16b
+	add	w5,w5,w9
+	eor	v25.16b,v5.16b,v6.16b
+	add	w6,w6,w10
+	eor	v26.16b,v9.16b,v10.16b
+	add	w7,w7,w11
+	eor	v27.16b,v13.16b,v14.16b
+	add	w8,w8,w12
+	eor	v28.16b,v17.16b,v18.16b
+	eor	w17,w17,w5
+	eor	v29.16b,v21.16b,v22.16b
+	eor	w19,w19,w6
+	ushr	v1.4s,v24.4s,#20
+	eor	w20,w20,w7
+	ushr	v5.4s,v25.4s,#20
+	eor	w21,w21,w8
+	ushr	v9.4s,v26.4s,#20
+	ror	w17,w17,#24
+	ushr	v13.4s,v27.4s,#20
+	ror	w19,w19,#24
+	ushr	v17.4s,v28.4s,#20
+	ror	w20,w20,#24
+	ushr	v21.4s,v29.4s,#20
+	ror	w21,w21,#24
+	sli	v1.4s,v24.4s,#12
+	add	w13,w13,w17
+	sli	v5.4s,v25.4s,#12
+	add	w14,w14,w19
+	sli	v9.4s,v26.4s,#12
+	add	w15,w15,w20
+	sli	v13.4s,v27.4s,#12
+	add	w16,w16,w21
+	sli	v17.4s,v28.4s,#12
+	eor	w9,w9,w13
+	sli	v21.4s,v29.4s,#12
+	eor	w10,w10,w14
+	add	v0.4s,v0.4s,v1.4s
+	eor	w11,w11,w15
+	add	v4.4s,v4.4s,v5.4s
+	eor	w12,w12,w16
+	add	v8.4s,v8.4s,v9.4s
+	ror	w9,w9,#25
+	add	v12.4s,v12.4s,v13.4s
+	ror	w10,w10,#25
+	add	v16.4s,v16.4s,v17.4s
+	ror	w11,w11,#25
+	add	v20.4s,v20.4s,v21.4s
+	ror	w12,w12,#25
+	eor	v24.16b,v3.16b,v0.16b
+	add	w5,w5,w10
+	eor	v25.16b,v7.16b,v4.16b
+	add	w6,w6,w11
+	eor	v26.16b,v11.16b,v8.16b
+	add	w7,w7,w12
+	eor	v27.16b,v15.16b,v12.16b
+	add	w8,w8,w9
+	eor	v28.16b,v19.16b,v16.16b
+	eor	w21,w21,w5
+	eor	v29.16b,v23.16b,v20.16b
+	eor	w17,w17,w6
+	ushr	v3.4s,v24.4s,#24
+	eor	w19,w19,w7
+	ushr	v7.4s,v25.4s,#24
+	eor	w20,w20,w8
+	ushr	v11.4s,v26.4s,#24
+	ror	w21,w21,#16
+	ushr	v15.4s,v27.4s,#24
+	ror	w17,w17,#16
+	ushr	v19.4s,v28.4s,#24
+	ror	w19,w19,#16
+	ushr	v23.4s,v29.4s,#24
+	ror	w20,w20,#16
+	sli	v3.4s,v24.4s,#8
+	add	w15,w15,w21
+	sli	v7.4s,v25.4s,#8
+	add	w16,w16,w17
+	sli	v11.4s,v26.4s,#8
+	add	w13,w13,w19
+	sli	v15.4s,v27.4s,#8
+	add	w14,w14,w20
+	sli	v19.4s,v28.4s,#8
+	eor	w10,w10,w15
+	sli	v23.4s,v29.4s,#8
+	eor	w11,w11,w16
+	add	v2.4s,v2.4s,v3.4s
+	eor	w12,w12,w13
+	add	v6.4s,v6.4s,v7.4s
+	eor	w9,w9,w14
+	add	v10.4s,v10.4s,v11.4s
+	ror	w10,w10,#20
+	add	v14.4s,v14.4s,v15.4s
+	ror	w11,w11,#20
+	add	v18.4s,v18.4s,v19.4s
+	ror	w12,w12,#20
+	add	v22.4s,v22.4s,v23.4s
+	ror	w9,w9,#20
+	eor	v24.16b,v1.16b,v2.16b
+	add	w5,w5,w10
+	eor	v25.16b,v5.16b,v6.16b
+	add	w6,w6,w11
+	eor	v26.16b,v9.16b,v10.16b
+	add	w7,w7,w12
+	eor	v27.16b,v13.16b,v14.16b
+	add	w8,w8,w9
+	eor	v28.16b,v17.16b,v18.16b
+	eor	w21,w21,w5
+	eor	v29.16b,v21.16b,v22.16b
+	eor	w17,w17,w6
+	ushr	v1.4s,v24.4s,#25
+	eor	w19,w19,w7
+	ushr	v5.4s,v25.4s,#25
+	eor	w20,w20,w8
+	ushr	v9.4s,v26.4s,#25
+	ror	w21,w21,#24
+	ushr	v13.4s,v27.4s,#25
+	ror	w17,w17,#24
+	ushr	v17.4s,v28.4s,#25
+	ror	w19,w19,#24
+	ushr	v21.4s,v29.4s,#25
+	ror	w20,w20,#24
+	sli	v1.4s,v24.4s,#7
+	add	w15,w15,w21
+	sli	v5.4s,v25.4s,#7
+	add	w16,w16,w17
+	sli	v9.4s,v26.4s,#7
+	add	w13,w13,w19
+	sli	v13.4s,v27.4s,#7
+	add	w14,w14,w20
+	sli	v17.4s,v28.4s,#7
+	eor	w10,w10,w15
+	sli	v21.4s,v29.4s,#7
+	eor	w11,w11,w16
+	ext	v2.16b,v2.16b,v2.16b,#8
+	eor	w12,w12,w13
+	ext	v6.16b,v6.16b,v6.16b,#8
+	eor	w9,w9,w14
+	ext	v10.16b,v10.16b,v10.16b,#8
+	ror	w10,w10,#25
+	ext	v14.16b,v14.16b,v14.16b,#8
+	ror	w11,w11,#25
+	ext	v18.16b,v18.16b,v18.16b,#8
+	ror	w12,w12,#25
+	ext	v22.16b,v22.16b,v22.16b,#8
+	ror	w9,w9,#25
+	ext	v3.16b,v3.16b,v3.16b,#4
+	ext	v7.16b,v7.16b,v7.16b,#4
+	ext	v11.16b,v11.16b,v11.16b,#4
+	ext	v15.16b,v15.16b,v15.16b,#4
+	ext	v19.16b,v19.16b,v19.16b,#4
+	ext	v23.16b,v23.16b,v23.16b,#4
+	ext	v1.16b,v1.16b,v1.16b,#12
+	ext	v5.16b,v5.16b,v5.16b,#12
+	ext	v9.16b,v9.16b,v9.16b,#12
+	ext	v13.16b,v13.16b,v13.16b,#12
+	ext	v17.16b,v17.16b,v17.16b,#12
+	ext	v21.16b,v21.16b,v21.16b,#12
+	cbnz	x4,Loop_upper_neon
+
+	add	w5,w5,w22		// accumulate key block
+	add	x6,x6,x22,lsr#32
+	add	w7,w7,w23
+	add	x8,x8,x23,lsr#32
+	add	w9,w9,w24
+	add	x10,x10,x24,lsr#32
+	add	w11,w11,w25
+	add	x12,x12,x25,lsr#32
+	add	w13,w13,w26
+	add	x14,x14,x26,lsr#32
+	add	w15,w15,w27
+	add	x16,x16,x27,lsr#32
+	add	w17,w17,w28
+	add	x19,x19,x28,lsr#32
+	add	w20,w20,w30
+	add	x21,x21,x30,lsr#32
+
+	add	x5,x5,x6,lsl#32	// pack
+	add	x7,x7,x8,lsl#32
+	ldp	x6,x8,[x1,#0]		// load input
+	add	x9,x9,x10,lsl#32
+	add	x11,x11,x12,lsl#32
+	ldp	x10,x12,[x1,#16]
+	add	x13,x13,x14,lsl#32
+	add	x15,x15,x16,lsl#32
+	ldp	x14,x16,[x1,#32]
+	add	x17,x17,x19,lsl#32
+	add	x20,x20,x21,lsl#32
+	ldp	x19,x21,[x1,#48]
+	add	x1,x1,#64
+#ifdef	__ARMEB__
+	rev	x5,x5
+	rev	x7,x7
+	rev	x9,x9
+	rev	x11,x11
+	rev	x13,x13
+	rev	x15,x15
+	rev	x17,x17
+	rev	x20,x20
+#endif
+	eor	x5,x5,x6
+	eor	x7,x7,x8
+	eor	x9,x9,x10
+	eor	x11,x11,x12
+	eor	x13,x13,x14
+	eor	x15,x15,x16
+	eor	x17,x17,x19
+	eor	x20,x20,x21
+
+	stp	x5,x7,[x0,#0]		// store output
+	add	x28,x28,#1			// increment counter
+	mov	w5,w22			// unpack key block
+	lsr	x6,x22,#32
+	stp	x9,x11,[x0,#16]
+	mov	w7,w23
+	lsr	x8,x23,#32
+	stp	x13,x15,[x0,#32]
+	mov	w9,w24
+	lsr	x10,x24,#32
+	stp	x17,x20,[x0,#48]
+	add	x0,x0,#64
+	mov	w11,w25
+	lsr	x12,x25,#32
+	mov	w13,w26
+	lsr	x14,x26,#32
+	mov	w15,w27
+	lsr	x16,x27,#32
+	mov	w17,w28
+	lsr	x19,x28,#32
+	mov	w20,w30
+	lsr	x21,x30,#32
+
+	mov	x4,#5
+Loop_lower_neon:
+	sub	x4,x4,#1
+	add	v0.4s,v0.4s,v1.4s
+	add	w5,w5,w9
+	add	v4.4s,v4.4s,v5.4s
+	add	w6,w6,w10
+	add	v8.4s,v8.4s,v9.4s
+	add	w7,w7,w11
+	add	v12.4s,v12.4s,v13.4s
+	add	w8,w8,w12
+	add	v16.4s,v16.4s,v17.4s
+	eor	w17,w17,w5
+	add	v20.4s,v20.4s,v21.4s
+	eor	w19,w19,w6
+	eor	v3.16b,v3.16b,v0.16b
+	eor	w20,w20,w7
+	eor	v7.16b,v7.16b,v4.16b
+	eor	w21,w21,w8
+	eor	v11.16b,v11.16b,v8.16b
+	ror	w17,w17,#16
+	eor	v15.16b,v15.16b,v12.16b
+	ror	w19,w19,#16
+	eor	v19.16b,v19.16b,v16.16b
+	ror	w20,w20,#16
+	eor	v23.16b,v23.16b,v20.16b
+	ror	w21,w21,#16
+	rev32	v3.8h,v3.8h
+	add	w13,w13,w17
+	rev32	v7.8h,v7.8h
+	add	w14,w14,w19
+	rev32	v11.8h,v11.8h
+	add	w15,w15,w20
+	rev32	v15.8h,v15.8h
+	add	w16,w16,w21
+	rev32	v19.8h,v19.8h
+	eor	w9,w9,w13
+	rev32	v23.8h,v23.8h
+	eor	w10,w10,w14
+	add	v2.4s,v2.4s,v3.4s
+	eor	w11,w11,w15
+	add	v6.4s,v6.4s,v7.4s
+	eor	w12,w12,w16
+	add	v10.4s,v10.4s,v11.4s
+	ror	w9,w9,#20
+	add	v14.4s,v14.4s,v15.4s
+	ror	w10,w10,#20
+	add	v18.4s,v18.4s,v19.4s
+	ror	w11,w11,#20
+	add	v22.4s,v22.4s,v23.4s
+	ror	w12,w12,#20
+	eor	v24.16b,v1.16b,v2.16b
+	add	w5,w5,w9
+	eor	v25.16b,v5.16b,v6.16b
+	add	w6,w6,w10
+	eor	v26.16b,v9.16b,v10.16b
+	add	w7,w7,w11
+	eor	v27.16b,v13.16b,v14.16b
+	add	w8,w8,w12
+	eor	v28.16b,v17.16b,v18.16b
+	eor	w17,w17,w5
+	eor	v29.16b,v21.16b,v22.16b
+	eor	w19,w19,w6
+	ushr	v1.4s,v24.4s,#20
+	eor	w20,w20,w7
+	ushr	v5.4s,v25.4s,#20
+	eor	w21,w21,w8
+	ushr	v9.4s,v26.4s,#20
+	ror	w17,w17,#24
+	ushr	v13.4s,v27.4s,#20
+	ror	w19,w19,#24
+	ushr	v17.4s,v28.4s,#20
+	ror	w20,w20,#24
+	ushr	v21.4s,v29.4s,#20
+	ror	w21,w21,#24
+	sli	v1.4s,v24.4s,#12
+	add	w13,w13,w17
+	sli	v5.4s,v25.4s,#12
+	add	w14,w14,w19
+	sli	v9.4s,v26.4s,#12
+	add	w15,w15,w20
+	sli	v13.4s,v27.4s,#12
+	add	w16,w16,w21
+	sli	v17.4s,v28.4s,#12
+	eor	w9,w9,w13
+	sli	v21.4s,v29.4s,#12
+	eor	w10,w10,w14
+	add	v0.4s,v0.4s,v1.4s
+	eor	w11,w11,w15
+	add	v4.4s,v4.4s,v5.4s
+	eor	w12,w12,w16
+	add	v8.4s,v8.4s,v9.4s
+	ror	w9,w9,#25
+	add	v12.4s,v12.4s,v13.4s
+	ror	w10,w10,#25
+	add	v16.4s,v16.4s,v17.4s
+	ror	w11,w11,#25
+	add	v20.4s,v20.4s,v21.4s
+	ror	w12,w12,#25
+	eor	v24.16b,v3.16b,v0.16b
+	add	w5,w5,w10
+	eor	v25.16b,v7.16b,v4.16b
+	add	w6,w6,w11
+	eor	v26.16b,v11.16b,v8.16b
+	add	w7,w7,w12
+	eor	v27.16b,v15.16b,v12.16b
+	add	w8,w8,w9
+	eor	v28.16b,v19.16b,v16.16b
+	eor	w21,w21,w5
+	eor	v29.16b,v23.16b,v20.16b
+	eor	w17,w17,w6
+	ushr	v3.4s,v24.4s,#24
+	eor	w19,w19,w7
+	ushr	v7.4s,v25.4s,#24
+	eor	w20,w20,w8
+	ushr	v11.4s,v26.4s,#24
+	ror	w21,w21,#16
+	ushr	v15.4s,v27.4s,#24
+	ror	w17,w17,#16
+	ushr	v19.4s,v28.4s,#24
+	ror	w19,w19,#16
+	ushr	v23.4s,v29.4s,#24
+	ror	w20,w20,#16
+	sli	v3.4s,v24.4s,#8
+	add	w15,w15,w21
+	sli	v7.4s,v25.4s,#8
+	add	w16,w16,w17
+	sli	v11.4s,v26.4s,#8
+	add	w13,w13,w19
+	sli	v15.4s,v27.4s,#8
+	add	w14,w14,w20
+	sli	v19.4s,v28.4s,#8
+	eor	w10,w10,w15
+	sli	v23.4s,v29.4s,#8
+	eor	w11,w11,w16
+	add	v2.4s,v2.4s,v3.4s
+	eor	w12,w12,w13
+	add	v6.4s,v6.4s,v7.4s
+	eor	w9,w9,w14
+	add	v10.4s,v10.4s,v11.4s
+	ror	w10,w10,#20
+	add	v14.4s,v14.4s,v15.4s
+	ror	w11,w11,#20
+	add	v18.4s,v18.4s,v19.4s
+	ror	w12,w12,#20
+	add	v22.4s,v22.4s,v23.4s
+	ror	w9,w9,#20
+	eor	v24.16b,v1.16b,v2.16b
+	add	w5,w5,w10
+	eor	v25.16b,v5.16b,v6.16b
+	add	w6,w6,w11
+	eor	v26.16b,v9.16b,v10.16b
+	add	w7,w7,w12
+	eor	v27.16b,v13.16b,v14.16b
+	add	w8,w8,w9
+	eor	v28.16b,v17.16b,v18.16b
+	eor	w21,w21,w5
+	eor	v29.16b,v21.16b,v22.16b
+	eor	w17,w17,w6
+	ushr	v1.4s,v24.4s,#25
+	eor	w19,w19,w7
+	ushr	v5.4s,v25.4s,#25
+	eor	w20,w20,w8
+	ushr	v9.4s,v26.4s,#25
+	ror	w21,w21,#24
+	ushr	v13.4s,v27.4s,#25
+	ror	w17,w17,#24
+	ushr	v17.4s,v28.4s,#25
+	ror	w19,w19,#24
+	ushr	v21.4s,v29.4s,#25
+	ror	w20,w20,#24
+	sli	v1.4s,v24.4s,#7
+	add	w15,w15,w21
+	sli	v5.4s,v25.4s,#7
+	add	w16,w16,w17
+	sli	v9.4s,v26.4s,#7
+	add	w13,w13,w19
+	sli	v13.4s,v27.4s,#7
+	add	w14,w14,w20
+	sli	v17.4s,v28.4s,#7
+	eor	w10,w10,w15
+	sli	v21.4s,v29.4s,#7
+	eor	w11,w11,w16
+	ext	v2.16b,v2.16b,v2.16b,#8
+	eor	w12,w12,w13
+	ext	v6.16b,v6.16b,v6.16b,#8
+	eor	w9,w9,w14
+	ext	v10.16b,v10.16b,v10.16b,#8
+	ror	w10,w10,#25
+	ext	v14.16b,v14.16b,v14.16b,#8
+	ror	w11,w11,#25
+	ext	v18.16b,v18.16b,v18.16b,#8
+	ror	w12,w12,#25
+	ext	v22.16b,v22.16b,v22.16b,#8
+	ror	w9,w9,#25
+	ext	v3.16b,v3.16b,v3.16b,#12
+	ext	v7.16b,v7.16b,v7.16b,#12
+	ext	v11.16b,v11.16b,v11.16b,#12
+	ext	v15.16b,v15.16b,v15.16b,#12
+	ext	v19.16b,v19.16b,v19.16b,#12
+	ext	v23.16b,v23.16b,v23.16b,#12
+	ext	v1.16b,v1.16b,v1.16b,#4
+	ext	v5.16b,v5.16b,v5.16b,#4
+	ext	v9.16b,v9.16b,v9.16b,#4
+	ext	v13.16b,v13.16b,v13.16b,#4
+	ext	v17.16b,v17.16b,v17.16b,#4
+	ext	v21.16b,v21.16b,v21.16b,#4
+	add	v0.4s,v0.4s,v1.4s
+	add	w5,w5,w9
+	add	v4.4s,v4.4s,v5.4s
+	add	w6,w6,w10
+	add	v8.4s,v8.4s,v9.4s
+	add	w7,w7,w11
+	add	v12.4s,v12.4s,v13.4s
+	add	w8,w8,w12
+	add	v16.4s,v16.4s,v17.4s
+	eor	w17,w17,w5
+	add	v20.4s,v20.4s,v21.4s
+	eor	w19,w19,w6
+	eor	v3.16b,v3.16b,v0.16b
+	eor	w20,w20,w7
+	eor	v7.16b,v7.16b,v4.16b
+	eor	w21,w21,w8
+	eor	v11.16b,v11.16b,v8.16b
+	ror	w17,w17,#16
+	eor	v15.16b,v15.16b,v12.16b
+	ror	w19,w19,#16
+	eor	v19.16b,v19.16b,v16.16b
+	ror	w20,w20,#16
+	eor	v23.16b,v23.16b,v20.16b
+	ror	w21,w21,#16
+	rev32	v3.8h,v3.8h
+	add	w13,w13,w17
+	rev32	v7.8h,v7.8h
+	add	w14,w14,w19
+	rev32	v11.8h,v11.8h
+	add	w15,w15,w20
+	rev32	v15.8h,v15.8h
+	add	w16,w16,w21
+	rev32	v19.8h,v19.8h
+	eor	w9,w9,w13
+	rev32	v23.8h,v23.8h
+	eor	w10,w10,w14
+	add	v2.4s,v2.4s,v3.4s
+	eor	w11,w11,w15
+	add	v6.4s,v6.4s,v7.4s
+	eor	w12,w12,w16
+	add	v10.4s,v10.4s,v11.4s
+	ror	w9,w9,#20
+	add	v14.4s,v14.4s,v15.4s
+	ror	w10,w10,#20
+	add	v18.4s,v18.4s,v19.4s
+	ror	w11,w11,#20
+	add	v22.4s,v22.4s,v23.4s
+	ror	w12,w12,#20
+	eor	v24.16b,v1.16b,v2.16b
+	add	w5,w5,w9
+	eor	v25.16b,v5.16b,v6.16b
+	add	w6,w6,w10
+	eor	v26.16b,v9.16b,v10.16b
+	add	w7,w7,w11
+	eor	v27.16b,v13.16b,v14.16b
+	add	w8,w8,w12
+	eor	v28.16b,v17.16b,v18.16b
+	eor	w17,w17,w5
+	eor	v29.16b,v21.16b,v22.16b
+	eor	w19,w19,w6
+	ushr	v1.4s,v24.4s,#20
+	eor	w20,w20,w7
+	ushr	v5.4s,v25.4s,#20
+	eor	w21,w21,w8
+	ushr	v9.4s,v26.4s,#20
+	ror	w17,w17,#24
+	ushr	v13.4s,v27.4s,#20
+	ror	w19,w19,#24
+	ushr	v17.4s,v28.4s,#20
+	ror	w20,w20,#24
+	ushr	v21.4s,v29.4s,#20
+	ror	w21,w21,#24
+	sli	v1.4s,v24.4s,#12
+	add	w13,w13,w17
+	sli	v5.4s,v25.4s,#12
+	add	w14,w14,w19
+	sli	v9.4s,v26.4s,#12
+	add	w15,w15,w20
+	sli	v13.4s,v27.4s,#12
+	add	w16,w16,w21
+	sli	v17.4s,v28.4s,#12
+	eor	w9,w9,w13
+	sli	v21.4s,v29.4s,#12
+	eor	w10,w10,w14
+	add	v0.4s,v0.4s,v1.4s
+	eor	w11,w11,w15
+	add	v4.4s,v4.4s,v5.4s
+	eor	w12,w12,w16
+	add	v8.4s,v8.4s,v9.4s
+	ror	w9,w9,#25
+	add	v12.4s,v12.4s,v13.4s
+	ror	w10,w10,#25
+	add	v16.4s,v16.4s,v17.4s
+	ror	w11,w11,#25
+	add	v20.4s,v20.4s,v21.4s
+	ror	w12,w12,#25
+	eor	v24.16b,v3.16b,v0.16b
+	add	w5,w5,w10
+	eor	v25.16b,v7.16b,v4.16b
+	add	w6,w6,w11
+	eor	v26.16b,v11.16b,v8.16b
+	add	w7,w7,w12
+	eor	v27.16b,v15.16b,v12.16b
+	add	w8,w8,w9
+	eor	v28.16b,v19.16b,v16.16b
+	eor	w21,w21,w5
+	eor	v29.16b,v23.16b,v20.16b
+	eor	w17,w17,w6
+	ushr	v3.4s,v24.4s,#24
+	eor	w19,w19,w7
+	ushr	v7.4s,v25.4s,#24
+	eor	w20,w20,w8
+	ushr	v11.4s,v26.4s,#24
+	ror	w21,w21,#16
+	ushr	v15.4s,v27.4s,#24
+	ror	w17,w17,#16
+	ushr	v19.4s,v28.4s,#24
+	ror	w19,w19,#16
+	ushr	v23.4s,v29.4s,#24
+	ror	w20,w20,#16
+	sli	v3.4s,v24.4s,#8
+	add	w15,w15,w21
+	sli	v7.4s,v25.4s,#8
+	add	w16,w16,w17
+	sli	v11.4s,v26.4s,#8
+	add	w13,w13,w19
+	sli	v15.4s,v27.4s,#8
+	add	w14,w14,w20
+	sli	v19.4s,v28.4s,#8
+	eor	w10,w10,w15
+	sli	v23.4s,v29.4s,#8
+	eor	w11,w11,w16
+	add	v2.4s,v2.4s,v3.4s
+	eor	w12,w12,w13
+	add	v6.4s,v6.4s,v7.4s
+	eor	w9,w9,w14
+	add	v10.4s,v10.4s,v11.4s
+	ror	w10,w10,#20
+	add	v14.4s,v14.4s,v15.4s
+	ror	w11,w11,#20
+	add	v18.4s,v18.4s,v19.4s
+	ror	w12,w12,#20
+	add	v22.4s,v22.4s,v23.4s
+	ror	w9,w9,#20
+	eor	v24.16b,v1.16b,v2.16b
+	add	w5,w5,w10
+	eor	v25.16b,v5.16b,v6.16b
+	add	w6,w6,w11
+	eor	v26.16b,v9.16b,v10.16b
+	add	w7,w7,w12
+	eor	v27.16b,v13.16b,v14.16b
+	add	w8,w8,w9
+	eor	v28.16b,v17.16b,v18.16b
+	eor	w21,w21,w5
+	eor	v29.16b,v21.16b,v22.16b
+	eor	w17,w17,w6
+	ushr	v1.4s,v24.4s,#25
+	eor	w19,w19,w7
+	ushr	v5.4s,v25.4s,#25
+	eor	w20,w20,w8
+	ushr	v9.4s,v26.4s,#25
+	ror	w21,w21,#24
+	ushr	v13.4s,v27.4s,#25
+	ror	w17,w17,#24
+	ushr	v17.4s,v28.4s,#25
+	ror	w19,w19,#24
+	ushr	v21.4s,v29.4s,#25
+	ror	w20,w20,#24
+	sli	v1.4s,v24.4s,#7
+	add	w15,w15,w21
+	sli	v5.4s,v25.4s,#7
+	add	w16,w16,w17
+	sli	v9.4s,v26.4s,#7
+	add	w13,w13,w19
+	sli	v13.4s,v27.4s,#7
+	add	w14,w14,w20
+	sli	v17.4s,v28.4s,#7
+	eor	w10,w10,w15
+	sli	v21.4s,v29.4s,#7
+	eor	w11,w11,w16
+	ext	v2.16b,v2.16b,v2.16b,#8
+	eor	w12,w12,w13
+	ext	v6.16b,v6.16b,v6.16b,#8
+	eor	w9,w9,w14
+	ext	v10.16b,v10.16b,v10.16b,#8
+	ror	w10,w10,#25
+	ext	v14.16b,v14.16b,v14.16b,#8
+	ror	w11,w11,#25
+	ext	v18.16b,v18.16b,v18.16b,#8
+	ror	w12,w12,#25
+	ext	v22.16b,v22.16b,v22.16b,#8
+	ror	w9,w9,#25
+	ext	v3.16b,v3.16b,v3.16b,#4
+	ext	v7.16b,v7.16b,v7.16b,#4
+	ext	v11.16b,v11.16b,v11.16b,#4
+	ext	v15.16b,v15.16b,v15.16b,#4
+	ext	v19.16b,v19.16b,v19.16b,#4
+	ext	v23.16b,v23.16b,v23.16b,#4
+	ext	v1.16b,v1.16b,v1.16b,#12
+	ext	v5.16b,v5.16b,v5.16b,#12
+	ext	v9.16b,v9.16b,v9.16b,#12
+	ext	v13.16b,v13.16b,v13.16b,#12
+	ext	v17.16b,v17.16b,v17.16b,#12
+	ext	v21.16b,v21.16b,v21.16b,#12
+	cbnz	x4,Loop_lower_neon
+
+	add	w5,w5,w22		// accumulate key block
+	ldp	q24,q25,[sp,#0]
+	add	x6,x6,x22,lsr#32
+	ldp	q26,q27,[sp,#32]
+	add	w7,w7,w23
+	ldp	q28,q29,[sp,#64]
+	add	x8,x8,x23,lsr#32
+	add	v0.4s,v0.4s,v24.4s
+	add	w9,w9,w24
+	add	v4.4s,v4.4s,v24.4s
+	add	x10,x10,x24,lsr#32
+	add	v8.4s,v8.4s,v24.4s
+	add	w11,w11,w25
+	add	v12.4s,v12.4s,v24.4s
+	add	x12,x12,x25,lsr#32
+	add	v16.4s,v16.4s,v24.4s
+	add	w13,w13,w26
+	add	v20.4s,v20.4s,v24.4s
+	add	x14,x14,x26,lsr#32
+	add	v2.4s,v2.4s,v26.4s
+	add	w15,w15,w27
+	add	v6.4s,v6.4s,v26.4s
+	add	x16,x16,x27,lsr#32
+	add	v10.4s,v10.4s,v26.4s
+	add	w17,w17,w28
+	add	v14.4s,v14.4s,v26.4s
+	add	x19,x19,x28,lsr#32
+	add	v18.4s,v18.4s,v26.4s
+	add	w20,w20,w30
+	add	v22.4s,v22.4s,v26.4s
+	add	x21,x21,x30,lsr#32
+	add	v19.4s,v19.4s,v31.4s			// +4
+	add	x5,x5,x6,lsl#32	// pack
+	add	v23.4s,v23.4s,v31.4s			// +4
+	add	x7,x7,x8,lsl#32
+	add	v3.4s,v3.4s,v27.4s
+	ldp	x6,x8,[x1,#0]		// load input
+	add	v7.4s,v7.4s,v28.4s
+	add	x9,x9,x10,lsl#32
+	add	v11.4s,v11.4s,v29.4s
+	add	x11,x11,x12,lsl#32
+	add	v15.4s,v15.4s,v30.4s
+	ldp	x10,x12,[x1,#16]
+	add	v19.4s,v19.4s,v27.4s
+	add	x13,x13,x14,lsl#32
+	add	v23.4s,v23.4s,v28.4s
+	add	x15,x15,x16,lsl#32
+	add	v1.4s,v1.4s,v25.4s
+	ldp	x14,x16,[x1,#32]
+	add	v5.4s,v5.4s,v25.4s
+	add	x17,x17,x19,lsl#32
+	add	v9.4s,v9.4s,v25.4s
+	add	x20,x20,x21,lsl#32
+	add	v13.4s,v13.4s,v25.4s
+	ldp	x19,x21,[x1,#48]
+	add	v17.4s,v17.4s,v25.4s
+	add	x1,x1,#64
+	add	v21.4s,v21.4s,v25.4s
+
+#ifdef	__ARMEB__
+	rev	x5,x5
+	rev	x7,x7
+	rev	x9,x9
+	rev	x11,x11
+	rev	x13,x13
+	rev	x15,x15
+	rev	x17,x17
+	rev	x20,x20
+#endif
+	ld1	{v24.16b,v25.16b,v26.16b,v27.16b},[x1],#64
+	eor	x5,x5,x6
+	eor	x7,x7,x8
+	eor	x9,x9,x10
+	eor	x11,x11,x12
+	eor	x13,x13,x14
+	eor	v0.16b,v0.16b,v24.16b
+	eor	x15,x15,x16
+	eor	v1.16b,v1.16b,v25.16b
+	eor	x17,x17,x19
+	eor	v2.16b,v2.16b,v26.16b
+	eor	x20,x20,x21
+	eor	v3.16b,v3.16b,v27.16b
+	ld1	{v24.16b,v25.16b,v26.16b,v27.16b},[x1],#64
+
+	stp	x5,x7,[x0,#0]		// store output
+	add	x28,x28,#7			// increment counter
+	stp	x9,x11,[x0,#16]
+	stp	x13,x15,[x0,#32]
+	stp	x17,x20,[x0,#48]
+	add	x0,x0,#64
+	st1	{v0.16b,v1.16b,v2.16b,v3.16b},[x0],#64
+
+	ld1	{v0.16b,v1.16b,v2.16b,v3.16b},[x1],#64
+	eor	v4.16b,v4.16b,v24.16b
+	eor	v5.16b,v5.16b,v25.16b
+	eor	v6.16b,v6.16b,v26.16b
+	eor	v7.16b,v7.16b,v27.16b
+	st1	{v4.16b,v5.16b,v6.16b,v7.16b},[x0],#64
+
+	ld1	{v4.16b,v5.16b,v6.16b,v7.16b},[x1],#64
+	eor	v8.16b,v8.16b,v0.16b
+	ldp	q24,q25,[sp,#0]
+	eor	v9.16b,v9.16b,v1.16b
+	ldp	q26,q27,[sp,#32]
+	eor	v10.16b,v10.16b,v2.16b
+	eor	v11.16b,v11.16b,v3.16b
+	st1	{v8.16b,v9.16b,v10.16b,v11.16b},[x0],#64
+
+	ld1	{v8.16b,v9.16b,v10.16b,v11.16b},[x1],#64
+	eor	v12.16b,v12.16b,v4.16b
+	eor	v13.16b,v13.16b,v5.16b
+	eor	v14.16b,v14.16b,v6.16b
+	eor	v15.16b,v15.16b,v7.16b
+	st1	{v12.16b,v13.16b,v14.16b,v15.16b},[x0],#64
+
+	ld1	{v12.16b,v13.16b,v14.16b,v15.16b},[x1],#64
+	eor	v16.16b,v16.16b,v8.16b
+	eor	v17.16b,v17.16b,v9.16b
+	eor	v18.16b,v18.16b,v10.16b
+	eor	v19.16b,v19.16b,v11.16b
+	st1	{v16.16b,v17.16b,v18.16b,v19.16b},[x0],#64
+
+	shl	v0.4s,v31.4s,#1			// 4 -> 8
+	eor	v20.16b,v20.16b,v12.16b
+	eor	v21.16b,v21.16b,v13.16b
+	eor	v22.16b,v22.16b,v14.16b
+	eor	v23.16b,v23.16b,v15.16b
+	st1	{v20.16b,v21.16b,v22.16b,v23.16b},[x0],#64
+
+	add	v27.4s,v27.4s,v0.4s			// += 8
+	add	v28.4s,v28.4s,v0.4s
+	add	v29.4s,v29.4s,v0.4s
+	add	v30.4s,v30.4s,v0.4s
+
+	b.hs	Loop_outer_512_neon
+
+	adds	x2,x2,#512
+	ushr	v0.4s,v31.4s,#2			// 4 -> 1
+
+	ldp	d8,d9,[sp,#128+0]		// meet ABI requirements
+	ldp	d10,d11,[sp,#128+16]
+	ldp	d12,d13,[sp,#128+32]
+	ldp	d14,d15,[sp,#128+48]
+
+	stp	q24,q31,[sp,#0]		// wipe off-load area
+	stp	q24,q31,[sp,#32]
+	stp	q24,q31,[sp,#64]
+
+	b.eq	Ldone_512_neon
+
+	cmp	x2,#192
+	sub	v27.4s,v27.4s,v0.4s			// -= 1
+	sub	v28.4s,v28.4s,v0.4s
+	sub	v29.4s,v29.4s,v0.4s
+	add	sp,sp,#128
+	b.hs	Loop_outer_neon
+
+	eor	v25.16b,v25.16b,v25.16b
+	eor	v26.16b,v26.16b,v26.16b
+	eor	v27.16b,v27.16b,v27.16b
+	eor	v28.16b,v28.16b,v28.16b
+	eor	v29.16b,v29.16b,v29.16b
+	eor	v30.16b,v30.16b,v30.16b
+	b	Loop_outer
+
+Ldone_512_neon:
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#128+64
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#96
+	ret
+
diff --git a/third_party/boringssl/ios-aarch64/crypto/fipsmodule/aesv8-armx64.S b/third_party/boringssl/ios-aarch64/crypto/fipsmodule/aesv8-armx64.S
new file mode 100644
index 0000000..90310f62
--- /dev/null
+++ b/third_party/boringssl/ios-aarch64/crypto/fipsmodule/aesv8-armx64.S
@@ -0,0 +1,755 @@
+#include <openssl/arm_arch.h>
+
+#if __ARM_MAX_ARCH__>=7
+.text
+#if !defined(__clang__) || defined(BORINGSSL_CLANG_SUPPORTS_DOT_ARCH)
+
+#endif
+.align	5
+Lrcon:
+.long	0x01,0x01,0x01,0x01
+.long	0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d	// rotate-n-splat
+.long	0x1b,0x1b,0x1b,0x1b
+
+.globl	_aes_hw_set_encrypt_key
+.private_extern	_aes_hw_set_encrypt_key
+
+.align	5
+_aes_hw_set_encrypt_key:
+Lenc_key:
+	stp	x29,x30,[sp,#-16]!
+	add	x29,sp,#0
+	mov	x3,#-1
+	cmp	x0,#0
+	b.eq	Lenc_key_abort
+	cmp	x2,#0
+	b.eq	Lenc_key_abort
+	mov	x3,#-2
+	cmp	w1,#128
+	b.lt	Lenc_key_abort
+	cmp	w1,#256
+	b.gt	Lenc_key_abort
+	tst	w1,#0x3f
+	b.ne	Lenc_key_abort
+
+	adr	x3,Lrcon
+	cmp	w1,#192
+
+	eor	v0.16b,v0.16b,v0.16b
+	ld1	{v3.16b},[x0],#16
+	mov	w1,#8		// reuse w1
+	ld1	{v1.4s,v2.4s},[x3],#32
+
+	b.lt	Loop128
+	b.eq	L192
+	b	L256
+
+.align	4
+Loop128:
+	tbl	v6.16b,{v3.16b},v2.16b
+	ext	v5.16b,v0.16b,v3.16b,#12
+	st1	{v3.4s},[x2],#16
+	aese	v6.16b,v0.16b
+	subs	w1,w1,#1
+
+	eor	v3.16b,v3.16b,v5.16b
+	ext	v5.16b,v0.16b,v5.16b,#12
+	eor	v3.16b,v3.16b,v5.16b
+	ext	v5.16b,v0.16b,v5.16b,#12
+	eor	v6.16b,v6.16b,v1.16b
+	eor	v3.16b,v3.16b,v5.16b
+	shl	v1.16b,v1.16b,#1
+	eor	v3.16b,v3.16b,v6.16b
+	b.ne	Loop128
+
+	ld1	{v1.4s},[x3]
+
+	tbl	v6.16b,{v3.16b},v2.16b
+	ext	v5.16b,v0.16b,v3.16b,#12
+	st1	{v3.4s},[x2],#16
+	aese	v6.16b,v0.16b
+
+	eor	v3.16b,v3.16b,v5.16b
+	ext	v5.16b,v0.16b,v5.16b,#12
+	eor	v3.16b,v3.16b,v5.16b
+	ext	v5.16b,v0.16b,v5.16b,#12
+	eor	v6.16b,v6.16b,v1.16b
+	eor	v3.16b,v3.16b,v5.16b
+	shl	v1.16b,v1.16b,#1
+	eor	v3.16b,v3.16b,v6.16b
+
+	tbl	v6.16b,{v3.16b},v2.16b
+	ext	v5.16b,v0.16b,v3.16b,#12
+	st1	{v3.4s},[x2],#16
+	aese	v6.16b,v0.16b
+
+	eor	v3.16b,v3.16b,v5.16b
+	ext	v5.16b,v0.16b,v5.16b,#12
+	eor	v3.16b,v3.16b,v5.16b
+	ext	v5.16b,v0.16b,v5.16b,#12
+	eor	v6.16b,v6.16b,v1.16b
+	eor	v3.16b,v3.16b,v5.16b
+	eor	v3.16b,v3.16b,v6.16b
+	st1	{v3.4s},[x2]
+	add	x2,x2,#0x50
+
+	mov	w12,#10
+	b	Ldone
+
+.align	4
+L192:
+	ld1	{v4.8b},[x0],#8
+	movi	v6.16b,#8			// borrow v6.16b
+	st1	{v3.4s},[x2],#16
+	sub	v2.16b,v2.16b,v6.16b	// adjust the mask
+
+Loop192:
+	tbl	v6.16b,{v4.16b},v2.16b
+	ext	v5.16b,v0.16b,v3.16b,#12
+	st1	{v4.8b},[x2],#8
+	aese	v6.16b,v0.16b
+	subs	w1,w1,#1
+
+	eor	v3.16b,v3.16b,v5.16b
+	ext	v5.16b,v0.16b,v5.16b,#12
+	eor	v3.16b,v3.16b,v5.16b
+	ext	v5.16b,v0.16b,v5.16b,#12
+	eor	v3.16b,v3.16b,v5.16b
+
+	dup	v5.4s,v3.s[3]
+	eor	v5.16b,v5.16b,v4.16b
+	eor	v6.16b,v6.16b,v1.16b
+	ext	v4.16b,v0.16b,v4.16b,#12
+	shl	v1.16b,v1.16b,#1
+	eor	v4.16b,v4.16b,v5.16b
+	eor	v3.16b,v3.16b,v6.16b
+	eor	v4.16b,v4.16b,v6.16b
+	st1	{v3.4s},[x2],#16
+	b.ne	Loop192
+
+	mov	w12,#12
+	add	x2,x2,#0x20
+	b	Ldone
+
+.align	4
+L256:
+	ld1	{v4.16b},[x0]
+	mov	w1,#7
+	mov	w12,#14
+	st1	{v3.4s},[x2],#16
+
+Loop256:
+	tbl	v6.16b,{v4.16b},v2.16b
+	ext	v5.16b,v0.16b,v3.16b,#12
+	st1	{v4.4s},[x2],#16
+	aese	v6.16b,v0.16b
+	subs	w1,w1,#1
+
+	eor	v3.16b,v3.16b,v5.16b
+	ext	v5.16b,v0.16b,v5.16b,#12
+	eor	v3.16b,v3.16b,v5.16b
+	ext	v5.16b,v0.16b,v5.16b,#12
+	eor	v6.16b,v6.16b,v1.16b
+	eor	v3.16b,v3.16b,v5.16b
+	shl	v1.16b,v1.16b,#1
+	eor	v3.16b,v3.16b,v6.16b
+	st1	{v3.4s},[x2],#16
+	b.eq	Ldone
+
+	dup	v6.4s,v3.s[3]		// just splat
+	ext	v5.16b,v0.16b,v4.16b,#12
+	aese	v6.16b,v0.16b
+
+	eor	v4.16b,v4.16b,v5.16b
+	ext	v5.16b,v0.16b,v5.16b,#12
+	eor	v4.16b,v4.16b,v5.16b
+	ext	v5.16b,v0.16b,v5.16b,#12
+	eor	v4.16b,v4.16b,v5.16b
+
+	eor	v4.16b,v4.16b,v6.16b
+	b	Loop256
+
+Ldone:
+	str	w12,[x2]
+	mov	x3,#0
+
+Lenc_key_abort:
+	mov	x0,x3			// return value
+	ldr	x29,[sp],#16
+	ret
+
+
+.globl	_aes_hw_set_decrypt_key
+.private_extern	_aes_hw_set_decrypt_key
+
+.align	5
+_aes_hw_set_decrypt_key:
+	stp	x29,x30,[sp,#-16]!
+	add	x29,sp,#0
+	bl	Lenc_key
+
+	cmp	x0,#0
+	b.ne	Ldec_key_abort
+
+	sub	x2,x2,#240		// restore original x2
+	mov	x4,#-16
+	add	x0,x2,x12,lsl#4	// end of key schedule
+
+	ld1	{v0.4s},[x2]
+	ld1	{v1.4s},[x0]
+	st1	{v0.4s},[x0],x4
+	st1	{v1.4s},[x2],#16
+
+Loop_imc:
+	ld1	{v0.4s},[x2]
+	ld1	{v1.4s},[x0]
+	aesimc	v0.16b,v0.16b
+	aesimc	v1.16b,v1.16b
+	st1	{v0.4s},[x0],x4
+	st1	{v1.4s},[x2],#16
+	cmp	x0,x2
+	b.hi	Loop_imc
+
+	ld1	{v0.4s},[x2]
+	aesimc	v0.16b,v0.16b
+	st1	{v0.4s},[x0]
+
+	eor	x0,x0,x0		// return value
+Ldec_key_abort:
+	ldp	x29,x30,[sp],#16
+	ret
+
+.globl	_aes_hw_encrypt
+.private_extern	_aes_hw_encrypt
+
+.align	5
+_aes_hw_encrypt:
+	ldr	w3,[x2,#240]
+	ld1	{v0.4s},[x2],#16
+	ld1	{v2.16b},[x0]
+	sub	w3,w3,#2
+	ld1	{v1.4s},[x2],#16
+
+Loop_enc:
+	aese	v2.16b,v0.16b
+	aesmc	v2.16b,v2.16b
+	ld1	{v0.4s},[x2],#16
+	subs	w3,w3,#2
+	aese	v2.16b,v1.16b
+	aesmc	v2.16b,v2.16b
+	ld1	{v1.4s},[x2],#16
+	b.gt	Loop_enc
+
+	aese	v2.16b,v0.16b
+	aesmc	v2.16b,v2.16b
+	ld1	{v0.4s},[x2]
+	aese	v2.16b,v1.16b
+	eor	v2.16b,v2.16b,v0.16b
+
+	st1	{v2.16b},[x1]
+	ret
+
+.globl	_aes_hw_decrypt
+.private_extern	_aes_hw_decrypt
+
+.align	5
+_aes_hw_decrypt:
+	ldr	w3,[x2,#240]
+	ld1	{v0.4s},[x2],#16
+	ld1	{v2.16b},[x0]
+	sub	w3,w3,#2
+	ld1	{v1.4s},[x2],#16
+
+Loop_dec:
+	aesd	v2.16b,v0.16b
+	aesimc	v2.16b,v2.16b
+	ld1	{v0.4s},[x2],#16
+	subs	w3,w3,#2
+	aesd	v2.16b,v1.16b
+	aesimc	v2.16b,v2.16b
+	ld1	{v1.4s},[x2],#16
+	b.gt	Loop_dec
+
+	aesd	v2.16b,v0.16b
+	aesimc	v2.16b,v2.16b
+	ld1	{v0.4s},[x2]
+	aesd	v2.16b,v1.16b
+	eor	v2.16b,v2.16b,v0.16b
+
+	st1	{v2.16b},[x1]
+	ret
+
+.globl	_aes_hw_cbc_encrypt
+.private_extern	_aes_hw_cbc_encrypt
+
+.align	5
+_aes_hw_cbc_encrypt:
+	stp	x29,x30,[sp,#-16]!
+	add	x29,sp,#0
+	subs	x2,x2,#16
+	mov	x8,#16
+	b.lo	Lcbc_abort
+	csel	x8,xzr,x8,eq
+
+	cmp	w5,#0			// en- or decrypting?
+	ldr	w5,[x3,#240]
+	and	x2,x2,#-16
+	ld1	{v6.16b},[x4]
+	ld1	{v0.16b},[x0],x8
+
+	ld1	{v16.4s,v17.4s},[x3]		// load key schedule...
+	sub	w5,w5,#6
+	add	x7,x3,x5,lsl#4	// pointer to last 7 round keys
+	sub	w5,w5,#2
+	ld1	{v18.4s,v19.4s},[x7],#32
+	ld1	{v20.4s,v21.4s},[x7],#32
+	ld1	{v22.4s,v23.4s},[x7],#32
+	ld1	{v7.4s},[x7]
+
+	add	x7,x3,#32
+	mov	w6,w5
+	b.eq	Lcbc_dec
+
+	cmp	w5,#2
+	eor	v0.16b,v0.16b,v6.16b
+	eor	v5.16b,v16.16b,v7.16b
+	b.eq	Lcbc_enc128
+
+	ld1	{v2.4s,v3.4s},[x7]
+	add	x7,x3,#16
+	add	x6,x3,#16*4
+	add	x12,x3,#16*5
+	aese	v0.16b,v16.16b
+	aesmc	v0.16b,v0.16b
+	add	x14,x3,#16*6
+	add	x3,x3,#16*7
+	b	Lenter_cbc_enc
+
+.align	4
+Loop_cbc_enc:
+	aese	v0.16b,v16.16b
+	aesmc	v0.16b,v0.16b
+	st1	{v6.16b},[x1],#16
+Lenter_cbc_enc:
+	aese	v0.16b,v17.16b
+	aesmc	v0.16b,v0.16b
+	aese	v0.16b,v2.16b
+	aesmc	v0.16b,v0.16b
+	ld1	{v16.4s},[x6]
+	cmp	w5,#4
+	aese	v0.16b,v3.16b
+	aesmc	v0.16b,v0.16b
+	ld1	{v17.4s},[x12]
+	b.eq	Lcbc_enc192
+
+	aese	v0.16b,v16.16b
+	aesmc	v0.16b,v0.16b
+	ld1	{v16.4s},[x14]
+	aese	v0.16b,v17.16b
+	aesmc	v0.16b,v0.16b
+	ld1	{v17.4s},[x3]
+	nop
+
+Lcbc_enc192:
+	aese	v0.16b,v16.16b
+	aesmc	v0.16b,v0.16b
+	subs	x2,x2,#16
+	aese	v0.16b,v17.16b
+	aesmc	v0.16b,v0.16b
+	csel	x8,xzr,x8,eq
+	aese	v0.16b,v18.16b
+	aesmc	v0.16b,v0.16b
+	aese	v0.16b,v19.16b
+	aesmc	v0.16b,v0.16b
+	ld1	{v16.16b},[x0],x8
+	aese	v0.16b,v20.16b
+	aesmc	v0.16b,v0.16b
+	eor	v16.16b,v16.16b,v5.16b
+	aese	v0.16b,v21.16b
+	aesmc	v0.16b,v0.16b
+	ld1	{v17.4s},[x7]		// re-pre-load rndkey[1]
+	aese	v0.16b,v22.16b
+	aesmc	v0.16b,v0.16b
+	aese	v0.16b,v23.16b
+	eor	v6.16b,v0.16b,v7.16b
+	b.hs	Loop_cbc_enc
+
+	st1	{v6.16b},[x1],#16
+	b	Lcbc_done
+
+.align	5
+Lcbc_enc128:
+	ld1	{v2.4s,v3.4s},[x7]
+	aese	v0.16b,v16.16b
+	aesmc	v0.16b,v0.16b
+	b	Lenter_cbc_enc128
+Loop_cbc_enc128:
+	aese	v0.16b,v16.16b
+	aesmc	v0.16b,v0.16b
+	st1	{v6.16b},[x1],#16
+Lenter_cbc_enc128:
+	aese	v0.16b,v17.16b
+	aesmc	v0.16b,v0.16b
+	subs	x2,x2,#16
+	aese	v0.16b,v2.16b
+	aesmc	v0.16b,v0.16b
+	csel	x8,xzr,x8,eq
+	aese	v0.16b,v3.16b
+	aesmc	v0.16b,v0.16b
+	aese	v0.16b,v18.16b
+	aesmc	v0.16b,v0.16b
+	aese	v0.16b,v19.16b
+	aesmc	v0.16b,v0.16b
+	ld1	{v16.16b},[x0],x8
+	aese	v0.16b,v20.16b
+	aesmc	v0.16b,v0.16b
+	aese	v0.16b,v21.16b
+	aesmc	v0.16b,v0.16b
+	aese	v0.16b,v22.16b
+	aesmc	v0.16b,v0.16b
+	eor	v16.16b,v16.16b,v5.16b
+	aese	v0.16b,v23.16b
+	eor	v6.16b,v0.16b,v7.16b
+	b.hs	Loop_cbc_enc128
+
+	st1	{v6.16b},[x1],#16
+	b	Lcbc_done
+.align	5
+Lcbc_dec:
+	ld1	{v18.16b},[x0],#16
+	subs	x2,x2,#32		// bias
+	add	w6,w5,#2
+	orr	v3.16b,v0.16b,v0.16b
+	orr	v1.16b,v0.16b,v0.16b
+	orr	v19.16b,v18.16b,v18.16b
+	b.lo	Lcbc_dec_tail
+
+	orr	v1.16b,v18.16b,v18.16b
+	ld1	{v18.16b},[x0],#16
+	orr	v2.16b,v0.16b,v0.16b
+	orr	v3.16b,v1.16b,v1.16b
+	orr	v19.16b,v18.16b,v18.16b
+
+Loop3x_cbc_dec:
+	aesd	v0.16b,v16.16b
+	aesimc	v0.16b,v0.16b
+	aesd	v1.16b,v16.16b
+	aesimc	v1.16b,v1.16b
+	aesd	v18.16b,v16.16b
+	aesimc	v18.16b,v18.16b
+	ld1	{v16.4s},[x7],#16
+	subs	w6,w6,#2
+	aesd	v0.16b,v17.16b
+	aesimc	v0.16b,v0.16b
+	aesd	v1.16b,v17.16b
+	aesimc	v1.16b,v1.16b
+	aesd	v18.16b,v17.16b
+	aesimc	v18.16b,v18.16b
+	ld1	{v17.4s},[x7],#16
+	b.gt	Loop3x_cbc_dec
+
+	aesd	v0.16b,v16.16b
+	aesimc	v0.16b,v0.16b
+	aesd	v1.16b,v16.16b
+	aesimc	v1.16b,v1.16b
+	aesd	v18.16b,v16.16b
+	aesimc	v18.16b,v18.16b
+	eor	v4.16b,v6.16b,v7.16b
+	subs	x2,x2,#0x30
+	eor	v5.16b,v2.16b,v7.16b
+	csel	x6,x2,x6,lo			// x6, w6, is zero at this point
+	aesd	v0.16b,v17.16b
+	aesimc	v0.16b,v0.16b
+	aesd	v1.16b,v17.16b
+	aesimc	v1.16b,v1.16b
+	aesd	v18.16b,v17.16b
+	aesimc	v18.16b,v18.16b
+	eor	v17.16b,v3.16b,v7.16b
+	add	x0,x0,x6		// x0 is adjusted in such way that
+					// at exit from the loop v1.16b-v18.16b
+					// are loaded with last "words"
+	orr	v6.16b,v19.16b,v19.16b
+	mov	x7,x3
+	aesd	v0.16b,v20.16b
+	aesimc	v0.16b,v0.16b
+	aesd	v1.16b,v20.16b
+	aesimc	v1.16b,v1.16b
+	aesd	v18.16b,v20.16b
+	aesimc	v18.16b,v18.16b
+	ld1	{v2.16b},[x0],#16
+	aesd	v0.16b,v21.16b
+	aesimc	v0.16b,v0.16b
+	aesd	v1.16b,v21.16b
+	aesimc	v1.16b,v1.16b
+	aesd	v18.16b,v21.16b
+	aesimc	v18.16b,v18.16b
+	ld1	{v3.16b},[x0],#16
+	aesd	v0.16b,v22.16b
+	aesimc	v0.16b,v0.16b
+	aesd	v1.16b,v22.16b
+	aesimc	v1.16b,v1.16b
+	aesd	v18.16b,v22.16b
+	aesimc	v18.16b,v18.16b
+	ld1	{v19.16b},[x0],#16
+	aesd	v0.16b,v23.16b
+	aesd	v1.16b,v23.16b
+	aesd	v18.16b,v23.16b
+	ld1	{v16.4s},[x7],#16	// re-pre-load rndkey[0]
+	add	w6,w5,#2
+	eor	v4.16b,v4.16b,v0.16b
+	eor	v5.16b,v5.16b,v1.16b
+	eor	v18.16b,v18.16b,v17.16b
+	ld1	{v17.4s},[x7],#16	// re-pre-load rndkey[1]
+	st1	{v4.16b},[x1],#16
+	orr	v0.16b,v2.16b,v2.16b
+	st1	{v5.16b},[x1],#16
+	orr	v1.16b,v3.16b,v3.16b
+	st1	{v18.16b},[x1],#16
+	orr	v18.16b,v19.16b,v19.16b
+	b.hs	Loop3x_cbc_dec
+
+	cmn	x2,#0x30
+	b.eq	Lcbc_done
+	nop
+
+Lcbc_dec_tail:
+	aesd	v1.16b,v16.16b
+	aesimc	v1.16b,v1.16b
+	aesd	v18.16b,v16.16b
+	aesimc	v18.16b,v18.16b
+	ld1	{v16.4s},[x7],#16
+	subs	w6,w6,#2
+	aesd	v1.16b,v17.16b
+	aesimc	v1.16b,v1.16b
+	aesd	v18.16b,v17.16b
+	aesimc	v18.16b,v18.16b
+	ld1	{v17.4s},[x7],#16
+	b.gt	Lcbc_dec_tail
+
+	aesd	v1.16b,v16.16b
+	aesimc	v1.16b,v1.16b
+	aesd	v18.16b,v16.16b
+	aesimc	v18.16b,v18.16b
+	aesd	v1.16b,v17.16b
+	aesimc	v1.16b,v1.16b
+	aesd	v18.16b,v17.16b
+	aesimc	v18.16b,v18.16b
+	aesd	v1.16b,v20.16b
+	aesimc	v1.16b,v1.16b
+	aesd	v18.16b,v20.16b
+	aesimc	v18.16b,v18.16b
+	cmn	x2,#0x20
+	aesd	v1.16b,v21.16b
+	aesimc	v1.16b,v1.16b
+	aesd	v18.16b,v21.16b
+	aesimc	v18.16b,v18.16b
+	eor	v5.16b,v6.16b,v7.16b
+	aesd	v1.16b,v22.16b
+	aesimc	v1.16b,v1.16b
+	aesd	v18.16b,v22.16b
+	aesimc	v18.16b,v18.16b
+	eor	v17.16b,v3.16b,v7.16b
+	aesd	v1.16b,v23.16b
+	aesd	v18.16b,v23.16b
+	b.eq	Lcbc_dec_one
+	eor	v5.16b,v5.16b,v1.16b
+	eor	v17.16b,v17.16b,v18.16b
+	orr	v6.16b,v19.16b,v19.16b
+	st1	{v5.16b},[x1],#16
+	st1	{v17.16b},[x1],#16
+	b	Lcbc_done
+
+Lcbc_dec_one:
+	eor	v5.16b,v5.16b,v18.16b
+	orr	v6.16b,v19.16b,v19.16b
+	st1	{v5.16b},[x1],#16
+
+Lcbc_done:
+	st1	{v6.16b},[x4]
+Lcbc_abort:
+	ldr	x29,[sp],#16
+	ret
+
+.globl	_aes_hw_ctr32_encrypt_blocks
+.private_extern	_aes_hw_ctr32_encrypt_blocks
+
+.align	5
+_aes_hw_ctr32_encrypt_blocks:
+	stp	x29,x30,[sp,#-16]!
+	add	x29,sp,#0
+	ldr	w5,[x3,#240]
+
+	ldr	w8, [x4, #12]
+	ld1	{v0.4s},[x4]
+
+	ld1	{v16.4s,v17.4s},[x3]		// load key schedule...
+	sub	w5,w5,#4
+	mov	x12,#16
+	cmp	x2,#2
+	add	x7,x3,x5,lsl#4	// pointer to last 5 round keys
+	sub	w5,w5,#2
+	ld1	{v20.4s,v21.4s},[x7],#32
+	ld1	{v22.4s,v23.4s},[x7],#32
+	ld1	{v7.4s},[x7]
+	add	x7,x3,#32
+	mov	w6,w5
+	csel	x12,xzr,x12,lo
+#ifndef __ARMEB__
+	rev	w8, w8
+#endif
+	orr	v1.16b,v0.16b,v0.16b
+	add	w10, w8, #1
+	orr	v18.16b,v0.16b,v0.16b
+	add	w8, w8, #2
+	orr	v6.16b,v0.16b,v0.16b
+	rev	w10, w10
+	mov	v1.s[3],w10
+	b.ls	Lctr32_tail
+	rev	w12, w8
+	sub	x2,x2,#3		// bias
+	mov	v18.s[3],w12
+	b	Loop3x_ctr32
+
+.align	4
+Loop3x_ctr32:
+	aese	v0.16b,v16.16b
+	aesmc	v0.16b,v0.16b
+	aese	v1.16b,v16.16b
+	aesmc	v1.16b,v1.16b
+	aese	v18.16b,v16.16b
+	aesmc	v18.16b,v18.16b
+	ld1	{v16.4s},[x7],#16
+	subs	w6,w6,#2
+	aese	v0.16b,v17.16b
+	aesmc	v0.16b,v0.16b
+	aese	v1.16b,v17.16b
+	aesmc	v1.16b,v1.16b
+	aese	v18.16b,v17.16b
+	aesmc	v18.16b,v18.16b
+	ld1	{v17.4s},[x7],#16
+	b.gt	Loop3x_ctr32
+
+	aese	v0.16b,v16.16b
+	aesmc	v4.16b,v0.16b
+	aese	v1.16b,v16.16b
+	aesmc	v5.16b,v1.16b
+	ld1	{v2.16b},[x0],#16
+	orr	v0.16b,v6.16b,v6.16b
+	aese	v18.16b,v16.16b
+	aesmc	v18.16b,v18.16b
+	ld1	{v3.16b},[x0],#16
+	orr	v1.16b,v6.16b,v6.16b
+	aese	v4.16b,v17.16b
+	aesmc	v4.16b,v4.16b
+	aese	v5.16b,v17.16b
+	aesmc	v5.16b,v5.16b
+	ld1	{v19.16b},[x0],#16
+	mov	x7,x3
+	aese	v18.16b,v17.16b
+	aesmc	v17.16b,v18.16b
+	orr	v18.16b,v6.16b,v6.16b
+	add	w9,w8,#1
+	aese	v4.16b,v20.16b
+	aesmc	v4.16b,v4.16b
+	aese	v5.16b,v20.16b
+	aesmc	v5.16b,v5.16b
+	eor	v2.16b,v2.16b,v7.16b
+	add	w10,w8,#2
+	aese	v17.16b,v20.16b
+	aesmc	v17.16b,v17.16b
+	eor	v3.16b,v3.16b,v7.16b
+	add	w8,w8,#3
+	aese	v4.16b,v21.16b
+	aesmc	v4.16b,v4.16b
+	aese	v5.16b,v21.16b
+	aesmc	v5.16b,v5.16b
+	eor	v19.16b,v19.16b,v7.16b
+	rev	w9,w9
+	aese	v17.16b,v21.16b
+	aesmc	v17.16b,v17.16b
+	mov	v0.s[3], w9
+	rev	w10,w10
+	aese	v4.16b,v22.16b
+	aesmc	v4.16b,v4.16b
+	aese	v5.16b,v22.16b
+	aesmc	v5.16b,v5.16b
+	mov	v1.s[3], w10
+	rev	w12,w8
+	aese	v17.16b,v22.16b
+	aesmc	v17.16b,v17.16b
+	mov	v18.s[3], w12
+	subs	x2,x2,#3
+	aese	v4.16b,v23.16b
+	aese	v5.16b,v23.16b
+	aese	v17.16b,v23.16b
+
+	eor	v2.16b,v2.16b,v4.16b
+	ld1	{v16.4s},[x7],#16	// re-pre-load rndkey[0]
+	st1	{v2.16b},[x1],#16
+	eor	v3.16b,v3.16b,v5.16b
+	mov	w6,w5
+	st1	{v3.16b},[x1],#16
+	eor	v19.16b,v19.16b,v17.16b
+	ld1	{v17.4s},[x7],#16	// re-pre-load rndkey[1]
+	st1	{v19.16b},[x1],#16
+	b.hs	Loop3x_ctr32
+
+	adds	x2,x2,#3
+	b.eq	Lctr32_done
+	cmp	x2,#1
+	mov	x12,#16
+	csel	x12,xzr,x12,eq
+
+Lctr32_tail:
+	aese	v0.16b,v16.16b
+	aesmc	v0.16b,v0.16b
+	aese	v1.16b,v16.16b
+	aesmc	v1.16b,v1.16b
+	ld1	{v16.4s},[x7],#16
+	subs	w6,w6,#2
+	aese	v0.16b,v17.16b
+	aesmc	v0.16b,v0.16b
+	aese	v1.16b,v17.16b
+	aesmc	v1.16b,v1.16b
+	ld1	{v17.4s},[x7],#16
+	b.gt	Lctr32_tail
+
+	aese	v0.16b,v16.16b
+	aesmc	v0.16b,v0.16b
+	aese	v1.16b,v16.16b
+	aesmc	v1.16b,v1.16b
+	aese	v0.16b,v17.16b
+	aesmc	v0.16b,v0.16b
+	aese	v1.16b,v17.16b
+	aesmc	v1.16b,v1.16b
+	ld1	{v2.16b},[x0],x12
+	aese	v0.16b,v20.16b
+	aesmc	v0.16b,v0.16b
+	aese	v1.16b,v20.16b
+	aesmc	v1.16b,v1.16b
+	ld1	{v3.16b},[x0]
+	aese	v0.16b,v21.16b
+	aesmc	v0.16b,v0.16b
+	aese	v1.16b,v21.16b
+	aesmc	v1.16b,v1.16b
+	eor	v2.16b,v2.16b,v7.16b
+	aese	v0.16b,v22.16b
+	aesmc	v0.16b,v0.16b
+	aese	v1.16b,v22.16b
+	aesmc	v1.16b,v1.16b
+	eor	v3.16b,v3.16b,v7.16b
+	aese	v0.16b,v23.16b
+	aese	v1.16b,v23.16b
+
+	cmp	x2,#1
+	eor	v2.16b,v2.16b,v0.16b
+	eor	v3.16b,v3.16b,v1.16b
+	st1	{v2.16b},[x1],#16
+	b.eq	Lctr32_done
+	st1	{v3.16b},[x1]
+
+Lctr32_done:
+	ldr	x29,[sp],#16
+	ret
+
+#endif
diff --git a/third_party/boringssl/ios-aarch64/crypto/fipsmodule/armv8-mont.S b/third_party/boringssl/ios-aarch64/crypto/fipsmodule/armv8-mont.S
new file mode 100644
index 0000000..5626574
--- /dev/null
+++ b/third_party/boringssl/ios-aarch64/crypto/fipsmodule/armv8-mont.S
@@ -0,0 +1,1405 @@
+.text
+
+.globl	_bn_mul_mont
+.private_extern	_bn_mul_mont
+
+.align	5
+_bn_mul_mont:
+	tst	x5,#7
+	b.eq	__bn_sqr8x_mont
+	tst	x5,#3
+	b.eq	__bn_mul4x_mont
+Lmul_mont:
+	stp	x29,x30,[sp,#-64]!
+	add	x29,sp,#0
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+
+	ldr	x9,[x2],#8		// bp[0]
+	sub	x22,sp,x5,lsl#3
+	ldp	x7,x8,[x1],#16	// ap[0..1]
+	lsl	x5,x5,#3
+	ldr	x4,[x4]		// *n0
+	and	x22,x22,#-16		// ABI says so
+	ldp	x13,x14,[x3],#16	// np[0..1]
+
+	mul	x6,x7,x9		// ap[0]*bp[0]
+	sub	x21,x5,#16		// j=num-2
+	umulh	x7,x7,x9
+	mul	x10,x8,x9		// ap[1]*bp[0]
+	umulh	x11,x8,x9
+
+	mul	x15,x6,x4		// "tp[0]"*n0
+	mov	sp,x22			// alloca
+
+	// (*)	mul	x12,x13,x15	// np[0]*m1
+	umulh	x13,x13,x15
+	mul	x16,x14,x15		// np[1]*m1
+	// (*)	adds	x12,x12,x6	// discarded
+	// (*)	As for removal of first multiplication and addition
+	//	instructions. The outcome of first addition is
+	//	guaranteed to be zero, which leaves two computationally
+	//	significant outcomes: it either carries or not. Then
+	//	question is when does it carry? Is there alternative
+	//	way to deduce it? If you follow operations, you can
+	//	observe that condition for carry is quite simple:
+	//	x6 being non-zero. So that carry can be calculated
+	//	by adding -1 to x6. That's what next instruction does.
+	subs	xzr,x6,#1		// (*)
+	umulh	x17,x14,x15
+	adc	x13,x13,xzr
+	cbz	x21,L1st_skip
+
+L1st:
+	ldr	x8,[x1],#8
+	adds	x6,x10,x7
+	sub	x21,x21,#8		// j--
+	adc	x7,x11,xzr
+
+	ldr	x14,[x3],#8
+	adds	x12,x16,x13
+	mul	x10,x8,x9		// ap[j]*bp[0]
+	adc	x13,x17,xzr
+	umulh	x11,x8,x9
+
+	adds	x12,x12,x6
+	mul	x16,x14,x15		// np[j]*m1
+	adc	x13,x13,xzr
+	umulh	x17,x14,x15
+	str	x12,[x22],#8		// tp[j-1]
+	cbnz	x21,L1st
+
+L1st_skip:
+	adds	x6,x10,x7
+	sub	x1,x1,x5		// rewind x1
+	adc	x7,x11,xzr
+
+	adds	x12,x16,x13
+	sub	x3,x3,x5		// rewind x3
+	adc	x13,x17,xzr
+
+	adds	x12,x12,x6
+	sub	x20,x5,#8		// i=num-1
+	adcs	x13,x13,x7
+
+	adc	x19,xzr,xzr		// upmost overflow bit
+	stp	x12,x13,[x22]
+
+Louter:
+	ldr	x9,[x2],#8		// bp[i]
+	ldp	x7,x8,[x1],#16
+	ldr	x23,[sp]		// tp[0]
+	add	x22,sp,#8
+
+	mul	x6,x7,x9		// ap[0]*bp[i]
+	sub	x21,x5,#16		// j=num-2
+	umulh	x7,x7,x9
+	ldp	x13,x14,[x3],#16
+	mul	x10,x8,x9		// ap[1]*bp[i]
+	adds	x6,x6,x23
+	umulh	x11,x8,x9
+	adc	x7,x7,xzr
+
+	mul	x15,x6,x4
+	sub	x20,x20,#8		// i--
+
+	// (*)	mul	x12,x13,x15	// np[0]*m1
+	umulh	x13,x13,x15
+	mul	x16,x14,x15		// np[1]*m1
+	// (*)	adds	x12,x12,x6
+	subs	xzr,x6,#1		// (*)
+	umulh	x17,x14,x15
+	cbz	x21,Linner_skip
+
+Linner:
+	ldr	x8,[x1],#8
+	adc	x13,x13,xzr
+	ldr	x23,[x22],#8		// tp[j]
+	adds	x6,x10,x7
+	sub	x21,x21,#8		// j--
+	adc	x7,x11,xzr
+
+	adds	x12,x16,x13
+	ldr	x14,[x3],#8
+	adc	x13,x17,xzr
+
+	mul	x10,x8,x9		// ap[j]*bp[i]
+	adds	x6,x6,x23
+	umulh	x11,x8,x9
+	adc	x7,x7,xzr
+
+	mul	x16,x14,x15		// np[j]*m1
+	adds	x12,x12,x6
+	umulh	x17,x14,x15
+	str	x12,[x22,#-16]		// tp[j-1]
+	cbnz	x21,Linner
+
+Linner_skip:
+	ldr	x23,[x22],#8		// tp[j]
+	adc	x13,x13,xzr
+	adds	x6,x10,x7
+	sub	x1,x1,x5		// rewind x1
+	adc	x7,x11,xzr
+
+	adds	x12,x16,x13
+	sub	x3,x3,x5		// rewind x3
+	adcs	x13,x17,x19
+	adc	x19,xzr,xzr
+
+	adds	x6,x6,x23
+	adc	x7,x7,xzr
+
+	adds	x12,x12,x6
+	adcs	x13,x13,x7
+	adc	x19,x19,xzr		// upmost overflow bit
+	stp	x12,x13,[x22,#-16]
+
+	cbnz	x20,Louter
+
+	// Final step. We see if result is larger than modulus, and
+	// if it is, subtract the modulus. But comparison implies
+	// subtraction. So we subtract modulus, see if it borrowed,
+	// and conditionally copy original value.
+	ldr	x23,[sp]		// tp[0]
+	add	x22,sp,#8
+	ldr	x14,[x3],#8		// np[0]
+	subs	x21,x5,#8		// j=num-1 and clear borrow
+	mov	x1,x0
+Lsub:
+	sbcs	x8,x23,x14		// tp[j]-np[j]
+	ldr	x23,[x22],#8
+	sub	x21,x21,#8		// j--
+	ldr	x14,[x3],#8
+	str	x8,[x1],#8		// rp[j]=tp[j]-np[j]
+	cbnz	x21,Lsub
+
+	sbcs	x8,x23,x14
+	sbcs	x19,x19,xzr		// did it borrow?
+	str	x8,[x1],#8		// rp[num-1]
+
+	ldr	x23,[sp]		// tp[0]
+	add	x22,sp,#8
+	ldr	x8,[x0],#8		// rp[0]
+	sub	x5,x5,#8		// num--
+	nop
+Lcond_copy:
+	sub	x5,x5,#8		// num--
+	csel	x14,x23,x8,lo		// did it borrow?
+	ldr	x23,[x22],#8
+	ldr	x8,[x0],#8
+	str	xzr,[x22,#-16]		// wipe tp
+	str	x14,[x0,#-16]
+	cbnz	x5,Lcond_copy
+
+	csel	x14,x23,x8,lo
+	str	xzr,[x22,#-8]		// wipe tp
+	str	x14,[x0,#-8]
+
+	ldp	x19,x20,[x29,#16]
+	mov	sp,x29
+	ldp	x21,x22,[x29,#32]
+	mov	x0,#1
+	ldp	x23,x24,[x29,#48]
+	ldr	x29,[sp],#64
+	ret
+
+
+.align	5
+__bn_sqr8x_mont:
+	cmp	x1,x2
+	b.ne	__bn_mul4x_mont
+Lsqr8x_mont:
+	stp	x29,x30,[sp,#-128]!
+	add	x29,sp,#0
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+	stp	x0,x3,[sp,#96]	// offload rp and np
+
+	ldp	x6,x7,[x1,#8*0]
+	ldp	x8,x9,[x1,#8*2]
+	ldp	x10,x11,[x1,#8*4]
+	ldp	x12,x13,[x1,#8*6]
+
+	sub	x2,sp,x5,lsl#4
+	lsl	x5,x5,#3
+	ldr	x4,[x4]		// *n0
+	mov	sp,x2			// alloca
+	sub	x27,x5,#8*8
+	b	Lsqr8x_zero_start
+
+Lsqr8x_zero:
+	sub	x27,x27,#8*8
+	stp	xzr,xzr,[x2,#8*0]
+	stp	xzr,xzr,[x2,#8*2]
+	stp	xzr,xzr,[x2,#8*4]
+	stp	xzr,xzr,[x2,#8*6]
+Lsqr8x_zero_start:
+	stp	xzr,xzr,[x2,#8*8]
+	stp	xzr,xzr,[x2,#8*10]
+	stp	xzr,xzr,[x2,#8*12]
+	stp	xzr,xzr,[x2,#8*14]
+	add	x2,x2,#8*16
+	cbnz	x27,Lsqr8x_zero
+
+	add	x3,x1,x5
+	add	x1,x1,#8*8
+	mov	x19,xzr
+	mov	x20,xzr
+	mov	x21,xzr
+	mov	x22,xzr
+	mov	x23,xzr
+	mov	x24,xzr
+	mov	x25,xzr
+	mov	x26,xzr
+	mov	x2,sp
+	str	x4,[x29,#112]		// offload n0
+
+	// Multiply everything but a[i]*a[i]
+.align	4
+Lsqr8x_outer_loop:
+        //                                                 a[1]a[0]	(i)
+        //                                             a[2]a[0]
+        //                                         a[3]a[0]
+        //                                     a[4]a[0]
+        //                                 a[5]a[0]
+        //                             a[6]a[0]
+        //                         a[7]a[0]
+        //                                         a[2]a[1]		(ii)
+        //                                     a[3]a[1]
+        //                                 a[4]a[1]
+        //                             a[5]a[1]
+        //                         a[6]a[1]
+        //                     a[7]a[1]
+        //                                 a[3]a[2]			(iii)
+        //                             a[4]a[2]
+        //                         a[5]a[2]
+        //                     a[6]a[2]
+        //                 a[7]a[2]
+        //                         a[4]a[3]				(iv)
+        //                     a[5]a[3]
+        //                 a[6]a[3]
+        //             a[7]a[3]
+        //                 a[5]a[4]					(v)
+        //             a[6]a[4]
+        //         a[7]a[4]
+        //         a[6]a[5]						(vi)
+        //     a[7]a[5]
+        // a[7]a[6]							(vii)
+
+	mul	x14,x7,x6		// lo(a[1..7]*a[0])		(i)
+	mul	x15,x8,x6
+	mul	x16,x9,x6
+	mul	x17,x10,x6
+	adds	x20,x20,x14		// t[1]+lo(a[1]*a[0])
+	mul	x14,x11,x6
+	adcs	x21,x21,x15
+	mul	x15,x12,x6
+	adcs	x22,x22,x16
+	mul	x16,x13,x6
+	adcs	x23,x23,x17
+	umulh	x17,x7,x6		// hi(a[1..7]*a[0])
+	adcs	x24,x24,x14
+	umulh	x14,x8,x6
+	adcs	x25,x25,x15
+	umulh	x15,x9,x6
+	adcs	x26,x26,x16
+	umulh	x16,x10,x6
+	stp	x19,x20,[x2],#8*2	// t[0..1]
+	adc	x19,xzr,xzr		// t[8]
+	adds	x21,x21,x17		// t[2]+lo(a[1]*a[0])
+	umulh	x17,x11,x6
+	adcs	x22,x22,x14
+	umulh	x14,x12,x6
+	adcs	x23,x23,x15
+	umulh	x15,x13,x6
+	adcs	x24,x24,x16
+	mul	x16,x8,x7		// lo(a[2..7]*a[1])		(ii)
+	adcs	x25,x25,x17
+	mul	x17,x9,x7
+	adcs	x26,x26,x14
+	mul	x14,x10,x7
+	adc	x19,x19,x15
+
+	mul	x15,x11,x7
+	adds	x22,x22,x16
+	mul	x16,x12,x7
+	adcs	x23,x23,x17
+	mul	x17,x13,x7
+	adcs	x24,x24,x14
+	umulh	x14,x8,x7		// hi(a[2..7]*a[1])
+	adcs	x25,x25,x15
+	umulh	x15,x9,x7
+	adcs	x26,x26,x16
+	umulh	x16,x10,x7
+	adcs	x19,x19,x17
+	umulh	x17,x11,x7
+	stp	x21,x22,[x2],#8*2	// t[2..3]
+	adc	x20,xzr,xzr		// t[9]
+	adds	x23,x23,x14
+	umulh	x14,x12,x7
+	adcs	x24,x24,x15
+	umulh	x15,x13,x7
+	adcs	x25,x25,x16
+	mul	x16,x9,x8		// lo(a[3..7]*a[2])		(iii)
+	adcs	x26,x26,x17
+	mul	x17,x10,x8
+	adcs	x19,x19,x14
+	mul	x14,x11,x8
+	adc	x20,x20,x15
+
+	mul	x15,x12,x8
+	adds	x24,x24,x16
+	mul	x16,x13,x8
+	adcs	x25,x25,x17
+	umulh	x17,x9,x8		// hi(a[3..7]*a[2])
+	adcs	x26,x26,x14
+	umulh	x14,x10,x8
+	adcs	x19,x19,x15
+	umulh	x15,x11,x8
+	adcs	x20,x20,x16
+	umulh	x16,x12,x8
+	stp	x23,x24,[x2],#8*2	// t[4..5]
+	adc	x21,xzr,xzr		// t[10]
+	adds	x25,x25,x17
+	umulh	x17,x13,x8
+	adcs	x26,x26,x14
+	mul	x14,x10,x9		// lo(a[4..7]*a[3])		(iv)
+	adcs	x19,x19,x15
+	mul	x15,x11,x9
+	adcs	x20,x20,x16
+	mul	x16,x12,x9
+	adc	x21,x21,x17
+
+	mul	x17,x13,x9
+	adds	x26,x26,x14
+	umulh	x14,x10,x9		// hi(a[4..7]*a[3])
+	adcs	x19,x19,x15
+	umulh	x15,x11,x9
+	adcs	x20,x20,x16
+	umulh	x16,x12,x9
+	adcs	x21,x21,x17
+	umulh	x17,x13,x9
+	stp	x25,x26,[x2],#8*2	// t[6..7]
+	adc	x22,xzr,xzr		// t[11]
+	adds	x19,x19,x14
+	mul	x14,x11,x10		// lo(a[5..7]*a[4])		(v)
+	adcs	x20,x20,x15
+	mul	x15,x12,x10
+	adcs	x21,x21,x16
+	mul	x16,x13,x10
+	adc	x22,x22,x17
+
+	umulh	x17,x11,x10		// hi(a[5..7]*a[4])
+	adds	x20,x20,x14
+	umulh	x14,x12,x10
+	adcs	x21,x21,x15
+	umulh	x15,x13,x10
+	adcs	x22,x22,x16
+	mul	x16,x12,x11		// lo(a[6..7]*a[5])		(vi)
+	adc	x23,xzr,xzr		// t[12]
+	adds	x21,x21,x17
+	mul	x17,x13,x11
+	adcs	x22,x22,x14
+	umulh	x14,x12,x11		// hi(a[6..7]*a[5])
+	adc	x23,x23,x15
+
+	umulh	x15,x13,x11
+	adds	x22,x22,x16
+	mul	x16,x13,x12		// lo(a[7]*a[6])		(vii)
+	adcs	x23,x23,x17
+	umulh	x17,x13,x12		// hi(a[7]*a[6])
+	adc	x24,xzr,xzr		// t[13]
+	adds	x23,x23,x14
+	sub	x27,x3,x1	// done yet?
+	adc	x24,x24,x15
+
+	adds	x24,x24,x16
+	sub	x14,x3,x5	// rewinded ap
+	adc	x25,xzr,xzr		// t[14]
+	add	x25,x25,x17
+
+	cbz	x27,Lsqr8x_outer_break
+
+	mov	x4,x6
+	ldp	x6,x7,[x2,#8*0]
+	ldp	x8,x9,[x2,#8*2]
+	ldp	x10,x11,[x2,#8*4]
+	ldp	x12,x13,[x2,#8*6]
+	adds	x19,x19,x6
+	adcs	x20,x20,x7
+	ldp	x6,x7,[x1,#8*0]
+	adcs	x21,x21,x8
+	adcs	x22,x22,x9
+	ldp	x8,x9,[x1,#8*2]
+	adcs	x23,x23,x10
+	adcs	x24,x24,x11
+	ldp	x10,x11,[x1,#8*4]
+	adcs	x25,x25,x12
+	mov	x0,x1
+	adcs	x26,xzr,x13
+	ldp	x12,x13,[x1,#8*6]
+	add	x1,x1,#8*8
+	//adc	x28,xzr,xzr		// moved below
+	mov	x27,#-8*8
+
+	//                                                         a[8]a[0]
+	//                                                     a[9]a[0]
+	//                                                 a[a]a[0]
+	//                                             a[b]a[0]
+	//                                         a[c]a[0]
+	//                                     a[d]a[0]
+	//                                 a[e]a[0]
+	//                             a[f]a[0]
+	//                                                     a[8]a[1]
+	//                         a[f]a[1]........................
+	//                                                 a[8]a[2]
+	//                     a[f]a[2]........................
+	//                                             a[8]a[3]
+	//                 a[f]a[3]........................
+	//                                         a[8]a[4]
+	//             a[f]a[4]........................
+	//                                     a[8]a[5]
+	//         a[f]a[5]........................
+	//                                 a[8]a[6]
+	//     a[f]a[6]........................
+	//                             a[8]a[7]
+	// a[f]a[7]........................
+Lsqr8x_mul:
+	mul	x14,x6,x4
+	adc	x28,xzr,xzr		// carry bit, modulo-scheduled
+	mul	x15,x7,x4
+	add	x27,x27,#8
+	mul	x16,x8,x4
+	mul	x17,x9,x4
+	adds	x19,x19,x14
+	mul	x14,x10,x4
+	adcs	x20,x20,x15
+	mul	x15,x11,x4
+	adcs	x21,x21,x16
+	mul	x16,x12,x4
+	adcs	x22,x22,x17
+	mul	x17,x13,x4
+	adcs	x23,x23,x14
+	umulh	x14,x6,x4
+	adcs	x24,x24,x15
+	umulh	x15,x7,x4
+	adcs	x25,x25,x16
+	umulh	x16,x8,x4
+	adcs	x26,x26,x17
+	umulh	x17,x9,x4
+	adc	x28,x28,xzr
+	str	x19,[x2],#8
+	adds	x19,x20,x14
+	umulh	x14,x10,x4
+	adcs	x20,x21,x15
+	umulh	x15,x11,x4
+	adcs	x21,x22,x16
+	umulh	x16,x12,x4
+	adcs	x22,x23,x17
+	umulh	x17,x13,x4
+	ldr	x4,[x0,x27]
+	adcs	x23,x24,x14
+	adcs	x24,x25,x15
+	adcs	x25,x26,x16
+	adcs	x26,x28,x17
+	//adc	x28,xzr,xzr		// moved above
+	cbnz	x27,Lsqr8x_mul
+					// note that carry flag is guaranteed
+					// to be zero at this point
+	cmp	x1,x3		// done yet?
+	b.eq	Lsqr8x_break
+
+	ldp	x6,x7,[x2,#8*0]
+	ldp	x8,x9,[x2,#8*2]
+	ldp	x10,x11,[x2,#8*4]
+	ldp	x12,x13,[x2,#8*6]
+	adds	x19,x19,x6
+	ldr	x4,[x0,#-8*8]
+	adcs	x20,x20,x7
+	ldp	x6,x7,[x1,#8*0]
+	adcs	x21,x21,x8
+	adcs	x22,x22,x9
+	ldp	x8,x9,[x1,#8*2]
+	adcs	x23,x23,x10
+	adcs	x24,x24,x11
+	ldp	x10,x11,[x1,#8*4]
+	adcs	x25,x25,x12
+	mov	x27,#-8*8
+	adcs	x26,x26,x13
+	ldp	x12,x13,[x1,#8*6]
+	add	x1,x1,#8*8
+	//adc	x28,xzr,xzr		// moved above
+	b	Lsqr8x_mul
+
+.align	4
+Lsqr8x_break:
+	ldp	x6,x7,[x0,#8*0]
+	add	x1,x0,#8*8
+	ldp	x8,x9,[x0,#8*2]
+	sub	x14,x3,x1		// is it last iteration?
+	ldp	x10,x11,[x0,#8*4]
+	sub	x15,x2,x14
+	ldp	x12,x13,[x0,#8*6]
+	cbz	x14,Lsqr8x_outer_loop
+
+	stp	x19,x20,[x2,#8*0]
+	ldp	x19,x20,[x15,#8*0]
+	stp	x21,x22,[x2,#8*2]
+	ldp	x21,x22,[x15,#8*2]
+	stp	x23,x24,[x2,#8*4]
+	ldp	x23,x24,[x15,#8*4]
+	stp	x25,x26,[x2,#8*6]
+	mov	x2,x15
+	ldp	x25,x26,[x15,#8*6]
+	b	Lsqr8x_outer_loop
+
+.align	4
+Lsqr8x_outer_break:
+	// Now multiply above result by 2 and add a[n-1]*a[n-1]|...|a[0]*a[0]
+	ldp	x7,x9,[x14,#8*0]	// recall that x14 is &a[0]
+	ldp	x15,x16,[sp,#8*1]
+	ldp	x11,x13,[x14,#8*2]
+	add	x1,x14,#8*4
+	ldp	x17,x14,[sp,#8*3]
+
+	stp	x19,x20,[x2,#8*0]
+	mul	x19,x7,x7
+	stp	x21,x22,[x2,#8*2]
+	umulh	x7,x7,x7
+	stp	x23,x24,[x2,#8*4]
+	mul	x8,x9,x9
+	stp	x25,x26,[x2,#8*6]
+	mov	x2,sp
+	umulh	x9,x9,x9
+	adds	x20,x7,x15,lsl#1
+	extr	x15,x16,x15,#63
+	sub	x27,x5,#8*4
+
+Lsqr4x_shift_n_add:
+	adcs	x21,x8,x15
+	extr	x16,x17,x16,#63
+	sub	x27,x27,#8*4
+	adcs	x22,x9,x16
+	ldp	x15,x16,[x2,#8*5]
+	mul	x10,x11,x11
+	ldp	x7,x9,[x1],#8*2
+	umulh	x11,x11,x11
+	mul	x12,x13,x13
+	umulh	x13,x13,x13
+	extr	x17,x14,x17,#63
+	stp	x19,x20,[x2,#8*0]
+	adcs	x23,x10,x17
+	extr	x14,x15,x14,#63
+	stp	x21,x22,[x2,#8*2]
+	adcs	x24,x11,x14
+	ldp	x17,x14,[x2,#8*7]
+	extr	x15,x16,x15,#63
+	adcs	x25,x12,x15
+	extr	x16,x17,x16,#63
+	adcs	x26,x13,x16
+	ldp	x15,x16,[x2,#8*9]
+	mul	x6,x7,x7
+	ldp	x11,x13,[x1],#8*2
+	umulh	x7,x7,x7
+	mul	x8,x9,x9
+	umulh	x9,x9,x9
+	stp	x23,x24,[x2,#8*4]
+	extr	x17,x14,x17,#63
+	stp	x25,x26,[x2,#8*6]
+	add	x2,x2,#8*8
+	adcs	x19,x6,x17
+	extr	x14,x15,x14,#63
+	adcs	x20,x7,x14
+	ldp	x17,x14,[x2,#8*3]
+	extr	x15,x16,x15,#63
+	cbnz	x27,Lsqr4x_shift_n_add
+	ldp	x1,x4,[x29,#104]	// pull np and n0
+
+	adcs	x21,x8,x15
+	extr	x16,x17,x16,#63
+	adcs	x22,x9,x16
+	ldp	x15,x16,[x2,#8*5]
+	mul	x10,x11,x11
+	umulh	x11,x11,x11
+	stp	x19,x20,[x2,#8*0]
+	mul	x12,x13,x13
+	umulh	x13,x13,x13
+	stp	x21,x22,[x2,#8*2]
+	extr	x17,x14,x17,#63
+	adcs	x23,x10,x17
+	extr	x14,x15,x14,#63
+	ldp	x19,x20,[sp,#8*0]
+	adcs	x24,x11,x14
+	extr	x15,x16,x15,#63
+	ldp	x6,x7,[x1,#8*0]
+	adcs	x25,x12,x15
+	extr	x16,xzr,x16,#63
+	ldp	x8,x9,[x1,#8*2]
+	adc	x26,x13,x16
+	ldp	x10,x11,[x1,#8*4]
+
+	// Reduce by 512 bits per iteration
+	mul	x28,x4,x19		// t[0]*n0
+	ldp	x12,x13,[x1,#8*6]
+	add	x3,x1,x5
+	ldp	x21,x22,[sp,#8*2]
+	stp	x23,x24,[x2,#8*4]
+	ldp	x23,x24,[sp,#8*4]
+	stp	x25,x26,[x2,#8*6]
+	ldp	x25,x26,[sp,#8*6]
+	add	x1,x1,#8*8
+	mov	x30,xzr		// initial top-most carry
+	mov	x2,sp
+	mov	x27,#8
+
+Lsqr8x_reduction:
+	// (*)	mul	x14,x6,x28	// lo(n[0-7])*lo(t[0]*n0)
+	mul	x15,x7,x28
+	sub	x27,x27,#1
+	mul	x16,x8,x28
+	str	x28,[x2],#8		// put aside t[0]*n0 for tail processing
+	mul	x17,x9,x28
+	// (*)	adds	xzr,x19,x14
+	subs	xzr,x19,#1		// (*)
+	mul	x14,x10,x28
+	adcs	x19,x20,x15
+	mul	x15,x11,x28
+	adcs	x20,x21,x16
+	mul	x16,x12,x28
+	adcs	x21,x22,x17
+	mul	x17,x13,x28
+	adcs	x22,x23,x14
+	umulh	x14,x6,x28		// hi(n[0-7])*lo(t[0]*n0)
+	adcs	x23,x24,x15
+	umulh	x15,x7,x28
+	adcs	x24,x25,x16
+	umulh	x16,x8,x28
+	adcs	x25,x26,x17
+	umulh	x17,x9,x28
+	adc	x26,xzr,xzr
+	adds	x19,x19,x14
+	umulh	x14,x10,x28
+	adcs	x20,x20,x15
+	umulh	x15,x11,x28
+	adcs	x21,x21,x16
+	umulh	x16,x12,x28
+	adcs	x22,x22,x17
+	umulh	x17,x13,x28
+	mul	x28,x4,x19		// next t[0]*n0
+	adcs	x23,x23,x14
+	adcs	x24,x24,x15
+	adcs	x25,x25,x16
+	adc	x26,x26,x17
+	cbnz	x27,Lsqr8x_reduction
+
+	ldp	x14,x15,[x2,#8*0]
+	ldp	x16,x17,[x2,#8*2]
+	mov	x0,x2
+	sub	x27,x3,x1	// done yet?
+	adds	x19,x19,x14
+	adcs	x20,x20,x15
+	ldp	x14,x15,[x2,#8*4]
+	adcs	x21,x21,x16
+	adcs	x22,x22,x17
+	ldp	x16,x17,[x2,#8*6]
+	adcs	x23,x23,x14
+	adcs	x24,x24,x15
+	adcs	x25,x25,x16
+	adcs	x26,x26,x17
+	//adc	x28,xzr,xzr		// moved below
+	cbz	x27,Lsqr8x8_post_condition
+
+	ldr	x4,[x2,#-8*8]
+	ldp	x6,x7,[x1,#8*0]
+	ldp	x8,x9,[x1,#8*2]
+	ldp	x10,x11,[x1,#8*4]
+	mov	x27,#-8*8
+	ldp	x12,x13,[x1,#8*6]
+	add	x1,x1,#8*8
+
+Lsqr8x_tail:
+	mul	x14,x6,x4
+	adc	x28,xzr,xzr		// carry bit, modulo-scheduled
+	mul	x15,x7,x4
+	add	x27,x27,#8
+	mul	x16,x8,x4
+	mul	x17,x9,x4
+	adds	x19,x19,x14
+	mul	x14,x10,x4
+	adcs	x20,x20,x15
+	mul	x15,x11,x4
+	adcs	x21,x21,x16
+	mul	x16,x12,x4
+	adcs	x22,x22,x17
+	mul	x17,x13,x4
+	adcs	x23,x23,x14
+	umulh	x14,x6,x4
+	adcs	x24,x24,x15
+	umulh	x15,x7,x4
+	adcs	x25,x25,x16
+	umulh	x16,x8,x4
+	adcs	x26,x26,x17
+	umulh	x17,x9,x4
+	adc	x28,x28,xzr
+	str	x19,[x2],#8
+	adds	x19,x20,x14
+	umulh	x14,x10,x4
+	adcs	x20,x21,x15
+	umulh	x15,x11,x4
+	adcs	x21,x22,x16
+	umulh	x16,x12,x4
+	adcs	x22,x23,x17
+	umulh	x17,x13,x4
+	ldr	x4,[x0,x27]
+	adcs	x23,x24,x14
+	adcs	x24,x25,x15
+	adcs	x25,x26,x16
+	adcs	x26,x28,x17
+	//adc	x28,xzr,xzr		// moved above
+	cbnz	x27,Lsqr8x_tail
+					// note that carry flag is guaranteed
+					// to be zero at this point
+	ldp	x6,x7,[x2,#8*0]
+	sub	x27,x3,x1	// done yet?
+	sub	x16,x3,x5	// rewinded np
+	ldp	x8,x9,[x2,#8*2]
+	ldp	x10,x11,[x2,#8*4]
+	ldp	x12,x13,[x2,#8*6]
+	cbz	x27,Lsqr8x_tail_break
+
+	ldr	x4,[x0,#-8*8]
+	adds	x19,x19,x6
+	adcs	x20,x20,x7
+	ldp	x6,x7,[x1,#8*0]
+	adcs	x21,x21,x8
+	adcs	x22,x22,x9
+	ldp	x8,x9,[x1,#8*2]
+	adcs	x23,x23,x10
+	adcs	x24,x24,x11
+	ldp	x10,x11,[x1,#8*4]
+	adcs	x25,x25,x12
+	mov	x27,#-8*8
+	adcs	x26,x26,x13
+	ldp	x12,x13,[x1,#8*6]
+	add	x1,x1,#8*8
+	//adc	x28,xzr,xzr		// moved above
+	b	Lsqr8x_tail
+
+.align	4
+Lsqr8x_tail_break:
+	ldr	x4,[x29,#112]		// pull n0
+	add	x27,x2,#8*8		// end of current t[num] window
+
+	subs	xzr,x30,#1		// "move" top-most carry to carry bit
+	adcs	x14,x19,x6
+	adcs	x15,x20,x7
+	ldp	x19,x20,[x0,#8*0]
+	adcs	x21,x21,x8
+	ldp	x6,x7,[x16,#8*0]	// recall that x16 is &n[0]
+	adcs	x22,x22,x9
+	ldp	x8,x9,[x16,#8*2]
+	adcs	x23,x23,x10
+	adcs	x24,x24,x11
+	ldp	x10,x11,[x16,#8*4]
+	adcs	x25,x25,x12
+	adcs	x26,x26,x13
+	ldp	x12,x13,[x16,#8*6]
+	add	x1,x16,#8*8
+	adc	x30,xzr,xzr	// top-most carry
+	mul	x28,x4,x19
+	stp	x14,x15,[x2,#8*0]
+	stp	x21,x22,[x2,#8*2]
+	ldp	x21,x22,[x0,#8*2]
+	stp	x23,x24,[x2,#8*4]
+	ldp	x23,x24,[x0,#8*4]
+	cmp	x27,x29		// did we hit the bottom?
+	stp	x25,x26,[x2,#8*6]
+	mov	x2,x0			// slide the window
+	ldp	x25,x26,[x0,#8*6]
+	mov	x27,#8
+	b.ne	Lsqr8x_reduction
+
+	// Final step. We see if result is larger than modulus, and
+	// if it is, subtract the modulus. But comparison implies
+	// subtraction. So we subtract modulus, see if it borrowed,
+	// and conditionally copy original value.
+	ldr	x0,[x29,#96]		// pull rp
+	add	x2,x2,#8*8
+	subs	x14,x19,x6
+	sbcs	x15,x20,x7
+	sub	x27,x5,#8*8
+	mov	x3,x0		// x0 copy
+
+Lsqr8x_sub:
+	sbcs	x16,x21,x8
+	ldp	x6,x7,[x1,#8*0]
+	sbcs	x17,x22,x9
+	stp	x14,x15,[x0,#8*0]
+	sbcs	x14,x23,x10
+	ldp	x8,x9,[x1,#8*2]
+	sbcs	x15,x24,x11
+	stp	x16,x17,[x0,#8*2]
+	sbcs	x16,x25,x12
+	ldp	x10,x11,[x1,#8*4]
+	sbcs	x17,x26,x13
+	ldp	x12,x13,[x1,#8*6]
+	add	x1,x1,#8*8
+	ldp	x19,x20,[x2,#8*0]
+	sub	x27,x27,#8*8
+	ldp	x21,x22,[x2,#8*2]
+	ldp	x23,x24,[x2,#8*4]
+	ldp	x25,x26,[x2,#8*6]
+	add	x2,x2,#8*8
+	stp	x14,x15,[x0,#8*4]
+	sbcs	x14,x19,x6
+	stp	x16,x17,[x0,#8*6]
+	add	x0,x0,#8*8
+	sbcs	x15,x20,x7
+	cbnz	x27,Lsqr8x_sub
+
+	sbcs	x16,x21,x8
+	mov	x2,sp
+	add	x1,sp,x5
+	ldp	x6,x7,[x3,#8*0]
+	sbcs	x17,x22,x9
+	stp	x14,x15,[x0,#8*0]
+	sbcs	x14,x23,x10
+	ldp	x8,x9,[x3,#8*2]
+	sbcs	x15,x24,x11
+	stp	x16,x17,[x0,#8*2]
+	sbcs	x16,x25,x12
+	ldp	x19,x20,[x1,#8*0]
+	sbcs	x17,x26,x13
+	ldp	x21,x22,[x1,#8*2]
+	sbcs	xzr,x30,xzr	// did it borrow?
+	ldr	x30,[x29,#8]		// pull return address
+	stp	x14,x15,[x0,#8*4]
+	stp	x16,x17,[x0,#8*6]
+
+	sub	x27,x5,#8*4
+Lsqr4x_cond_copy:
+	sub	x27,x27,#8*4
+	csel	x14,x19,x6,lo
+	stp	xzr,xzr,[x2,#8*0]
+	csel	x15,x20,x7,lo
+	ldp	x6,x7,[x3,#8*4]
+	ldp	x19,x20,[x1,#8*4]
+	csel	x16,x21,x8,lo
+	stp	xzr,xzr,[x2,#8*2]
+	add	x2,x2,#8*4
+	csel	x17,x22,x9,lo
+	ldp	x8,x9,[x3,#8*6]
+	ldp	x21,x22,[x1,#8*6]
+	add	x1,x1,#8*4
+	stp	x14,x15,[x3,#8*0]
+	stp	x16,x17,[x3,#8*2]
+	add	x3,x3,#8*4
+	stp	xzr,xzr,[x1,#8*0]
+	stp	xzr,xzr,[x1,#8*2]
+	cbnz	x27,Lsqr4x_cond_copy
+
+	csel	x14,x19,x6,lo
+	stp	xzr,xzr,[x2,#8*0]
+	csel	x15,x20,x7,lo
+	stp	xzr,xzr,[x2,#8*2]
+	csel	x16,x21,x8,lo
+	csel	x17,x22,x9,lo
+	stp	x14,x15,[x3,#8*0]
+	stp	x16,x17,[x3,#8*2]
+
+	b	Lsqr8x_done
+
+.align	4
+Lsqr8x8_post_condition:
+	adc	x28,xzr,xzr
+	ldr	x30,[x29,#8]		// pull return address
+	// x19-7,x28 hold result, x6-7 hold modulus
+	subs	x6,x19,x6
+	ldr	x1,[x29,#96]		// pull rp
+	sbcs	x7,x20,x7
+	stp	xzr,xzr,[sp,#8*0]
+	sbcs	x8,x21,x8
+	stp	xzr,xzr,[sp,#8*2]
+	sbcs	x9,x22,x9
+	stp	xzr,xzr,[sp,#8*4]
+	sbcs	x10,x23,x10
+	stp	xzr,xzr,[sp,#8*6]
+	sbcs	x11,x24,x11
+	stp	xzr,xzr,[sp,#8*8]
+	sbcs	x12,x25,x12
+	stp	xzr,xzr,[sp,#8*10]
+	sbcs	x13,x26,x13
+	stp	xzr,xzr,[sp,#8*12]
+	sbcs	x28,x28,xzr	// did it borrow?
+	stp	xzr,xzr,[sp,#8*14]
+
+	// x6-7 hold result-modulus
+	csel	x6,x19,x6,lo
+	csel	x7,x20,x7,lo
+	csel	x8,x21,x8,lo
+	csel	x9,x22,x9,lo
+	stp	x6,x7,[x1,#8*0]
+	csel	x10,x23,x10,lo
+	csel	x11,x24,x11,lo
+	stp	x8,x9,[x1,#8*2]
+	csel	x12,x25,x12,lo
+	csel	x13,x26,x13,lo
+	stp	x10,x11,[x1,#8*4]
+	stp	x12,x13,[x1,#8*6]
+
+Lsqr8x_done:
+	ldp	x19,x20,[x29,#16]
+	mov	sp,x29
+	ldp	x21,x22,[x29,#32]
+	mov	x0,#1
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldr	x29,[sp],#128
+	ret
+
+
+.align	5
+__bn_mul4x_mont:
+	stp	x29,x30,[sp,#-128]!
+	add	x29,sp,#0
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+
+	sub	x26,sp,x5,lsl#3
+	lsl	x5,x5,#3
+	ldr	x4,[x4]		// *n0
+	sub	sp,x26,#8*4		// alloca
+
+	add	x10,x2,x5
+	add	x27,x1,x5
+	stp	x0,x10,[x29,#96]	// offload rp and &b[num]
+
+	ldr	x24,[x2,#8*0]		// b[0]
+	ldp	x6,x7,[x1,#8*0]	// a[0..3]
+	ldp	x8,x9,[x1,#8*2]
+	add	x1,x1,#8*4
+	mov	x19,xzr
+	mov	x20,xzr
+	mov	x21,xzr
+	mov	x22,xzr
+	ldp	x14,x15,[x3,#8*0]	// n[0..3]
+	ldp	x16,x17,[x3,#8*2]
+	adds	x3,x3,#8*4		// clear carry bit
+	mov	x0,xzr
+	mov	x28,#0
+	mov	x26,sp
+
+Loop_mul4x_1st_reduction:
+	mul	x10,x6,x24		// lo(a[0..3]*b[0])
+	adc	x0,x0,xzr	// modulo-scheduled
+	mul	x11,x7,x24
+	add	x28,x28,#8
+	mul	x12,x8,x24
+	and	x28,x28,#31
+	mul	x13,x9,x24
+	adds	x19,x19,x10
+	umulh	x10,x6,x24		// hi(a[0..3]*b[0])
+	adcs	x20,x20,x11
+	mul	x25,x19,x4		// t[0]*n0
+	adcs	x21,x21,x12
+	umulh	x11,x7,x24
+	adcs	x22,x22,x13
+	umulh	x12,x8,x24
+	adc	x23,xzr,xzr
+	umulh	x13,x9,x24
+	ldr	x24,[x2,x28]		// next b[i] (or b[0])
+	adds	x20,x20,x10
+	// (*)	mul	x10,x14,x25	// lo(n[0..3]*t[0]*n0)
+	str	x25,[x26],#8		// put aside t[0]*n0 for tail processing
+	adcs	x21,x21,x11
+	mul	x11,x15,x25
+	adcs	x22,x22,x12
+	mul	x12,x16,x25
+	adc	x23,x23,x13		// can't overflow
+	mul	x13,x17,x25
+	// (*)	adds	xzr,x19,x10
+	subs	xzr,x19,#1		// (*)
+	umulh	x10,x14,x25		// hi(n[0..3]*t[0]*n0)
+	adcs	x19,x20,x11
+	umulh	x11,x15,x25
+	adcs	x20,x21,x12
+	umulh	x12,x16,x25
+	adcs	x21,x22,x13
+	umulh	x13,x17,x25
+	adcs	x22,x23,x0
+	adc	x0,xzr,xzr
+	adds	x19,x19,x10
+	sub	x10,x27,x1
+	adcs	x20,x20,x11
+	adcs	x21,x21,x12
+	adcs	x22,x22,x13
+	//adc	x0,x0,xzr
+	cbnz	x28,Loop_mul4x_1st_reduction
+
+	cbz	x10,Lmul4x4_post_condition
+
+	ldp	x6,x7,[x1,#8*0]	// a[4..7]
+	ldp	x8,x9,[x1,#8*2]
+	add	x1,x1,#8*4
+	ldr	x25,[sp]		// a[0]*n0
+	ldp	x14,x15,[x3,#8*0]	// n[4..7]
+	ldp	x16,x17,[x3,#8*2]
+	add	x3,x3,#8*4
+
+Loop_mul4x_1st_tail:
+	mul	x10,x6,x24		// lo(a[4..7]*b[i])
+	adc	x0,x0,xzr	// modulo-scheduled
+	mul	x11,x7,x24
+	add	x28,x28,#8
+	mul	x12,x8,x24
+	and	x28,x28,#31
+	mul	x13,x9,x24
+	adds	x19,x19,x10
+	umulh	x10,x6,x24		// hi(a[4..7]*b[i])
+	adcs	x20,x20,x11
+	umulh	x11,x7,x24
+	adcs	x21,x21,x12
+	umulh	x12,x8,x24
+	adcs	x22,x22,x13
+	umulh	x13,x9,x24
+	adc	x23,xzr,xzr
+	ldr	x24,[x2,x28]		// next b[i] (or b[0])
+	adds	x20,x20,x10
+	mul	x10,x14,x25		// lo(n[4..7]*a[0]*n0)
+	adcs	x21,x21,x11
+	mul	x11,x15,x25
+	adcs	x22,x22,x12
+	mul	x12,x16,x25
+	adc	x23,x23,x13		// can't overflow
+	mul	x13,x17,x25
+	adds	x19,x19,x10
+	umulh	x10,x14,x25		// hi(n[4..7]*a[0]*n0)
+	adcs	x20,x20,x11
+	umulh	x11,x15,x25
+	adcs	x21,x21,x12
+	umulh	x12,x16,x25
+	adcs	x22,x22,x13
+	adcs	x23,x23,x0
+	umulh	x13,x17,x25
+	adc	x0,xzr,xzr
+	ldr	x25,[sp,x28]		// next t[0]*n0
+	str	x19,[x26],#8		// result!!!
+	adds	x19,x20,x10
+	sub	x10,x27,x1		// done yet?
+	adcs	x20,x21,x11
+	adcs	x21,x22,x12
+	adcs	x22,x23,x13
+	//adc	x0,x0,xzr
+	cbnz	x28,Loop_mul4x_1st_tail
+
+	sub	x11,x27,x5	// rewinded x1
+	cbz	x10,Lmul4x_proceed
+
+	ldp	x6,x7,[x1,#8*0]
+	ldp	x8,x9,[x1,#8*2]
+	add	x1,x1,#8*4
+	ldp	x14,x15,[x3,#8*0]
+	ldp	x16,x17,[x3,#8*2]
+	add	x3,x3,#8*4
+	b	Loop_mul4x_1st_tail
+
+.align	5
+Lmul4x_proceed:
+	ldr	x24,[x2,#8*4]!		// *++b
+	adc	x30,x0,xzr
+	ldp	x6,x7,[x11,#8*0]	// a[0..3]
+	sub	x3,x3,x5		// rewind np
+	ldp	x8,x9,[x11,#8*2]
+	add	x1,x11,#8*4
+
+	stp	x19,x20,[x26,#8*0]	// result!!!
+	ldp	x19,x20,[sp,#8*4]	// t[0..3]
+	stp	x21,x22,[x26,#8*2]	// result!!!
+	ldp	x21,x22,[sp,#8*6]
+
+	ldp	x14,x15,[x3,#8*0]	// n[0..3]
+	mov	x26,sp
+	ldp	x16,x17,[x3,#8*2]
+	adds	x3,x3,#8*4		// clear carry bit
+	mov	x0,xzr
+
+.align	4
+Loop_mul4x_reduction:
+	mul	x10,x6,x24		// lo(a[0..3]*b[4])
+	adc	x0,x0,xzr	// modulo-scheduled
+	mul	x11,x7,x24
+	add	x28,x28,#8
+	mul	x12,x8,x24
+	and	x28,x28,#31
+	mul	x13,x9,x24
+	adds	x19,x19,x10
+	umulh	x10,x6,x24		// hi(a[0..3]*b[4])
+	adcs	x20,x20,x11
+	mul	x25,x19,x4		// t[0]*n0
+	adcs	x21,x21,x12
+	umulh	x11,x7,x24
+	adcs	x22,x22,x13
+	umulh	x12,x8,x24
+	adc	x23,xzr,xzr
+	umulh	x13,x9,x24
+	ldr	x24,[x2,x28]		// next b[i]
+	adds	x20,x20,x10
+	// (*)	mul	x10,x14,x25
+	str	x25,[x26],#8		// put aside t[0]*n0 for tail processing
+	adcs	x21,x21,x11
+	mul	x11,x15,x25		// lo(n[0..3]*t[0]*n0
+	adcs	x22,x22,x12
+	mul	x12,x16,x25
+	adc	x23,x23,x13		// can't overflow
+	mul	x13,x17,x25
+	// (*)	adds	xzr,x19,x10
+	subs	xzr,x19,#1		// (*)
+	umulh	x10,x14,x25		// hi(n[0..3]*t[0]*n0
+	adcs	x19,x20,x11
+	umulh	x11,x15,x25
+	adcs	x20,x21,x12
+	umulh	x12,x16,x25
+	adcs	x21,x22,x13
+	umulh	x13,x17,x25
+	adcs	x22,x23,x0
+	adc	x0,xzr,xzr
+	adds	x19,x19,x10
+	adcs	x20,x20,x11
+	adcs	x21,x21,x12
+	adcs	x22,x22,x13
+	//adc	x0,x0,xzr
+	cbnz	x28,Loop_mul4x_reduction
+
+	adc	x0,x0,xzr
+	ldp	x10,x11,[x26,#8*4]	// t[4..7]
+	ldp	x12,x13,[x26,#8*6]
+	ldp	x6,x7,[x1,#8*0]	// a[4..7]
+	ldp	x8,x9,[x1,#8*2]
+	add	x1,x1,#8*4
+	adds	x19,x19,x10
+	adcs	x20,x20,x11
+	adcs	x21,x21,x12
+	adcs	x22,x22,x13
+	//adc	x0,x0,xzr
+
+	ldr	x25,[sp]		// t[0]*n0
+	ldp	x14,x15,[x3,#8*0]	// n[4..7]
+	ldp	x16,x17,[x3,#8*2]
+	add	x3,x3,#8*4
+
+.align	4
+Loop_mul4x_tail:
+	mul	x10,x6,x24		// lo(a[4..7]*b[4])
+	adc	x0,x0,xzr	// modulo-scheduled
+	mul	x11,x7,x24
+	add	x28,x28,#8
+	mul	x12,x8,x24
+	and	x28,x28,#31
+	mul	x13,x9,x24
+	adds	x19,x19,x10
+	umulh	x10,x6,x24		// hi(a[4..7]*b[4])
+	adcs	x20,x20,x11
+	umulh	x11,x7,x24
+	adcs	x21,x21,x12
+	umulh	x12,x8,x24
+	adcs	x22,x22,x13
+	umulh	x13,x9,x24
+	adc	x23,xzr,xzr
+	ldr	x24,[x2,x28]		// next b[i]
+	adds	x20,x20,x10
+	mul	x10,x14,x25		// lo(n[4..7]*t[0]*n0)
+	adcs	x21,x21,x11
+	mul	x11,x15,x25
+	adcs	x22,x22,x12
+	mul	x12,x16,x25
+	adc	x23,x23,x13		// can't overflow
+	mul	x13,x17,x25
+	adds	x19,x19,x10
+	umulh	x10,x14,x25		// hi(n[4..7]*t[0]*n0)
+	adcs	x20,x20,x11
+	umulh	x11,x15,x25
+	adcs	x21,x21,x12
+	umulh	x12,x16,x25
+	adcs	x22,x22,x13
+	umulh	x13,x17,x25
+	adcs	x23,x23,x0
+	ldr	x25,[sp,x28]		// next a[0]*n0
+	adc	x0,xzr,xzr
+	str	x19,[x26],#8		// result!!!
+	adds	x19,x20,x10
+	sub	x10,x27,x1		// done yet?
+	adcs	x20,x21,x11
+	adcs	x21,x22,x12
+	adcs	x22,x23,x13
+	//adc	x0,x0,xzr
+	cbnz	x28,Loop_mul4x_tail
+
+	sub	x11,x3,x5		// rewinded np?
+	adc	x0,x0,xzr
+	cbz	x10,Loop_mul4x_break
+
+	ldp	x10,x11,[x26,#8*4]
+	ldp	x12,x13,[x26,#8*6]
+	ldp	x6,x7,[x1,#8*0]
+	ldp	x8,x9,[x1,#8*2]
+	add	x1,x1,#8*4
+	adds	x19,x19,x10
+	adcs	x20,x20,x11
+	adcs	x21,x21,x12
+	adcs	x22,x22,x13
+	//adc	x0,x0,xzr
+	ldp	x14,x15,[x3,#8*0]
+	ldp	x16,x17,[x3,#8*2]
+	add	x3,x3,#8*4
+	b	Loop_mul4x_tail
+
+.align	4
+Loop_mul4x_break:
+	ldp	x12,x13,[x29,#96]	// pull rp and &b[num]
+	adds	x19,x19,x30
+	add	x2,x2,#8*4		// bp++
+	adcs	x20,x20,xzr
+	sub	x1,x1,x5		// rewind ap
+	adcs	x21,x21,xzr
+	stp	x19,x20,[x26,#8*0]	// result!!!
+	adcs	x22,x22,xzr
+	ldp	x19,x20,[sp,#8*4]	// t[0..3]
+	adc	x30,x0,xzr
+	stp	x21,x22,[x26,#8*2]	// result!!!
+	cmp	x2,x13			// done yet?
+	ldp	x21,x22,[sp,#8*6]
+	ldp	x14,x15,[x11,#8*0]	// n[0..3]
+	ldp	x16,x17,[x11,#8*2]
+	add	x3,x11,#8*4
+	b.eq	Lmul4x_post
+
+	ldr	x24,[x2]
+	ldp	x6,x7,[x1,#8*0]	// a[0..3]
+	ldp	x8,x9,[x1,#8*2]
+	adds	x1,x1,#8*4		// clear carry bit
+	mov	x0,xzr
+	mov	x26,sp
+	b	Loop_mul4x_reduction
+
+.align	4
+Lmul4x_post:
+	// Final step. We see if result is larger than modulus, and
+	// if it is, subtract the modulus. But comparison implies
+	// subtraction. So we subtract modulus, see if it borrowed,
+	// and conditionally copy original value.
+	mov	x0,x12
+	mov	x27,x12		// x0 copy
+	subs	x10,x19,x14
+	add	x26,sp,#8*8
+	sbcs	x11,x20,x15
+	sub	x28,x5,#8*4
+
+Lmul4x_sub:
+	sbcs	x12,x21,x16
+	ldp	x14,x15,[x3,#8*0]
+	sub	x28,x28,#8*4
+	ldp	x19,x20,[x26,#8*0]
+	sbcs	x13,x22,x17
+	ldp	x16,x17,[x3,#8*2]
+	add	x3,x3,#8*4
+	ldp	x21,x22,[x26,#8*2]
+	add	x26,x26,#8*4
+	stp	x10,x11,[x0,#8*0]
+	sbcs	x10,x19,x14
+	stp	x12,x13,[x0,#8*2]
+	add	x0,x0,#8*4
+	sbcs	x11,x20,x15
+	cbnz	x28,Lmul4x_sub
+
+	sbcs	x12,x21,x16
+	mov	x26,sp
+	add	x1,sp,#8*4
+	ldp	x6,x7,[x27,#8*0]
+	sbcs	x13,x22,x17
+	stp	x10,x11,[x0,#8*0]
+	ldp	x8,x9,[x27,#8*2]
+	stp	x12,x13,[x0,#8*2]
+	ldp	x19,x20,[x1,#8*0]
+	ldp	x21,x22,[x1,#8*2]
+	sbcs	xzr,x30,xzr	// did it borrow?
+	ldr	x30,[x29,#8]		// pull return address
+
+	sub	x28,x5,#8*4
+Lmul4x_cond_copy:
+	sub	x28,x28,#8*4
+	csel	x10,x19,x6,lo
+	stp	xzr,xzr,[x26,#8*0]
+	csel	x11,x20,x7,lo
+	ldp	x6,x7,[x27,#8*4]
+	ldp	x19,x20,[x1,#8*4]
+	csel	x12,x21,x8,lo
+	stp	xzr,xzr,[x26,#8*2]
+	add	x26,x26,#8*4
+	csel	x13,x22,x9,lo
+	ldp	x8,x9,[x27,#8*6]
+	ldp	x21,x22,[x1,#8*6]
+	add	x1,x1,#8*4
+	stp	x10,x11,[x27,#8*0]
+	stp	x12,x13,[x27,#8*2]
+	add	x27,x27,#8*4
+	cbnz	x28,Lmul4x_cond_copy
+
+	csel	x10,x19,x6,lo
+	stp	xzr,xzr,[x26,#8*0]
+	csel	x11,x20,x7,lo
+	stp	xzr,xzr,[x26,#8*2]
+	csel	x12,x21,x8,lo
+	stp	xzr,xzr,[x26,#8*3]
+	csel	x13,x22,x9,lo
+	stp	xzr,xzr,[x26,#8*4]
+	stp	x10,x11,[x27,#8*0]
+	stp	x12,x13,[x27,#8*2]
+
+	b	Lmul4x_done
+
+.align	4
+Lmul4x4_post_condition:
+	adc	x0,x0,xzr
+	ldr	x1,[x29,#96]		// pull rp
+	// x19-3,x0 hold result, x14-7 hold modulus
+	subs	x6,x19,x14
+	ldr	x30,[x29,#8]		// pull return address
+	sbcs	x7,x20,x15
+	stp	xzr,xzr,[sp,#8*0]
+	sbcs	x8,x21,x16
+	stp	xzr,xzr,[sp,#8*2]
+	sbcs	x9,x22,x17
+	stp	xzr,xzr,[sp,#8*4]
+	sbcs	xzr,x0,xzr		// did it borrow?
+	stp	xzr,xzr,[sp,#8*6]
+
+	// x6-3 hold result-modulus
+	csel	x6,x19,x6,lo
+	csel	x7,x20,x7,lo
+	csel	x8,x21,x8,lo
+	csel	x9,x22,x9,lo
+	stp	x6,x7,[x1,#8*0]
+	stp	x8,x9,[x1,#8*2]
+
+Lmul4x_done:
+	ldp	x19,x20,[x29,#16]
+	mov	sp,x29
+	ldp	x21,x22,[x29,#32]
+	mov	x0,#1
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldr	x29,[sp],#128
+	ret
+
+.byte	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105,112,108,105,99,97,116,105,111,110,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+.align	4
diff --git a/third_party/boringssl/ios-aarch64/crypto/fipsmodule/ghashv8-armx64.S b/third_party/boringssl/ios-aarch64/crypto/fipsmodule/ghashv8-armx64.S
new file mode 100644
index 0000000..01d32321
--- /dev/null
+++ b/third_party/boringssl/ios-aarch64/crypto/fipsmodule/ghashv8-armx64.S
@@ -0,0 +1,233 @@
+#include <openssl/arm_arch.h>
+
+.text
+#if !defined(__clang__) || defined(BORINGSSL_CLANG_SUPPORTS_DOT_ARCH)
+
+#endif
+.globl	_gcm_init_v8
+.private_extern	_gcm_init_v8
+
+.align	4
+_gcm_init_v8:
+	ld1	{v17.2d},[x1]		//load input H
+	movi	v19.16b,#0xe1
+	shl	v19.2d,v19.2d,#57		//0xc2.0
+	ext	v3.16b,v17.16b,v17.16b,#8
+	ushr	v18.2d,v19.2d,#63
+	dup	v17.4s,v17.s[1]
+	ext	v16.16b,v18.16b,v19.16b,#8		//t0=0xc2....01
+	ushr	v18.2d,v3.2d,#63
+	sshr	v17.4s,v17.4s,#31		//broadcast carry bit
+	and	v18.16b,v18.16b,v16.16b
+	shl	v3.2d,v3.2d,#1
+	ext	v18.16b,v18.16b,v18.16b,#8
+	and	v16.16b,v16.16b,v17.16b
+	orr	v3.16b,v3.16b,v18.16b		//H<<<=1
+	eor	v20.16b,v3.16b,v16.16b		//twisted H
+	st1	{v20.2d},[x0],#16		//store Htable[0]
+
+	//calculate H^2
+	ext	v16.16b,v20.16b,v20.16b,#8		//Karatsuba pre-processing
+	pmull	v0.1q,v20.1d,v20.1d
+	eor	v16.16b,v16.16b,v20.16b
+	pmull2	v2.1q,v20.2d,v20.2d
+	pmull	v1.1q,v16.1d,v16.1d
+
+	ext	v17.16b,v0.16b,v2.16b,#8		//Karatsuba post-processing
+	eor	v18.16b,v0.16b,v2.16b
+	eor	v1.16b,v1.16b,v17.16b
+	eor	v1.16b,v1.16b,v18.16b
+	pmull	v18.1q,v0.1d,v19.1d		//1st phase
+
+	ins	v2.d[0],v1.d[1]
+	ins	v1.d[1],v0.d[0]
+	eor	v0.16b,v1.16b,v18.16b
+
+	ext	v18.16b,v0.16b,v0.16b,#8		//2nd phase
+	pmull	v0.1q,v0.1d,v19.1d
+	eor	v18.16b,v18.16b,v2.16b
+	eor	v22.16b,v0.16b,v18.16b
+
+	ext	v17.16b,v22.16b,v22.16b,#8		//Karatsuba pre-processing
+	eor	v17.16b,v17.16b,v22.16b
+	ext	v21.16b,v16.16b,v17.16b,#8		//pack Karatsuba pre-processed
+	st1	{v21.2d,v22.2d},[x0]		//store Htable[1..2]
+
+	ret
+
+.globl	_gcm_gmult_v8
+.private_extern	_gcm_gmult_v8
+
+.align	4
+_gcm_gmult_v8:
+	ld1	{v17.2d},[x0]		//load Xi
+	movi	v19.16b,#0xe1
+	ld1	{v20.2d,v21.2d},[x1]	//load twisted H, ...
+	shl	v19.2d,v19.2d,#57
+#ifndef __ARMEB__
+	rev64	v17.16b,v17.16b
+#endif
+	ext	v3.16b,v17.16b,v17.16b,#8
+
+	pmull	v0.1q,v20.1d,v3.1d		//H.lo·Xi.lo
+	eor	v17.16b,v17.16b,v3.16b		//Karatsuba pre-processing
+	pmull2	v2.1q,v20.2d,v3.2d		//H.hi·Xi.hi
+	pmull	v1.1q,v21.1d,v17.1d		//(H.lo+H.hi)·(Xi.lo+Xi.hi)
+
+	ext	v17.16b,v0.16b,v2.16b,#8		//Karatsuba post-processing
+	eor	v18.16b,v0.16b,v2.16b
+	eor	v1.16b,v1.16b,v17.16b
+	eor	v1.16b,v1.16b,v18.16b
+	pmull	v18.1q,v0.1d,v19.1d		//1st phase of reduction
+
+	ins	v2.d[0],v1.d[1]
+	ins	v1.d[1],v0.d[0]
+	eor	v0.16b,v1.16b,v18.16b
+
+	ext	v18.16b,v0.16b,v0.16b,#8		//2nd phase of reduction
+	pmull	v0.1q,v0.1d,v19.1d
+	eor	v18.16b,v18.16b,v2.16b
+	eor	v0.16b,v0.16b,v18.16b
+
+#ifndef __ARMEB__
+	rev64	v0.16b,v0.16b
+#endif
+	ext	v0.16b,v0.16b,v0.16b,#8
+	st1	{v0.2d},[x0]		//write out Xi
+
+	ret
+
+.globl	_gcm_ghash_v8
+.private_extern	_gcm_ghash_v8
+
+.align	4
+_gcm_ghash_v8:
+	ld1	{v0.2d},[x0]		//load [rotated] Xi
+						//"[rotated]" means that
+						//loaded value would have
+						//to be rotated in order to
+						//make it appear as in
+						//alorithm specification
+	subs	x3,x3,#32		//see if x3 is 32 or larger
+	mov	x12,#16		//x12 is used as post-
+						//increment for input pointer;
+						//as loop is modulo-scheduled
+						//x12 is zeroed just in time
+						//to preclude oversteping
+						//inp[len], which means that
+						//last block[s] are actually
+						//loaded twice, but last
+						//copy is not processed
+	ld1	{v20.2d,v21.2d},[x1],#32	//load twisted H, ..., H^2
+	movi	v19.16b,#0xe1
+	ld1	{v22.2d},[x1]
+	csel	x12,xzr,x12,eq			//is it time to zero x12?
+	ext	v0.16b,v0.16b,v0.16b,#8		//rotate Xi
+	ld1	{v16.2d},[x2],#16	//load [rotated] I[0]
+	shl	v19.2d,v19.2d,#57		//compose 0xc2.0 constant
+#ifndef __ARMEB__
+	rev64	v16.16b,v16.16b
+	rev64	v0.16b,v0.16b
+#endif
+	ext	v3.16b,v16.16b,v16.16b,#8		//rotate I[0]
+	b.lo	Lodd_tail_v8		//x3 was less than 32
+	ld1	{v17.2d},[x2],x12	//load [rotated] I[1]
+#ifndef __ARMEB__
+	rev64	v17.16b,v17.16b
+#endif
+	ext	v7.16b,v17.16b,v17.16b,#8
+	eor	v3.16b,v3.16b,v0.16b		//I[i]^=Xi
+	pmull	v4.1q,v20.1d,v7.1d		//H·Ii+1
+	eor	v17.16b,v17.16b,v7.16b		//Karatsuba pre-processing
+	pmull2	v6.1q,v20.2d,v7.2d
+	b	Loop_mod2x_v8
+
+.align	4
+Loop_mod2x_v8:
+	ext	v18.16b,v3.16b,v3.16b,#8
+	subs	x3,x3,#32		//is there more data?
+	pmull	v0.1q,v22.1d,v3.1d		//H^2.lo·Xi.lo
+	csel	x12,xzr,x12,lo			//is it time to zero x12?
+
+	pmull	v5.1q,v21.1d,v17.1d
+	eor	v18.16b,v18.16b,v3.16b		//Karatsuba pre-processing
+	pmull2	v2.1q,v22.2d,v3.2d		//H^2.hi·Xi.hi
+	eor	v0.16b,v0.16b,v4.16b		//accumulate
+	pmull2	v1.1q,v21.2d,v18.2d		//(H^2.lo+H^2.hi)·(Xi.lo+Xi.hi)
+	ld1	{v16.2d},[x2],x12	//load [rotated] I[i+2]
+
+	eor	v2.16b,v2.16b,v6.16b
+	csel	x12,xzr,x12,eq			//is it time to zero x12?
+	eor	v1.16b,v1.16b,v5.16b
+
+	ext	v17.16b,v0.16b,v2.16b,#8		//Karatsuba post-processing
+	eor	v18.16b,v0.16b,v2.16b
+	eor	v1.16b,v1.16b,v17.16b
+	ld1	{v17.2d},[x2],x12	//load [rotated] I[i+3]
+#ifndef __ARMEB__
+	rev64	v16.16b,v16.16b
+#endif
+	eor	v1.16b,v1.16b,v18.16b
+	pmull	v18.1q,v0.1d,v19.1d		//1st phase of reduction
+
+#ifndef __ARMEB__
+	rev64	v17.16b,v17.16b
+#endif
+	ins	v2.d[0],v1.d[1]
+	ins	v1.d[1],v0.d[0]
+	ext	v7.16b,v17.16b,v17.16b,#8
+	ext	v3.16b,v16.16b,v16.16b,#8
+	eor	v0.16b,v1.16b,v18.16b
+	pmull	v4.1q,v20.1d,v7.1d		//H·Ii+1
+	eor	v3.16b,v3.16b,v2.16b		//accumulate v3.16b early
+
+	ext	v18.16b,v0.16b,v0.16b,#8		//2nd phase of reduction
+	pmull	v0.1q,v0.1d,v19.1d
+	eor	v3.16b,v3.16b,v18.16b
+	eor	v17.16b,v17.16b,v7.16b		//Karatsuba pre-processing
+	eor	v3.16b,v3.16b,v0.16b
+	pmull2	v6.1q,v20.2d,v7.2d
+	b.hs	Loop_mod2x_v8		//there was at least 32 more bytes
+
+	eor	v2.16b,v2.16b,v18.16b
+	ext	v3.16b,v16.16b,v16.16b,#8		//re-construct v3.16b
+	adds	x3,x3,#32		//re-construct x3
+	eor	v0.16b,v0.16b,v2.16b		//re-construct v0.16b
+	b.eq	Ldone_v8		//is x3 zero?
+Lodd_tail_v8:
+	ext	v18.16b,v0.16b,v0.16b,#8
+	eor	v3.16b,v3.16b,v0.16b		//inp^=Xi
+	eor	v17.16b,v16.16b,v18.16b		//v17.16b is rotated inp^Xi
+
+	pmull	v0.1q,v20.1d,v3.1d		//H.lo·Xi.lo
+	eor	v17.16b,v17.16b,v3.16b		//Karatsuba pre-processing
+	pmull2	v2.1q,v20.2d,v3.2d		//H.hi·Xi.hi
+	pmull	v1.1q,v21.1d,v17.1d		//(H.lo+H.hi)·(Xi.lo+Xi.hi)
+
+	ext	v17.16b,v0.16b,v2.16b,#8		//Karatsuba post-processing
+	eor	v18.16b,v0.16b,v2.16b
+	eor	v1.16b,v1.16b,v17.16b
+	eor	v1.16b,v1.16b,v18.16b
+	pmull	v18.1q,v0.1d,v19.1d		//1st phase of reduction
+
+	ins	v2.d[0],v1.d[1]
+	ins	v1.d[1],v0.d[0]
+	eor	v0.16b,v1.16b,v18.16b
+
+	ext	v18.16b,v0.16b,v0.16b,#8		//2nd phase of reduction
+	pmull	v0.1q,v0.1d,v19.1d
+	eor	v18.16b,v18.16b,v2.16b
+	eor	v0.16b,v0.16b,v18.16b
+
+Ldone_v8:
+#ifndef __ARMEB__
+	rev64	v0.16b,v0.16b
+#endif
+	ext	v0.16b,v0.16b,v0.16b,#8
+	st1	{v0.2d},[x0]		//write out Xi
+
+	ret
+
+.byte	71,72,65,83,72,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+.align	2
diff --git a/third_party/boringssl/ios-aarch64/crypto/fipsmodule/sha1-armv8.S b/third_party/boringssl/ios-aarch64/crypto/fipsmodule/sha1-armv8.S
new file mode 100644
index 0000000..00a8f10
--- /dev/null
+++ b/third_party/boringssl/ios-aarch64/crypto/fipsmodule/sha1-armv8.S
@@ -0,0 +1,1214 @@
+#include <openssl/arm_arch.h>
+
+.text
+
+
+.globl	_sha1_block_data_order
+.private_extern	_sha1_block_data_order
+
+.align	6
+_sha1_block_data_order:
+	ldr	x16,LOPENSSL_armcap_P
+	adr	x17,LOPENSSL_armcap_P
+	add	x16,x16,x17
+	ldr	w16,[x16]
+	tst	w16,#ARMV8_SHA1
+	b.ne	Lv8_entry
+
+	stp	x29,x30,[sp,#-96]!
+	add	x29,sp,#0
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+
+	ldp	w20,w21,[x0]
+	ldp	w22,w23,[x0,#8]
+	ldr	w24,[x0,#16]
+
+Loop:
+	ldr	x3,[x1],#64
+	movz	w28,#0x7999
+	sub	x2,x2,#1
+	movk	w28,#0x5a82,lsl#16
+#ifdef	__ARMEB__
+	ror	x3,x3,#32
+#else
+	rev32	x3,x3
+#endif
+	add	w24,w24,w28		// warm it up
+	add	w24,w24,w3
+	lsr	x4,x3,#32
+	ldr	x5,[x1,#-56]
+	bic	w25,w23,w21
+	and	w26,w22,w21
+	ror	w27,w20,#27
+	add	w23,w23,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w24,w24,w27		// e+=rot(a,5)
+	ror	w21,w21,#2
+	add	w23,w23,w4	// future e+=X[i]
+	add	w24,w24,w25		// e+=F(b,c,d)
+#ifdef	__ARMEB__
+	ror	x5,x5,#32
+#else
+	rev32	x5,x5
+#endif
+	bic	w25,w22,w20
+	and	w26,w21,w20
+	ror	w27,w24,#27
+	add	w22,w22,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w23,w23,w27		// e+=rot(a,5)
+	ror	w20,w20,#2
+	add	w22,w22,w5	// future e+=X[i]
+	add	w23,w23,w25		// e+=F(b,c,d)
+	lsr	x6,x5,#32
+	ldr	x7,[x1,#-48]
+	bic	w25,w21,w24
+	and	w26,w20,w24
+	ror	w27,w23,#27
+	add	w21,w21,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w22,w22,w27		// e+=rot(a,5)
+	ror	w24,w24,#2
+	add	w21,w21,w6	// future e+=X[i]
+	add	w22,w22,w25		// e+=F(b,c,d)
+#ifdef	__ARMEB__
+	ror	x7,x7,#32
+#else
+	rev32	x7,x7
+#endif
+	bic	w25,w20,w23
+	and	w26,w24,w23
+	ror	w27,w22,#27
+	add	w20,w20,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w21,w21,w27		// e+=rot(a,5)
+	ror	w23,w23,#2
+	add	w20,w20,w7	// future e+=X[i]
+	add	w21,w21,w25		// e+=F(b,c,d)
+	lsr	x8,x7,#32
+	ldr	x9,[x1,#-40]
+	bic	w25,w24,w22
+	and	w26,w23,w22
+	ror	w27,w21,#27
+	add	w24,w24,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w20,w20,w27		// e+=rot(a,5)
+	ror	w22,w22,#2
+	add	w24,w24,w8	// future e+=X[i]
+	add	w20,w20,w25		// e+=F(b,c,d)
+#ifdef	__ARMEB__
+	ror	x9,x9,#32
+#else
+	rev32	x9,x9
+#endif
+	bic	w25,w23,w21
+	and	w26,w22,w21
+	ror	w27,w20,#27
+	add	w23,w23,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w24,w24,w27		// e+=rot(a,5)
+	ror	w21,w21,#2
+	add	w23,w23,w9	// future e+=X[i]
+	add	w24,w24,w25		// e+=F(b,c,d)
+	lsr	x10,x9,#32
+	ldr	x11,[x1,#-32]
+	bic	w25,w22,w20
+	and	w26,w21,w20
+	ror	w27,w24,#27
+	add	w22,w22,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w23,w23,w27		// e+=rot(a,5)
+	ror	w20,w20,#2
+	add	w22,w22,w10	// future e+=X[i]
+	add	w23,w23,w25		// e+=F(b,c,d)
+#ifdef	__ARMEB__
+	ror	x11,x11,#32
+#else
+	rev32	x11,x11
+#endif
+	bic	w25,w21,w24
+	and	w26,w20,w24
+	ror	w27,w23,#27
+	add	w21,w21,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w22,w22,w27		// e+=rot(a,5)
+	ror	w24,w24,#2
+	add	w21,w21,w11	// future e+=X[i]
+	add	w22,w22,w25		// e+=F(b,c,d)
+	lsr	x12,x11,#32
+	ldr	x13,[x1,#-24]
+	bic	w25,w20,w23
+	and	w26,w24,w23
+	ror	w27,w22,#27
+	add	w20,w20,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w21,w21,w27		// e+=rot(a,5)
+	ror	w23,w23,#2
+	add	w20,w20,w12	// future e+=X[i]
+	add	w21,w21,w25		// e+=F(b,c,d)
+#ifdef	__ARMEB__
+	ror	x13,x13,#32
+#else
+	rev32	x13,x13
+#endif
+	bic	w25,w24,w22
+	and	w26,w23,w22
+	ror	w27,w21,#27
+	add	w24,w24,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w20,w20,w27		// e+=rot(a,5)
+	ror	w22,w22,#2
+	add	w24,w24,w13	// future e+=X[i]
+	add	w20,w20,w25		// e+=F(b,c,d)
+	lsr	x14,x13,#32
+	ldr	x15,[x1,#-16]
+	bic	w25,w23,w21
+	and	w26,w22,w21
+	ror	w27,w20,#27
+	add	w23,w23,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w24,w24,w27		// e+=rot(a,5)
+	ror	w21,w21,#2
+	add	w23,w23,w14	// future e+=X[i]
+	add	w24,w24,w25		// e+=F(b,c,d)
+#ifdef	__ARMEB__
+	ror	x15,x15,#32
+#else
+	rev32	x15,x15
+#endif
+	bic	w25,w22,w20
+	and	w26,w21,w20
+	ror	w27,w24,#27
+	add	w22,w22,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w23,w23,w27		// e+=rot(a,5)
+	ror	w20,w20,#2
+	add	w22,w22,w15	// future e+=X[i]
+	add	w23,w23,w25		// e+=F(b,c,d)
+	lsr	x16,x15,#32
+	ldr	x17,[x1,#-8]
+	bic	w25,w21,w24
+	and	w26,w20,w24
+	ror	w27,w23,#27
+	add	w21,w21,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w22,w22,w27		// e+=rot(a,5)
+	ror	w24,w24,#2
+	add	w21,w21,w16	// future e+=X[i]
+	add	w22,w22,w25		// e+=F(b,c,d)
+#ifdef	__ARMEB__
+	ror	x17,x17,#32
+#else
+	rev32	x17,x17
+#endif
+	bic	w25,w20,w23
+	and	w26,w24,w23
+	ror	w27,w22,#27
+	add	w20,w20,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w21,w21,w27		// e+=rot(a,5)
+	ror	w23,w23,#2
+	add	w20,w20,w17	// future e+=X[i]
+	add	w21,w21,w25		// e+=F(b,c,d)
+	lsr	x19,x17,#32
+	eor	w3,w3,w5
+	bic	w25,w24,w22
+	and	w26,w23,w22
+	ror	w27,w21,#27
+	eor	w3,w3,w11
+	add	w24,w24,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w20,w20,w27		// e+=rot(a,5)
+	eor	w3,w3,w16
+	ror	w22,w22,#2
+	add	w24,w24,w19	// future e+=X[i]
+	add	w20,w20,w25		// e+=F(b,c,d)
+	ror	w3,w3,#31
+	eor	w4,w4,w6
+	bic	w25,w23,w21
+	and	w26,w22,w21
+	ror	w27,w20,#27
+	eor	w4,w4,w12
+	add	w23,w23,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w24,w24,w27		// e+=rot(a,5)
+	eor	w4,w4,w17
+	ror	w21,w21,#2
+	add	w23,w23,w3	// future e+=X[i]
+	add	w24,w24,w25		// e+=F(b,c,d)
+	ror	w4,w4,#31
+	eor	w5,w5,w7
+	bic	w25,w22,w20
+	and	w26,w21,w20
+	ror	w27,w24,#27
+	eor	w5,w5,w13
+	add	w22,w22,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w23,w23,w27		// e+=rot(a,5)
+	eor	w5,w5,w19
+	ror	w20,w20,#2
+	add	w22,w22,w4	// future e+=X[i]
+	add	w23,w23,w25		// e+=F(b,c,d)
+	ror	w5,w5,#31
+	eor	w6,w6,w8
+	bic	w25,w21,w24
+	and	w26,w20,w24
+	ror	w27,w23,#27
+	eor	w6,w6,w14
+	add	w21,w21,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w22,w22,w27		// e+=rot(a,5)
+	eor	w6,w6,w3
+	ror	w24,w24,#2
+	add	w21,w21,w5	// future e+=X[i]
+	add	w22,w22,w25		// e+=F(b,c,d)
+	ror	w6,w6,#31
+	eor	w7,w7,w9
+	bic	w25,w20,w23
+	and	w26,w24,w23
+	ror	w27,w22,#27
+	eor	w7,w7,w15
+	add	w20,w20,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w21,w21,w27		// e+=rot(a,5)
+	eor	w7,w7,w4
+	ror	w23,w23,#2
+	add	w20,w20,w6	// future e+=X[i]
+	add	w21,w21,w25		// e+=F(b,c,d)
+	ror	w7,w7,#31
+	movz	w28,#0xeba1
+	movk	w28,#0x6ed9,lsl#16
+	eor	w8,w8,w10
+	bic	w25,w24,w22
+	and	w26,w23,w22
+	ror	w27,w21,#27
+	eor	w8,w8,w16
+	add	w24,w24,w28		// future e+=K
+	orr	w25,w25,w26
+	add	w20,w20,w27		// e+=rot(a,5)
+	eor	w8,w8,w5
+	ror	w22,w22,#2
+	add	w24,w24,w7	// future e+=X[i]
+	add	w20,w20,w25		// e+=F(b,c,d)
+	ror	w8,w8,#31
+	eor	w9,w9,w11
+	eor	w25,w23,w21
+	ror	w27,w20,#27
+	add	w23,w23,w28		// future e+=K
+	eor	w9,w9,w17
+	eor	w25,w25,w22
+	add	w24,w24,w27		// e+=rot(a,5)
+	ror	w21,w21,#2
+	eor	w9,w9,w6
+	add	w23,w23,w8	// future e+=X[i]
+	add	w24,w24,w25		// e+=F(b,c,d)
+	ror	w9,w9,#31
+	eor	w10,w10,w12
+	eor	w25,w22,w20
+	ror	w27,w24,#27
+	add	w22,w22,w28		// future e+=K
+	eor	w10,w10,w19
+	eor	w25,w25,w21
+	add	w23,w23,w27		// e+=rot(a,5)
+	ror	w20,w20,#2
+	eor	w10,w10,w7
+	add	w22,w22,w9	// future e+=X[i]
+	add	w23,w23,w25		// e+=F(b,c,d)
+	ror	w10,w10,#31
+	eor	w11,w11,w13
+	eor	w25,w21,w24
+	ror	w27,w23,#27
+	add	w21,w21,w28		// future e+=K
+	eor	w11,w11,w3
+	eor	w25,w25,w20
+	add	w22,w22,w27		// e+=rot(a,5)
+	ror	w24,w24,#2
+	eor	w11,w11,w8
+	add	w21,w21,w10	// future e+=X[i]
+	add	w22,w22,w25		// e+=F(b,c,d)
+	ror	w11,w11,#31
+	eor	w12,w12,w14
+	eor	w25,w20,w23
+	ror	w27,w22,#27
+	add	w20,w20,w28		// future e+=K
+	eor	w12,w12,w4
+	eor	w25,w25,w24
+	add	w21,w21,w27		// e+=rot(a,5)
+	ror	w23,w23,#2
+	eor	w12,w12,w9
+	add	w20,w20,w11	// future e+=X[i]
+	add	w21,w21,w25		// e+=F(b,c,d)
+	ror	w12,w12,#31
+	eor	w13,w13,w15
+	eor	w25,w24,w22
+	ror	w27,w21,#27
+	add	w24,w24,w28		// future e+=K
+	eor	w13,w13,w5
+	eor	w25,w25,w23
+	add	w20,w20,w27		// e+=rot(a,5)
+	ror	w22,w22,#2
+	eor	w13,w13,w10
+	add	w24,w24,w12	// future e+=X[i]
+	add	w20,w20,w25		// e+=F(b,c,d)
+	ror	w13,w13,#31
+	eor	w14,w14,w16
+	eor	w25,w23,w21
+	ror	w27,w20,#27
+	add	w23,w23,w28		// future e+=K
+	eor	w14,w14,w6
+	eor	w25,w25,w22
+	add	w24,w24,w27		// e+=rot(a,5)
+	ror	w21,w21,#2
+	eor	w14,w14,w11
+	add	w23,w23,w13	// future e+=X[i]
+	add	w24,w24,w25		// e+=F(b,c,d)
+	ror	w14,w14,#31
+	eor	w15,w15,w17
+	eor	w25,w22,w20
+	ror	w27,w24,#27
+	add	w22,w22,w28		// future e+=K
+	eor	w15,w15,w7
+	eor	w25,w25,w21
+	add	w23,w23,w27		// e+=rot(a,5)
+	ror	w20,w20,#2
+	eor	w15,w15,w12
+	add	w22,w22,w14	// future e+=X[i]
+	add	w23,w23,w25		// e+=F(b,c,d)
+	ror	w15,w15,#31
+	eor	w16,w16,w19
+	eor	w25,w21,w24
+	ror	w27,w23,#27
+	add	w21,w21,w28		// future e+=K
+	eor	w16,w16,w8
+	eor	w25,w25,w20
+	add	w22,w22,w27		// e+=rot(a,5)
+	ror	w24,w24,#2
+	eor	w16,w16,w13
+	add	w21,w21,w15	// future e+=X[i]
+	add	w22,w22,w25		// e+=F(b,c,d)
+	ror	w16,w16,#31
+	eor	w17,w17,w3
+	eor	w25,w20,w23
+	ror	w27,w22,#27
+	add	w20,w20,w28		// future e+=K
+	eor	w17,w17,w9
+	eor	w25,w25,w24
+	add	w21,w21,w27		// e+=rot(a,5)
+	ror	w23,w23,#2
+	eor	w17,w17,w14
+	add	w20,w20,w16	// future e+=X[i]
+	add	w21,w21,w25		// e+=F(b,c,d)
+	ror	w17,w17,#31
+	eor	w19,w19,w4
+	eor	w25,w24,w22
+	ror	w27,w21,#27
+	add	w24,w24,w28		// future e+=K
+	eor	w19,w19,w10
+	eor	w25,w25,w23
+	add	w20,w20,w27		// e+=rot(a,5)
+	ror	w22,w22,#2
+	eor	w19,w19,w15
+	add	w24,w24,w17	// future e+=X[i]
+	add	w20,w20,w25		// e+=F(b,c,d)
+	ror	w19,w19,#31
+	eor	w3,w3,w5
+	eor	w25,w23,w21
+	ror	w27,w20,#27
+	add	w23,w23,w28		// future e+=K
+	eor	w3,w3,w11
+	eor	w25,w25,w22
+	add	w24,w24,w27		// e+=rot(a,5)
+	ror	w21,w21,#2
+	eor	w3,w3,w16
+	add	w23,w23,w19	// future e+=X[i]
+	add	w24,w24,w25		// e+=F(b,c,d)
+	ror	w3,w3,#31
+	eor	w4,w4,w6
+	eor	w25,w22,w20
+	ror	w27,w24,#27
+	add	w22,w22,w28		// future e+=K
+	eor	w4,w4,w12
+	eor	w25,w25,w21
+	add	w23,w23,w27		// e+=rot(a,5)
+	ror	w20,w20,#2
+	eor	w4,w4,w17
+	add	w22,w22,w3	// future e+=X[i]
+	add	w23,w23,w25		// e+=F(b,c,d)
+	ror	w4,w4,#31
+	eor	w5,w5,w7
+	eor	w25,w21,w24
+	ror	w27,w23,#27
+	add	w21,w21,w28		// future e+=K
+	eor	w5,w5,w13
+	eor	w25,w25,w20
+	add	w22,w22,w27		// e+=rot(a,5)
+	ror	w24,w24,#2
+	eor	w5,w5,w19
+	add	w21,w21,w4	// future e+=X[i]
+	add	w22,w22,w25		// e+=F(b,c,d)
+	ror	w5,w5,#31
+	eor	w6,w6,w8
+	eor	w25,w20,w23
+	ror	w27,w22,#27
+	add	w20,w20,w28		// future e+=K
+	eor	w6,w6,w14
+	eor	w25,w25,w24
+	add	w21,w21,w27		// e+=rot(a,5)
+	ror	w23,w23,#2
+	eor	w6,w6,w3
+	add	w20,w20,w5	// future e+=X[i]
+	add	w21,w21,w25		// e+=F(b,c,d)
+	ror	w6,w6,#31
+	eor	w7,w7,w9
+	eor	w25,w24,w22
+	ror	w27,w21,#27
+	add	w24,w24,w28		// future e+=K
+	eor	w7,w7,w15
+	eor	w25,w25,w23
+	add	w20,w20,w27		// e+=rot(a,5)
+	ror	w22,w22,#2
+	eor	w7,w7,w4
+	add	w24,w24,w6	// future e+=X[i]
+	add	w20,w20,w25		// e+=F(b,c,d)
+	ror	w7,w7,#31
+	eor	w8,w8,w10
+	eor	w25,w23,w21
+	ror	w27,w20,#27
+	add	w23,w23,w28		// future e+=K
+	eor	w8,w8,w16
+	eor	w25,w25,w22
+	add	w24,w24,w27		// e+=rot(a,5)
+	ror	w21,w21,#2
+	eor	w8,w8,w5
+	add	w23,w23,w7	// future e+=X[i]
+	add	w24,w24,w25		// e+=F(b,c,d)
+	ror	w8,w8,#31
+	eor	w9,w9,w11
+	eor	w25,w22,w20
+	ror	w27,w24,#27
+	add	w22,w22,w28		// future e+=K
+	eor	w9,w9,w17
+	eor	w25,w25,w21
+	add	w23,w23,w27		// e+=rot(a,5)
+	ror	w20,w20,#2
+	eor	w9,w9,w6
+	add	w22,w22,w8	// future e+=X[i]
+	add	w23,w23,w25		// e+=F(b,c,d)
+	ror	w9,w9,#31
+	eor	w10,w10,w12
+	eor	w25,w21,w24
+	ror	w27,w23,#27
+	add	w21,w21,w28		// future e+=K
+	eor	w10,w10,w19
+	eor	w25,w25,w20
+	add	w22,w22,w27		// e+=rot(a,5)
+	ror	w24,w24,#2
+	eor	w10,w10,w7
+	add	w21,w21,w9	// future e+=X[i]
+	add	w22,w22,w25		// e+=F(b,c,d)
+	ror	w10,w10,#31
+	eor	w11,w11,w13
+	eor	w25,w20,w23
+	ror	w27,w22,#27
+	add	w20,w20,w28		// future e+=K
+	eor	w11,w11,w3
+	eor	w25,w25,w24
+	add	w21,w21,w27		// e+=rot(a,5)
+	ror	w23,w23,#2
+	eor	w11,w11,w8
+	add	w20,w20,w10	// future e+=X[i]
+	add	w21,w21,w25		// e+=F(b,c,d)
+	ror	w11,w11,#31
+	movz	w28,#0xbcdc
+	movk	w28,#0x8f1b,lsl#16
+	eor	w12,w12,w14
+	eor	w25,w24,w22
+	ror	w27,w21,#27
+	add	w24,w24,w28		// future e+=K
+	eor	w12,w12,w4
+	eor	w25,w25,w23
+	add	w20,w20,w27		// e+=rot(a,5)
+	ror	w22,w22,#2
+	eor	w12,w12,w9
+	add	w24,w24,w11	// future e+=X[i]
+	add	w20,w20,w25		// e+=F(b,c,d)
+	ror	w12,w12,#31
+	orr	w25,w21,w22
+	and	w26,w21,w22
+	eor	w13,w13,w15
+	ror	w27,w20,#27
+	and	w25,w25,w23
+	add	w23,w23,w28		// future e+=K
+	eor	w13,w13,w5
+	add	w24,w24,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w21,w21,#2
+	eor	w13,w13,w10
+	add	w23,w23,w12	// future e+=X[i]
+	add	w24,w24,w25		// e+=F(b,c,d)
+	ror	w13,w13,#31
+	orr	w25,w20,w21
+	and	w26,w20,w21
+	eor	w14,w14,w16
+	ror	w27,w24,#27
+	and	w25,w25,w22
+	add	w22,w22,w28		// future e+=K
+	eor	w14,w14,w6
+	add	w23,w23,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w20,w20,#2
+	eor	w14,w14,w11
+	add	w22,w22,w13	// future e+=X[i]
+	add	w23,w23,w25		// e+=F(b,c,d)
+	ror	w14,w14,#31
+	orr	w25,w24,w20
+	and	w26,w24,w20
+	eor	w15,w15,w17
+	ror	w27,w23,#27
+	and	w25,w25,w21
+	add	w21,w21,w28		// future e+=K
+	eor	w15,w15,w7
+	add	w22,w22,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w24,w24,#2
+	eor	w15,w15,w12
+	add	w21,w21,w14	// future e+=X[i]
+	add	w22,w22,w25		// e+=F(b,c,d)
+	ror	w15,w15,#31
+	orr	w25,w23,w24
+	and	w26,w23,w24
+	eor	w16,w16,w19
+	ror	w27,w22,#27
+	and	w25,w25,w20
+	add	w20,w20,w28		// future e+=K
+	eor	w16,w16,w8
+	add	w21,w21,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w23,w23,#2
+	eor	w16,w16,w13
+	add	w20,w20,w15	// future e+=X[i]
+	add	w21,w21,w25		// e+=F(b,c,d)
+	ror	w16,w16,#31
+	orr	w25,w22,w23
+	and	w26,w22,w23
+	eor	w17,w17,w3
+	ror	w27,w21,#27
+	and	w25,w25,w24
+	add	w24,w24,w28		// future e+=K
+	eor	w17,w17,w9
+	add	w20,w20,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w22,w22,#2
+	eor	w17,w17,w14
+	add	w24,w24,w16	// future e+=X[i]
+	add	w20,w20,w25		// e+=F(b,c,d)
+	ror	w17,w17,#31
+	orr	w25,w21,w22
+	and	w26,w21,w22
+	eor	w19,w19,w4
+	ror	w27,w20,#27
+	and	w25,w25,w23
+	add	w23,w23,w28		// future e+=K
+	eor	w19,w19,w10
+	add	w24,w24,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w21,w21,#2
+	eor	w19,w19,w15
+	add	w23,w23,w17	// future e+=X[i]
+	add	w24,w24,w25		// e+=F(b,c,d)
+	ror	w19,w19,#31
+	orr	w25,w20,w21
+	and	w26,w20,w21
+	eor	w3,w3,w5
+	ror	w27,w24,#27
+	and	w25,w25,w22
+	add	w22,w22,w28		// future e+=K
+	eor	w3,w3,w11
+	add	w23,w23,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w20,w20,#2
+	eor	w3,w3,w16
+	add	w22,w22,w19	// future e+=X[i]
+	add	w23,w23,w25		// e+=F(b,c,d)
+	ror	w3,w3,#31
+	orr	w25,w24,w20
+	and	w26,w24,w20
+	eor	w4,w4,w6
+	ror	w27,w23,#27
+	and	w25,w25,w21
+	add	w21,w21,w28		// future e+=K
+	eor	w4,w4,w12
+	add	w22,w22,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w24,w24,#2
+	eor	w4,w4,w17
+	add	w21,w21,w3	// future e+=X[i]
+	add	w22,w22,w25		// e+=F(b,c,d)
+	ror	w4,w4,#31
+	orr	w25,w23,w24
+	and	w26,w23,w24
+	eor	w5,w5,w7
+	ror	w27,w22,#27
+	and	w25,w25,w20
+	add	w20,w20,w28		// future e+=K
+	eor	w5,w5,w13
+	add	w21,w21,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w23,w23,#2
+	eor	w5,w5,w19
+	add	w20,w20,w4	// future e+=X[i]
+	add	w21,w21,w25		// e+=F(b,c,d)
+	ror	w5,w5,#31
+	orr	w25,w22,w23
+	and	w26,w22,w23
+	eor	w6,w6,w8
+	ror	w27,w21,#27
+	and	w25,w25,w24
+	add	w24,w24,w28		// future e+=K
+	eor	w6,w6,w14
+	add	w20,w20,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w22,w22,#2
+	eor	w6,w6,w3
+	add	w24,w24,w5	// future e+=X[i]
+	add	w20,w20,w25		// e+=F(b,c,d)
+	ror	w6,w6,#31
+	orr	w25,w21,w22
+	and	w26,w21,w22
+	eor	w7,w7,w9
+	ror	w27,w20,#27
+	and	w25,w25,w23
+	add	w23,w23,w28		// future e+=K
+	eor	w7,w7,w15
+	add	w24,w24,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w21,w21,#2
+	eor	w7,w7,w4
+	add	w23,w23,w6	// future e+=X[i]
+	add	w24,w24,w25		// e+=F(b,c,d)
+	ror	w7,w7,#31
+	orr	w25,w20,w21
+	and	w26,w20,w21
+	eor	w8,w8,w10
+	ror	w27,w24,#27
+	and	w25,w25,w22
+	add	w22,w22,w28		// future e+=K
+	eor	w8,w8,w16
+	add	w23,w23,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w20,w20,#2
+	eor	w8,w8,w5
+	add	w22,w22,w7	// future e+=X[i]
+	add	w23,w23,w25		// e+=F(b,c,d)
+	ror	w8,w8,#31
+	orr	w25,w24,w20
+	and	w26,w24,w20
+	eor	w9,w9,w11
+	ror	w27,w23,#27
+	and	w25,w25,w21
+	add	w21,w21,w28		// future e+=K
+	eor	w9,w9,w17
+	add	w22,w22,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w24,w24,#2
+	eor	w9,w9,w6
+	add	w21,w21,w8	// future e+=X[i]
+	add	w22,w22,w25		// e+=F(b,c,d)
+	ror	w9,w9,#31
+	orr	w25,w23,w24
+	and	w26,w23,w24
+	eor	w10,w10,w12
+	ror	w27,w22,#27
+	and	w25,w25,w20
+	add	w20,w20,w28		// future e+=K
+	eor	w10,w10,w19
+	add	w21,w21,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w23,w23,#2
+	eor	w10,w10,w7
+	add	w20,w20,w9	// future e+=X[i]
+	add	w21,w21,w25		// e+=F(b,c,d)
+	ror	w10,w10,#31
+	orr	w25,w22,w23
+	and	w26,w22,w23
+	eor	w11,w11,w13
+	ror	w27,w21,#27
+	and	w25,w25,w24
+	add	w24,w24,w28		// future e+=K
+	eor	w11,w11,w3
+	add	w20,w20,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w22,w22,#2
+	eor	w11,w11,w8
+	add	w24,w24,w10	// future e+=X[i]
+	add	w20,w20,w25		// e+=F(b,c,d)
+	ror	w11,w11,#31
+	orr	w25,w21,w22
+	and	w26,w21,w22
+	eor	w12,w12,w14
+	ror	w27,w20,#27
+	and	w25,w25,w23
+	add	w23,w23,w28		// future e+=K
+	eor	w12,w12,w4
+	add	w24,w24,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w21,w21,#2
+	eor	w12,w12,w9
+	add	w23,w23,w11	// future e+=X[i]
+	add	w24,w24,w25		// e+=F(b,c,d)
+	ror	w12,w12,#31
+	orr	w25,w20,w21
+	and	w26,w20,w21
+	eor	w13,w13,w15
+	ror	w27,w24,#27
+	and	w25,w25,w22
+	add	w22,w22,w28		// future e+=K
+	eor	w13,w13,w5
+	add	w23,w23,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w20,w20,#2
+	eor	w13,w13,w10
+	add	w22,w22,w12	// future e+=X[i]
+	add	w23,w23,w25		// e+=F(b,c,d)
+	ror	w13,w13,#31
+	orr	w25,w24,w20
+	and	w26,w24,w20
+	eor	w14,w14,w16
+	ror	w27,w23,#27
+	and	w25,w25,w21
+	add	w21,w21,w28		// future e+=K
+	eor	w14,w14,w6
+	add	w22,w22,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w24,w24,#2
+	eor	w14,w14,w11
+	add	w21,w21,w13	// future e+=X[i]
+	add	w22,w22,w25		// e+=F(b,c,d)
+	ror	w14,w14,#31
+	orr	w25,w23,w24
+	and	w26,w23,w24
+	eor	w15,w15,w17
+	ror	w27,w22,#27
+	and	w25,w25,w20
+	add	w20,w20,w28		// future e+=K
+	eor	w15,w15,w7
+	add	w21,w21,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w23,w23,#2
+	eor	w15,w15,w12
+	add	w20,w20,w14	// future e+=X[i]
+	add	w21,w21,w25		// e+=F(b,c,d)
+	ror	w15,w15,#31
+	movz	w28,#0xc1d6
+	movk	w28,#0xca62,lsl#16
+	orr	w25,w22,w23
+	and	w26,w22,w23
+	eor	w16,w16,w19
+	ror	w27,w21,#27
+	and	w25,w25,w24
+	add	w24,w24,w28		// future e+=K
+	eor	w16,w16,w8
+	add	w20,w20,w27		// e+=rot(a,5)
+	orr	w25,w25,w26
+	ror	w22,w22,#2
+	eor	w16,w16,w13
+	add	w24,w24,w15	// future e+=X[i]
+	add	w20,w20,w25		// e+=F(b,c,d)
+	ror	w16,w16,#31
+	eor	w17,w17,w3
+	eor	w25,w23,w21
+	ror	w27,w20,#27
+	add	w23,w23,w28		// future e+=K
+	eor	w17,w17,w9
+	eor	w25,w25,w22
+	add	w24,w24,w27		// e+=rot(a,5)
+	ror	w21,w21,#2
+	eor	w17,w17,w14
+	add	w23,w23,w16	// future e+=X[i]
+	add	w24,w24,w25		// e+=F(b,c,d)
+	ror	w17,w17,#31
+	eor	w19,w19,w4
+	eor	w25,w22,w20
+	ror	w27,w24,#27
+	add	w22,w22,w28		// future e+=K
+	eor	w19,w19,w10
+	eor	w25,w25,w21
+	add	w23,w23,w27		// e+=rot(a,5)
+	ror	w20,w20,#2
+	eor	w19,w19,w15
+	add	w22,w22,w17	// future e+=X[i]
+	add	w23,w23,w25		// e+=F(b,c,d)
+	ror	w19,w19,#31
+	eor	w3,w3,w5
+	eor	w25,w21,w24
+	ror	w27,w23,#27
+	add	w21,w21,w28		// future e+=K
+	eor	w3,w3,w11
+	eor	w25,w25,w20
+	add	w22,w22,w27		// e+=rot(a,5)
+	ror	w24,w24,#2
+	eor	w3,w3,w16
+	add	w21,w21,w19	// future e+=X[i]
+	add	w22,w22,w25		// e+=F(b,c,d)
+	ror	w3,w3,#31
+	eor	w4,w4,w6
+	eor	w25,w20,w23
+	ror	w27,w22,#27
+	add	w20,w20,w28		// future e+=K
+	eor	w4,w4,w12
+	eor	w25,w25,w24
+	add	w21,w21,w27		// e+=rot(a,5)
+	ror	w23,w23,#2
+	eor	w4,w4,w17
+	add	w20,w20,w3	// future e+=X[i]
+	add	w21,w21,w25		// e+=F(b,c,d)
+	ror	w4,w4,#31
+	eor	w5,w5,w7
+	eor	w25,w24,w22
+	ror	w27,w21,#27
+	add	w24,w24,w28		// future e+=K
+	eor	w5,w5,w13
+	eor	w25,w25,w23
+	add	w20,w20,w27		// e+=rot(a,5)
+	ror	w22,w22,#2
+	eor	w5,w5,w19
+	add	w24,w24,w4	// future e+=X[i]
+	add	w20,w20,w25		// e+=F(b,c,d)
+	ror	w5,w5,#31
+	eor	w6,w6,w8
+	eor	w25,w23,w21
+	ror	w27,w20,#27
+	add	w23,w23,w28		// future e+=K
+	eor	w6,w6,w14
+	eor	w25,w25,w22
+	add	w24,w24,w27		// e+=rot(a,5)
+	ror	w21,w21,#2
+	eor	w6,w6,w3
+	add	w23,w23,w5	// future e+=X[i]
+	add	w24,w24,w25		// e+=F(b,c,d)
+	ror	w6,w6,#31
+	eor	w7,w7,w9
+	eor	w25,w22,w20
+	ror	w27,w24,#27
+	add	w22,w22,w28		// future e+=K
+	eor	w7,w7,w15
+	eor	w25,w25,w21
+	add	w23,w23,w27		// e+=rot(a,5)
+	ror	w20,w20,#2
+	eor	w7,w7,w4
+	add	w22,w22,w6	// future e+=X[i]
+	add	w23,w23,w25		// e+=F(b,c,d)
+	ror	w7,w7,#31
+	eor	w8,w8,w10
+	eor	w25,w21,w24
+	ror	w27,w23,#27
+	add	w21,w21,w28		// future e+=K
+	eor	w8,w8,w16
+	eor	w25,w25,w20
+	add	w22,w22,w27		// e+=rot(a,5)
+	ror	w24,w24,#2
+	eor	w8,w8,w5
+	add	w21,w21,w7	// future e+=X[i]
+	add	w22,w22,w25		// e+=F(b,c,d)
+	ror	w8,w8,#31
+	eor	w9,w9,w11
+	eor	w25,w20,w23
+	ror	w27,w22,#27
+	add	w20,w20,w28		// future e+=K
+	eor	w9,w9,w17
+	eor	w25,w25,w24
+	add	w21,w21,w27		// e+=rot(a,5)
+	ror	w23,w23,#2
+	eor	w9,w9,w6
+	add	w20,w20,w8	// future e+=X[i]
+	add	w21,w21,w25		// e+=F(b,c,d)
+	ror	w9,w9,#31
+	eor	w10,w10,w12
+	eor	w25,w24,w22
+	ror	w27,w21,#27
+	add	w24,w24,w28		// future e+=K
+	eor	w10,w10,w19
+	eor	w25,w25,w23
+	add	w20,w20,w27		// e+=rot(a,5)
+	ror	w22,w22,#2
+	eor	w10,w10,w7
+	add	w24,w24,w9	// future e+=X[i]
+	add	w20,w20,w25		// e+=F(b,c,d)
+	ror	w10,w10,#31
+	eor	w11,w11,w13
+	eor	w25,w23,w21
+	ror	w27,w20,#27
+	add	w23,w23,w28		// future e+=K
+	eor	w11,w11,w3
+	eor	w25,w25,w22
+	add	w24,w24,w27		// e+=rot(a,5)
+	ror	w21,w21,#2
+	eor	w11,w11,w8
+	add	w23,w23,w10	// future e+=X[i]
+	add	w24,w24,w25		// e+=F(b,c,d)
+	ror	w11,w11,#31
+	eor	w12,w12,w14
+	eor	w25,w22,w20
+	ror	w27,w24,#27
+	add	w22,w22,w28		// future e+=K
+	eor	w12,w12,w4
+	eor	w25,w25,w21
+	add	w23,w23,w27		// e+=rot(a,5)
+	ror	w20,w20,#2
+	eor	w12,w12,w9
+	add	w22,w22,w11	// future e+=X[i]
+	add	w23,w23,w25		// e+=F(b,c,d)
+	ror	w12,w12,#31
+	eor	w13,w13,w15
+	eor	w25,w21,w24
+	ror	w27,w23,#27
+	add	w21,w21,w28		// future e+=K
+	eor	w13,w13,w5
+	eor	w25,w25,w20
+	add	w22,w22,w27		// e+=rot(a,5)
+	ror	w24,w24,#2
+	eor	w13,w13,w10
+	add	w21,w21,w12	// future e+=X[i]
+	add	w22,w22,w25		// e+=F(b,c,d)
+	ror	w13,w13,#31
+	eor	w14,w14,w16
+	eor	w25,w20,w23
+	ror	w27,w22,#27
+	add	w20,w20,w28		// future e+=K
+	eor	w14,w14,w6
+	eor	w25,w25,w24
+	add	w21,w21,w27		// e+=rot(a,5)
+	ror	w23,w23,#2
+	eor	w14,w14,w11
+	add	w20,w20,w13	// future e+=X[i]
+	add	w21,w21,w25		// e+=F(b,c,d)
+	ror	w14,w14,#31
+	eor	w15,w15,w17
+	eor	w25,w24,w22
+	ror	w27,w21,#27
+	add	w24,w24,w28		// future e+=K
+	eor	w15,w15,w7
+	eor	w25,w25,w23
+	add	w20,w20,w27		// e+=rot(a,5)
+	ror	w22,w22,#2
+	eor	w15,w15,w12
+	add	w24,w24,w14	// future e+=X[i]
+	add	w20,w20,w25		// e+=F(b,c,d)
+	ror	w15,w15,#31
+	eor	w16,w16,w19
+	eor	w25,w23,w21
+	ror	w27,w20,#27
+	add	w23,w23,w28		// future e+=K
+	eor	w16,w16,w8
+	eor	w25,w25,w22
+	add	w24,w24,w27		// e+=rot(a,5)
+	ror	w21,w21,#2
+	eor	w16,w16,w13
+	add	w23,w23,w15	// future e+=X[i]
+	add	w24,w24,w25		// e+=F(b,c,d)
+	ror	w16,w16,#31
+	eor	w17,w17,w3
+	eor	w25,w22,w20
+	ror	w27,w24,#27
+	add	w22,w22,w28		// future e+=K
+	eor	w17,w17,w9
+	eor	w25,w25,w21
+	add	w23,w23,w27		// e+=rot(a,5)
+	ror	w20,w20,#2
+	eor	w17,w17,w14
+	add	w22,w22,w16	// future e+=X[i]
+	add	w23,w23,w25		// e+=F(b,c,d)
+	ror	w17,w17,#31
+	eor	w19,w19,w4
+	eor	w25,w21,w24
+	ror	w27,w23,#27
+	add	w21,w21,w28		// future e+=K
+	eor	w19,w19,w10
+	eor	w25,w25,w20
+	add	w22,w22,w27		// e+=rot(a,5)
+	ror	w24,w24,#2
+	eor	w19,w19,w15
+	add	w21,w21,w17	// future e+=X[i]
+	add	w22,w22,w25		// e+=F(b,c,d)
+	ror	w19,w19,#31
+	ldp	w4,w5,[x0]
+	eor	w25,w20,w23
+	ror	w27,w22,#27
+	add	w20,w20,w28		// future e+=K
+	eor	w25,w25,w24
+	add	w21,w21,w27		// e+=rot(a,5)
+	ror	w23,w23,#2
+	add	w20,w20,w19	// future e+=X[i]
+	add	w21,w21,w25		// e+=F(b,c,d)
+	ldp	w6,w7,[x0,#8]
+	eor	w25,w24,w22
+	ror	w27,w21,#27
+	eor	w25,w25,w23
+	add	w20,w20,w27		// e+=rot(a,5)
+	ror	w22,w22,#2
+	ldr	w8,[x0,#16]
+	add	w20,w20,w25		// e+=F(b,c,d)
+	add	w21,w21,w5
+	add	w22,w22,w6
+	add	w20,w20,w4
+	add	w23,w23,w7
+	add	w24,w24,w8
+	stp	w20,w21,[x0]
+	stp	w22,w23,[x0,#8]
+	str	w24,[x0,#16]
+	cbnz	x2,Loop
+
+	ldp	x19,x20,[sp,#16]
+	ldp	x21,x22,[sp,#32]
+	ldp	x23,x24,[sp,#48]
+	ldp	x25,x26,[sp,#64]
+	ldp	x27,x28,[sp,#80]
+	ldr	x29,[sp],#96
+	ret
+
+
+.align	6
+sha1_block_armv8:
+Lv8_entry:
+	stp	x29,x30,[sp,#-16]!
+	add	x29,sp,#0
+
+	adr	x4,Lconst
+	eor	v1.16b,v1.16b,v1.16b
+	ld1	{v0.4s},[x0],#16
+	ld1	{v1.s}[0],[x0]
+	sub	x0,x0,#16
+	ld1	{v16.4s,v17.4s,v18.4s,v19.4s},[x4]
+
+Loop_hw:
+	ld1	{v4.16b,v5.16b,v6.16b,v7.16b},[x1],#64
+	sub	x2,x2,#1
+	rev32	v4.16b,v4.16b
+	rev32	v5.16b,v5.16b
+
+	add	v20.4s,v16.4s,v4.4s
+	rev32	v6.16b,v6.16b
+	orr	v22.16b,v0.16b,v0.16b	// offload
+
+	add	v21.4s,v16.4s,v5.4s
+	rev32	v7.16b,v7.16b
+.long	0x5e280803	//sha1h v3.16b,v0.16b
+.long	0x5e140020	//sha1c v0.16b,v1.16b,v20.4s		// 0
+	add	v20.4s,v16.4s,v6.4s
+.long	0x5e0630a4	//sha1su0 v4.16b,v5.16b,v6.16b
+.long	0x5e280802	//sha1h v2.16b,v0.16b		// 1
+.long	0x5e150060	//sha1c v0.16b,v3.16b,v21.4s
+	add	v21.4s,v16.4s,v7.4s
+.long	0x5e2818e4	//sha1su1 v4.16b,v7.16b
+.long	0x5e0730c5	//sha1su0 v5.16b,v6.16b,v7.16b
+.long	0x5e280803	//sha1h v3.16b,v0.16b		// 2
+.long	0x5e140040	//sha1c v0.16b,v2.16b,v20.4s
+	add	v20.4s,v16.4s,v4.4s
+.long	0x5e281885	//sha1su1 v5.16b,v4.16b
+.long	0x5e0430e6	//sha1su0 v6.16b,v7.16b,v4.16b
+.long	0x5e280802	//sha1h v2.16b,v0.16b		// 3
+.long	0x5e150060	//sha1c v0.16b,v3.16b,v21.4s
+	add	v21.4s,v17.4s,v5.4s
+.long	0x5e2818a6	//sha1su1 v6.16b,v5.16b
+.long	0x5e053087	//sha1su0 v7.16b,v4.16b,v5.16b
+.long	0x5e280803	//sha1h v3.16b,v0.16b		// 4
+.long	0x5e140040	//sha1c v0.16b,v2.16b,v20.4s
+	add	v20.4s,v17.4s,v6.4s
+.long	0x5e2818c7	//sha1su1 v7.16b,v6.16b
+.long	0x5e0630a4	//sha1su0 v4.16b,v5.16b,v6.16b
+.long	0x5e280802	//sha1h v2.16b,v0.16b		// 5
+.long	0x5e151060	//sha1p v0.16b,v3.16b,v21.4s
+	add	v21.4s,v17.4s,v7.4s
+.long	0x5e2818e4	//sha1su1 v4.16b,v7.16b
+.long	0x5e0730c5	//sha1su0 v5.16b,v6.16b,v7.16b
+.long	0x5e280803	//sha1h v3.16b,v0.16b		// 6
+.long	0x5e141040	//sha1p v0.16b,v2.16b,v20.4s
+	add	v20.4s,v17.4s,v4.4s
+.long	0x5e281885	//sha1su1 v5.16b,v4.16b
+.long	0x5e0430e6	//sha1su0 v6.16b,v7.16b,v4.16b
+.long	0x5e280802	//sha1h v2.16b,v0.16b		// 7
+.long	0x5e151060	//sha1p v0.16b,v3.16b,v21.4s
+	add	v21.4s,v17.4s,v5.4s
+.long	0x5e2818a6	//sha1su1 v6.16b,v5.16b
+.long	0x5e053087	//sha1su0 v7.16b,v4.16b,v5.16b
+.long	0x5e280803	//sha1h v3.16b,v0.16b		// 8
+.long	0x5e141040	//sha1p v0.16b,v2.16b,v20.4s
+	add	v20.4s,v18.4s,v6.4s
+.long	0x5e2818c7	//sha1su1 v7.16b,v6.16b
+.long	0x5e0630a4	//sha1su0 v4.16b,v5.16b,v6.16b
+.long	0x5e280802	//sha1h v2.16b,v0.16b		// 9
+.long	0x5e151060	//sha1p v0.16b,v3.16b,v21.4s
+	add	v21.4s,v18.4s,v7.4s
+.long	0x5e2818e4	//sha1su1 v4.16b,v7.16b
+.long	0x5e0730c5	//sha1su0 v5.16b,v6.16b,v7.16b
+.long	0x5e280803	//sha1h v3.16b,v0.16b		// 10
+.long	0x5e142040	//sha1m v0.16b,v2.16b,v20.4s
+	add	v20.4s,v18.4s,v4.4s
+.long	0x5e281885	//sha1su1 v5.16b,v4.16b
+.long	0x5e0430e6	//sha1su0 v6.16b,v7.16b,v4.16b
+.long	0x5e280802	//sha1h v2.16b,v0.16b		// 11
+.long	0x5e152060	//sha1m v0.16b,v3.16b,v21.4s
+	add	v21.4s,v18.4s,v5.4s
+.long	0x5e2818a6	//sha1su1 v6.16b,v5.16b
+.long	0x5e053087	//sha1su0 v7.16b,v4.16b,v5.16b
+.long	0x5e280803	//sha1h v3.16b,v0.16b		// 12
+.long	0x5e142040	//sha1m v0.16b,v2.16b,v20.4s
+	add	v20.4s,v18.4s,v6.4s
+.long	0x5e2818c7	//sha1su1 v7.16b,v6.16b
+.long	0x5e0630a4	//sha1su0 v4.16b,v5.16b,v6.16b
+.long	0x5e280802	//sha1h v2.16b,v0.16b		// 13
+.long	0x5e152060	//sha1m v0.16b,v3.16b,v21.4s
+	add	v21.4s,v19.4s,v7.4s
+.long	0x5e2818e4	//sha1su1 v4.16b,v7.16b
+.long	0x5e0730c5	//sha1su0 v5.16b,v6.16b,v7.16b
+.long	0x5e280803	//sha1h v3.16b,v0.16b		// 14
+.long	0x5e142040	//sha1m v0.16b,v2.16b,v20.4s
+	add	v20.4s,v19.4s,v4.4s
+.long	0x5e281885	//sha1su1 v5.16b,v4.16b
+.long	0x5e0430e6	//sha1su0 v6.16b,v7.16b,v4.16b
+.long	0x5e280802	//sha1h v2.16b,v0.16b		// 15
+.long	0x5e151060	//sha1p v0.16b,v3.16b,v21.4s
+	add	v21.4s,v19.4s,v5.4s
+.long	0x5e2818a6	//sha1su1 v6.16b,v5.16b
+.long	0x5e053087	//sha1su0 v7.16b,v4.16b,v5.16b
+.long	0x5e280803	//sha1h v3.16b,v0.16b		// 16
+.long	0x5e141040	//sha1p v0.16b,v2.16b,v20.4s
+	add	v20.4s,v19.4s,v6.4s
+.long	0x5e2818c7	//sha1su1 v7.16b,v6.16b
+.long	0x5e280802	//sha1h v2.16b,v0.16b		// 17
+.long	0x5e151060	//sha1p v0.16b,v3.16b,v21.4s
+	add	v21.4s,v19.4s,v7.4s
+
+.long	0x5e280803	//sha1h v3.16b,v0.16b		// 18
+.long	0x5e141040	//sha1p v0.16b,v2.16b,v20.4s
+
+.long	0x5e280802	//sha1h v2.16b,v0.16b		// 19
+.long	0x5e151060	//sha1p v0.16b,v3.16b,v21.4s
+
+	add	v1.4s,v1.4s,v2.4s
+	add	v0.4s,v0.4s,v22.4s
+
+	cbnz	x2,Loop_hw
+
+	st1	{v0.4s},[x0],#16
+	st1	{v1.s}[0],[x0]
+
+	ldr	x29,[sp],#16
+	ret
+
+.align	6
+Lconst:
+.long	0x5a827999,0x5a827999,0x5a827999,0x5a827999	//K_00_19
+.long	0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1	//K_20_39
+.long	0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc	//K_40_59
+.long	0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6	//K_60_79
+LOPENSSL_armcap_P:
+.quad	_OPENSSL_armcap_P-.
+.byte	83,72,65,49,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+.align	2
+.comm	_OPENSSL_armcap_P,4,4
diff --git a/third_party/boringssl/ios-aarch64/crypto/fipsmodule/sha256-armv8.S b/third_party/boringssl/ios-aarch64/crypto/fipsmodule/sha256-armv8.S
new file mode 100644
index 0000000..e70d6ba
--- /dev/null
+++ b/third_party/boringssl/ios-aarch64/crypto/fipsmodule/sha256-armv8.S
@@ -0,0 +1,1144 @@
+#include <openssl/arm_arch.h>
+
+.text
+
+
+.globl	_sha256_block_data_order
+.private_extern	_sha256_block_data_order
+
+.align	6
+_sha256_block_data_order:
+	ldr	x16,LOPENSSL_armcap_P
+	adr	x17,LOPENSSL_armcap_P
+	add	x16,x16,x17
+	ldr	w16,[x16]
+	tst	w16,#ARMV8_SHA256
+	b.ne	Lv8_entry
+	stp	x29,x30,[sp,#-128]!
+	add	x29,sp,#0
+
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+	sub	sp,sp,#4*4
+
+	ldp	w20,w21,[x0]				// load context
+	ldp	w22,w23,[x0,#2*4]
+	ldp	w24,w25,[x0,#4*4]
+	add	x2,x1,x2,lsl#6	// end of input
+	ldp	w26,w27,[x0,#6*4]
+	adr	x30,LK256
+	stp	x0,x2,[x29,#96]
+
+Loop:
+	ldp	w3,w4,[x1],#2*4
+	ldr	w19,[x30],#4			// *K++
+	eor	w28,w21,w22				// magic seed
+	str	x1,[x29,#112]
+#ifndef	__ARMEB__
+	rev	w3,w3			// 0
+#endif
+	ror	w16,w24,#6
+	add	w27,w27,w19			// h+=K[i]
+	eor	w6,w24,w24,ror#14
+	and	w17,w25,w24
+	bic	w19,w26,w24
+	add	w27,w27,w3			// h+=X[i]
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w20,w21			// a^b, b^c in next round
+	eor	w16,w16,w6,ror#11	// Sigma1(e)
+	ror	w6,w20,#2
+	add	w27,w27,w17			// h+=Ch(e,f,g)
+	eor	w17,w20,w20,ror#9
+	add	w27,w27,w16			// h+=Sigma1(e)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	add	w23,w23,w27			// d+=h
+	eor	w28,w28,w21			// Maj(a,b,c)
+	eor	w17,w6,w17,ror#13	// Sigma0(a)
+	add	w27,w27,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	//add	w27,w27,w17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	w4,w4			// 1
+#endif
+	ldp	w5,w6,[x1],#2*4
+	add	w27,w27,w17			// h+=Sigma0(a)
+	ror	w16,w23,#6
+	add	w26,w26,w28			// h+=K[i]
+	eor	w7,w23,w23,ror#14
+	and	w17,w24,w23
+	bic	w28,w25,w23
+	add	w26,w26,w4			// h+=X[i]
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w27,w20			// a^b, b^c in next round
+	eor	w16,w16,w7,ror#11	// Sigma1(e)
+	ror	w7,w27,#2
+	add	w26,w26,w17			// h+=Ch(e,f,g)
+	eor	w17,w27,w27,ror#9
+	add	w26,w26,w16			// h+=Sigma1(e)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	add	w22,w22,w26			// d+=h
+	eor	w19,w19,w20			// Maj(a,b,c)
+	eor	w17,w7,w17,ror#13	// Sigma0(a)
+	add	w26,w26,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	//add	w26,w26,w17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	w5,w5			// 2
+#endif
+	add	w26,w26,w17			// h+=Sigma0(a)
+	ror	w16,w22,#6
+	add	w25,w25,w19			// h+=K[i]
+	eor	w8,w22,w22,ror#14
+	and	w17,w23,w22
+	bic	w19,w24,w22
+	add	w25,w25,w5			// h+=X[i]
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w26,w27			// a^b, b^c in next round
+	eor	w16,w16,w8,ror#11	// Sigma1(e)
+	ror	w8,w26,#2
+	add	w25,w25,w17			// h+=Ch(e,f,g)
+	eor	w17,w26,w26,ror#9
+	add	w25,w25,w16			// h+=Sigma1(e)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	add	w21,w21,w25			// d+=h
+	eor	w28,w28,w27			// Maj(a,b,c)
+	eor	w17,w8,w17,ror#13	// Sigma0(a)
+	add	w25,w25,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	//add	w25,w25,w17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	w6,w6			// 3
+#endif
+	ldp	w7,w8,[x1],#2*4
+	add	w25,w25,w17			// h+=Sigma0(a)
+	ror	w16,w21,#6
+	add	w24,w24,w28			// h+=K[i]
+	eor	w9,w21,w21,ror#14
+	and	w17,w22,w21
+	bic	w28,w23,w21
+	add	w24,w24,w6			// h+=X[i]
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w25,w26			// a^b, b^c in next round
+	eor	w16,w16,w9,ror#11	// Sigma1(e)
+	ror	w9,w25,#2
+	add	w24,w24,w17			// h+=Ch(e,f,g)
+	eor	w17,w25,w25,ror#9
+	add	w24,w24,w16			// h+=Sigma1(e)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	add	w20,w20,w24			// d+=h
+	eor	w19,w19,w26			// Maj(a,b,c)
+	eor	w17,w9,w17,ror#13	// Sigma0(a)
+	add	w24,w24,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	//add	w24,w24,w17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	w7,w7			// 4
+#endif
+	add	w24,w24,w17			// h+=Sigma0(a)
+	ror	w16,w20,#6
+	add	w23,w23,w19			// h+=K[i]
+	eor	w10,w20,w20,ror#14
+	and	w17,w21,w20
+	bic	w19,w22,w20
+	add	w23,w23,w7			// h+=X[i]
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w24,w25			// a^b, b^c in next round
+	eor	w16,w16,w10,ror#11	// Sigma1(e)
+	ror	w10,w24,#2
+	add	w23,w23,w17			// h+=Ch(e,f,g)
+	eor	w17,w24,w24,ror#9
+	add	w23,w23,w16			// h+=Sigma1(e)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	add	w27,w27,w23			// d+=h
+	eor	w28,w28,w25			// Maj(a,b,c)
+	eor	w17,w10,w17,ror#13	// Sigma0(a)
+	add	w23,w23,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	//add	w23,w23,w17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	w8,w8			// 5
+#endif
+	ldp	w9,w10,[x1],#2*4
+	add	w23,w23,w17			// h+=Sigma0(a)
+	ror	w16,w27,#6
+	add	w22,w22,w28			// h+=K[i]
+	eor	w11,w27,w27,ror#14
+	and	w17,w20,w27
+	bic	w28,w21,w27
+	add	w22,w22,w8			// h+=X[i]
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w23,w24			// a^b, b^c in next round
+	eor	w16,w16,w11,ror#11	// Sigma1(e)
+	ror	w11,w23,#2
+	add	w22,w22,w17			// h+=Ch(e,f,g)
+	eor	w17,w23,w23,ror#9
+	add	w22,w22,w16			// h+=Sigma1(e)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	add	w26,w26,w22			// d+=h
+	eor	w19,w19,w24			// Maj(a,b,c)
+	eor	w17,w11,w17,ror#13	// Sigma0(a)
+	add	w22,w22,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	//add	w22,w22,w17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	w9,w9			// 6
+#endif
+	add	w22,w22,w17			// h+=Sigma0(a)
+	ror	w16,w26,#6
+	add	w21,w21,w19			// h+=K[i]
+	eor	w12,w26,w26,ror#14
+	and	w17,w27,w26
+	bic	w19,w20,w26
+	add	w21,w21,w9			// h+=X[i]
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w22,w23			// a^b, b^c in next round
+	eor	w16,w16,w12,ror#11	// Sigma1(e)
+	ror	w12,w22,#2
+	add	w21,w21,w17			// h+=Ch(e,f,g)
+	eor	w17,w22,w22,ror#9
+	add	w21,w21,w16			// h+=Sigma1(e)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	add	w25,w25,w21			// d+=h
+	eor	w28,w28,w23			// Maj(a,b,c)
+	eor	w17,w12,w17,ror#13	// Sigma0(a)
+	add	w21,w21,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	//add	w21,w21,w17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	w10,w10			// 7
+#endif
+	ldp	w11,w12,[x1],#2*4
+	add	w21,w21,w17			// h+=Sigma0(a)
+	ror	w16,w25,#6
+	add	w20,w20,w28			// h+=K[i]
+	eor	w13,w25,w25,ror#14
+	and	w17,w26,w25
+	bic	w28,w27,w25
+	add	w20,w20,w10			// h+=X[i]
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w21,w22			// a^b, b^c in next round
+	eor	w16,w16,w13,ror#11	// Sigma1(e)
+	ror	w13,w21,#2
+	add	w20,w20,w17			// h+=Ch(e,f,g)
+	eor	w17,w21,w21,ror#9
+	add	w20,w20,w16			// h+=Sigma1(e)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	add	w24,w24,w20			// d+=h
+	eor	w19,w19,w22			// Maj(a,b,c)
+	eor	w17,w13,w17,ror#13	// Sigma0(a)
+	add	w20,w20,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	//add	w20,w20,w17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	w11,w11			// 8
+#endif
+	add	w20,w20,w17			// h+=Sigma0(a)
+	ror	w16,w24,#6
+	add	w27,w27,w19			// h+=K[i]
+	eor	w14,w24,w24,ror#14
+	and	w17,w25,w24
+	bic	w19,w26,w24
+	add	w27,w27,w11			// h+=X[i]
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w20,w21			// a^b, b^c in next round
+	eor	w16,w16,w14,ror#11	// Sigma1(e)
+	ror	w14,w20,#2
+	add	w27,w27,w17			// h+=Ch(e,f,g)
+	eor	w17,w20,w20,ror#9
+	add	w27,w27,w16			// h+=Sigma1(e)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	add	w23,w23,w27			// d+=h
+	eor	w28,w28,w21			// Maj(a,b,c)
+	eor	w17,w14,w17,ror#13	// Sigma0(a)
+	add	w27,w27,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	//add	w27,w27,w17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	w12,w12			// 9
+#endif
+	ldp	w13,w14,[x1],#2*4
+	add	w27,w27,w17			// h+=Sigma0(a)
+	ror	w16,w23,#6
+	add	w26,w26,w28			// h+=K[i]
+	eor	w15,w23,w23,ror#14
+	and	w17,w24,w23
+	bic	w28,w25,w23
+	add	w26,w26,w12			// h+=X[i]
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w27,w20			// a^b, b^c in next round
+	eor	w16,w16,w15,ror#11	// Sigma1(e)
+	ror	w15,w27,#2
+	add	w26,w26,w17			// h+=Ch(e,f,g)
+	eor	w17,w27,w27,ror#9
+	add	w26,w26,w16			// h+=Sigma1(e)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	add	w22,w22,w26			// d+=h
+	eor	w19,w19,w20			// Maj(a,b,c)
+	eor	w17,w15,w17,ror#13	// Sigma0(a)
+	add	w26,w26,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	//add	w26,w26,w17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	w13,w13			// 10
+#endif
+	add	w26,w26,w17			// h+=Sigma0(a)
+	ror	w16,w22,#6
+	add	w25,w25,w19			// h+=K[i]
+	eor	w0,w22,w22,ror#14
+	and	w17,w23,w22
+	bic	w19,w24,w22
+	add	w25,w25,w13			// h+=X[i]
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w26,w27			// a^b, b^c in next round
+	eor	w16,w16,w0,ror#11	// Sigma1(e)
+	ror	w0,w26,#2
+	add	w25,w25,w17			// h+=Ch(e,f,g)
+	eor	w17,w26,w26,ror#9
+	add	w25,w25,w16			// h+=Sigma1(e)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	add	w21,w21,w25			// d+=h
+	eor	w28,w28,w27			// Maj(a,b,c)
+	eor	w17,w0,w17,ror#13	// Sigma0(a)
+	add	w25,w25,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	//add	w25,w25,w17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	w14,w14			// 11
+#endif
+	ldp	w15,w0,[x1],#2*4
+	add	w25,w25,w17			// h+=Sigma0(a)
+	str	w6,[sp,#12]
+	ror	w16,w21,#6
+	add	w24,w24,w28			// h+=K[i]
+	eor	w6,w21,w21,ror#14
+	and	w17,w22,w21
+	bic	w28,w23,w21
+	add	w24,w24,w14			// h+=X[i]
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w25,w26			// a^b, b^c in next round
+	eor	w16,w16,w6,ror#11	// Sigma1(e)
+	ror	w6,w25,#2
+	add	w24,w24,w17			// h+=Ch(e,f,g)
+	eor	w17,w25,w25,ror#9
+	add	w24,w24,w16			// h+=Sigma1(e)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	add	w20,w20,w24			// d+=h
+	eor	w19,w19,w26			// Maj(a,b,c)
+	eor	w17,w6,w17,ror#13	// Sigma0(a)
+	add	w24,w24,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	//add	w24,w24,w17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	w15,w15			// 12
+#endif
+	add	w24,w24,w17			// h+=Sigma0(a)
+	str	w7,[sp,#0]
+	ror	w16,w20,#6
+	add	w23,w23,w19			// h+=K[i]
+	eor	w7,w20,w20,ror#14
+	and	w17,w21,w20
+	bic	w19,w22,w20
+	add	w23,w23,w15			// h+=X[i]
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w24,w25			// a^b, b^c in next round
+	eor	w16,w16,w7,ror#11	// Sigma1(e)
+	ror	w7,w24,#2
+	add	w23,w23,w17			// h+=Ch(e,f,g)
+	eor	w17,w24,w24,ror#9
+	add	w23,w23,w16			// h+=Sigma1(e)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	add	w27,w27,w23			// d+=h
+	eor	w28,w28,w25			// Maj(a,b,c)
+	eor	w17,w7,w17,ror#13	// Sigma0(a)
+	add	w23,w23,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	//add	w23,w23,w17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	w0,w0			// 13
+#endif
+	ldp	w1,w2,[x1]
+	add	w23,w23,w17			// h+=Sigma0(a)
+	str	w8,[sp,#4]
+	ror	w16,w27,#6
+	add	w22,w22,w28			// h+=K[i]
+	eor	w8,w27,w27,ror#14
+	and	w17,w20,w27
+	bic	w28,w21,w27
+	add	w22,w22,w0			// h+=X[i]
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w23,w24			// a^b, b^c in next round
+	eor	w16,w16,w8,ror#11	// Sigma1(e)
+	ror	w8,w23,#2
+	add	w22,w22,w17			// h+=Ch(e,f,g)
+	eor	w17,w23,w23,ror#9
+	add	w22,w22,w16			// h+=Sigma1(e)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	add	w26,w26,w22			// d+=h
+	eor	w19,w19,w24			// Maj(a,b,c)
+	eor	w17,w8,w17,ror#13	// Sigma0(a)
+	add	w22,w22,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	//add	w22,w22,w17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	w1,w1			// 14
+#endif
+	ldr	w6,[sp,#12]
+	add	w22,w22,w17			// h+=Sigma0(a)
+	str	w9,[sp,#8]
+	ror	w16,w26,#6
+	add	w21,w21,w19			// h+=K[i]
+	eor	w9,w26,w26,ror#14
+	and	w17,w27,w26
+	bic	w19,w20,w26
+	add	w21,w21,w1			// h+=X[i]
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w22,w23			// a^b, b^c in next round
+	eor	w16,w16,w9,ror#11	// Sigma1(e)
+	ror	w9,w22,#2
+	add	w21,w21,w17			// h+=Ch(e,f,g)
+	eor	w17,w22,w22,ror#9
+	add	w21,w21,w16			// h+=Sigma1(e)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	add	w25,w25,w21			// d+=h
+	eor	w28,w28,w23			// Maj(a,b,c)
+	eor	w17,w9,w17,ror#13	// Sigma0(a)
+	add	w21,w21,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	//add	w21,w21,w17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	w2,w2			// 15
+#endif
+	ldr	w7,[sp,#0]
+	add	w21,w21,w17			// h+=Sigma0(a)
+	str	w10,[sp,#12]
+	ror	w16,w25,#6
+	add	w20,w20,w28			// h+=K[i]
+	ror	w9,w4,#7
+	and	w17,w26,w25
+	ror	w8,w1,#17
+	bic	w28,w27,w25
+	ror	w10,w21,#2
+	add	w20,w20,w2			// h+=X[i]
+	eor	w16,w16,w25,ror#11
+	eor	w9,w9,w4,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w21,w22			// a^b, b^c in next round
+	eor	w16,w16,w25,ror#25	// Sigma1(e)
+	eor	w10,w10,w21,ror#13
+	add	w20,w20,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w8,w8,w1,ror#19
+	eor	w9,w9,w4,lsr#3	// sigma0(X[i+1])
+	add	w20,w20,w16			// h+=Sigma1(e)
+	eor	w19,w19,w22			// Maj(a,b,c)
+	eor	w17,w10,w21,ror#22	// Sigma0(a)
+	eor	w8,w8,w1,lsr#10	// sigma1(X[i+14])
+	add	w3,w3,w12
+	add	w24,w24,w20			// d+=h
+	add	w20,w20,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w3,w3,w9
+	add	w20,w20,w17			// h+=Sigma0(a)
+	add	w3,w3,w8
+Loop_16_xx:
+	ldr	w8,[sp,#4]
+	str	w11,[sp,#0]
+	ror	w16,w24,#6
+	add	w27,w27,w19			// h+=K[i]
+	ror	w10,w5,#7
+	and	w17,w25,w24
+	ror	w9,w2,#17
+	bic	w19,w26,w24
+	ror	w11,w20,#2
+	add	w27,w27,w3			// h+=X[i]
+	eor	w16,w16,w24,ror#11
+	eor	w10,w10,w5,ror#18
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w20,w21			// a^b, b^c in next round
+	eor	w16,w16,w24,ror#25	// Sigma1(e)
+	eor	w11,w11,w20,ror#13
+	add	w27,w27,w17			// h+=Ch(e,f,g)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	eor	w9,w9,w2,ror#19
+	eor	w10,w10,w5,lsr#3	// sigma0(X[i+1])
+	add	w27,w27,w16			// h+=Sigma1(e)
+	eor	w28,w28,w21			// Maj(a,b,c)
+	eor	w17,w11,w20,ror#22	// Sigma0(a)
+	eor	w9,w9,w2,lsr#10	// sigma1(X[i+14])
+	add	w4,w4,w13
+	add	w23,w23,w27			// d+=h
+	add	w27,w27,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	add	w4,w4,w10
+	add	w27,w27,w17			// h+=Sigma0(a)
+	add	w4,w4,w9
+	ldr	w9,[sp,#8]
+	str	w12,[sp,#4]
+	ror	w16,w23,#6
+	add	w26,w26,w28			// h+=K[i]
+	ror	w11,w6,#7
+	and	w17,w24,w23
+	ror	w10,w3,#17
+	bic	w28,w25,w23
+	ror	w12,w27,#2
+	add	w26,w26,w4			// h+=X[i]
+	eor	w16,w16,w23,ror#11
+	eor	w11,w11,w6,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w27,w20			// a^b, b^c in next round
+	eor	w16,w16,w23,ror#25	// Sigma1(e)
+	eor	w12,w12,w27,ror#13
+	add	w26,w26,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w10,w10,w3,ror#19
+	eor	w11,w11,w6,lsr#3	// sigma0(X[i+1])
+	add	w26,w26,w16			// h+=Sigma1(e)
+	eor	w19,w19,w20			// Maj(a,b,c)
+	eor	w17,w12,w27,ror#22	// Sigma0(a)
+	eor	w10,w10,w3,lsr#10	// sigma1(X[i+14])
+	add	w5,w5,w14
+	add	w22,w22,w26			// d+=h
+	add	w26,w26,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w5,w5,w11
+	add	w26,w26,w17			// h+=Sigma0(a)
+	add	w5,w5,w10
+	ldr	w10,[sp,#12]
+	str	w13,[sp,#8]
+	ror	w16,w22,#6
+	add	w25,w25,w19			// h+=K[i]
+	ror	w12,w7,#7
+	and	w17,w23,w22
+	ror	w11,w4,#17
+	bic	w19,w24,w22
+	ror	w13,w26,#2
+	add	w25,w25,w5			// h+=X[i]
+	eor	w16,w16,w22,ror#11
+	eor	w12,w12,w7,ror#18
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w26,w27			// a^b, b^c in next round
+	eor	w16,w16,w22,ror#25	// Sigma1(e)
+	eor	w13,w13,w26,ror#13
+	add	w25,w25,w17			// h+=Ch(e,f,g)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	eor	w11,w11,w4,ror#19
+	eor	w12,w12,w7,lsr#3	// sigma0(X[i+1])
+	add	w25,w25,w16			// h+=Sigma1(e)
+	eor	w28,w28,w27			// Maj(a,b,c)
+	eor	w17,w13,w26,ror#22	// Sigma0(a)
+	eor	w11,w11,w4,lsr#10	// sigma1(X[i+14])
+	add	w6,w6,w15
+	add	w21,w21,w25			// d+=h
+	add	w25,w25,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	add	w6,w6,w12
+	add	w25,w25,w17			// h+=Sigma0(a)
+	add	w6,w6,w11
+	ldr	w11,[sp,#0]
+	str	w14,[sp,#12]
+	ror	w16,w21,#6
+	add	w24,w24,w28			// h+=K[i]
+	ror	w13,w8,#7
+	and	w17,w22,w21
+	ror	w12,w5,#17
+	bic	w28,w23,w21
+	ror	w14,w25,#2
+	add	w24,w24,w6			// h+=X[i]
+	eor	w16,w16,w21,ror#11
+	eor	w13,w13,w8,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w25,w26			// a^b, b^c in next round
+	eor	w16,w16,w21,ror#25	// Sigma1(e)
+	eor	w14,w14,w25,ror#13
+	add	w24,w24,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w12,w12,w5,ror#19
+	eor	w13,w13,w8,lsr#3	// sigma0(X[i+1])
+	add	w24,w24,w16			// h+=Sigma1(e)
+	eor	w19,w19,w26			// Maj(a,b,c)
+	eor	w17,w14,w25,ror#22	// Sigma0(a)
+	eor	w12,w12,w5,lsr#10	// sigma1(X[i+14])
+	add	w7,w7,w0
+	add	w20,w20,w24			// d+=h
+	add	w24,w24,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w7,w7,w13
+	add	w24,w24,w17			// h+=Sigma0(a)
+	add	w7,w7,w12
+	ldr	w12,[sp,#4]
+	str	w15,[sp,#0]
+	ror	w16,w20,#6
+	add	w23,w23,w19			// h+=K[i]
+	ror	w14,w9,#7
+	and	w17,w21,w20
+	ror	w13,w6,#17
+	bic	w19,w22,w20
+	ror	w15,w24,#2
+	add	w23,w23,w7			// h+=X[i]
+	eor	w16,w16,w20,ror#11
+	eor	w14,w14,w9,ror#18
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w24,w25			// a^b, b^c in next round
+	eor	w16,w16,w20,ror#25	// Sigma1(e)
+	eor	w15,w15,w24,ror#13
+	add	w23,w23,w17			// h+=Ch(e,f,g)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	eor	w13,w13,w6,ror#19
+	eor	w14,w14,w9,lsr#3	// sigma0(X[i+1])
+	add	w23,w23,w16			// h+=Sigma1(e)
+	eor	w28,w28,w25			// Maj(a,b,c)
+	eor	w17,w15,w24,ror#22	// Sigma0(a)
+	eor	w13,w13,w6,lsr#10	// sigma1(X[i+14])
+	add	w8,w8,w1
+	add	w27,w27,w23			// d+=h
+	add	w23,w23,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	add	w8,w8,w14
+	add	w23,w23,w17			// h+=Sigma0(a)
+	add	w8,w8,w13
+	ldr	w13,[sp,#8]
+	str	w0,[sp,#4]
+	ror	w16,w27,#6
+	add	w22,w22,w28			// h+=K[i]
+	ror	w15,w10,#7
+	and	w17,w20,w27
+	ror	w14,w7,#17
+	bic	w28,w21,w27
+	ror	w0,w23,#2
+	add	w22,w22,w8			// h+=X[i]
+	eor	w16,w16,w27,ror#11
+	eor	w15,w15,w10,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w23,w24			// a^b, b^c in next round
+	eor	w16,w16,w27,ror#25	// Sigma1(e)
+	eor	w0,w0,w23,ror#13
+	add	w22,w22,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w14,w14,w7,ror#19
+	eor	w15,w15,w10,lsr#3	// sigma0(X[i+1])
+	add	w22,w22,w16			// h+=Sigma1(e)
+	eor	w19,w19,w24			// Maj(a,b,c)
+	eor	w17,w0,w23,ror#22	// Sigma0(a)
+	eor	w14,w14,w7,lsr#10	// sigma1(X[i+14])
+	add	w9,w9,w2
+	add	w26,w26,w22			// d+=h
+	add	w22,w22,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w9,w9,w15
+	add	w22,w22,w17			// h+=Sigma0(a)
+	add	w9,w9,w14
+	ldr	w14,[sp,#12]
+	str	w1,[sp,#8]
+	ror	w16,w26,#6
+	add	w21,w21,w19			// h+=K[i]
+	ror	w0,w11,#7
+	and	w17,w27,w26
+	ror	w15,w8,#17
+	bic	w19,w20,w26
+	ror	w1,w22,#2
+	add	w21,w21,w9			// h+=X[i]
+	eor	w16,w16,w26,ror#11
+	eor	w0,w0,w11,ror#18
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w22,w23			// a^b, b^c in next round
+	eor	w16,w16,w26,ror#25	// Sigma1(e)
+	eor	w1,w1,w22,ror#13
+	add	w21,w21,w17			// h+=Ch(e,f,g)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	eor	w15,w15,w8,ror#19
+	eor	w0,w0,w11,lsr#3	// sigma0(X[i+1])
+	add	w21,w21,w16			// h+=Sigma1(e)
+	eor	w28,w28,w23			// Maj(a,b,c)
+	eor	w17,w1,w22,ror#22	// Sigma0(a)
+	eor	w15,w15,w8,lsr#10	// sigma1(X[i+14])
+	add	w10,w10,w3
+	add	w25,w25,w21			// d+=h
+	add	w21,w21,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	add	w10,w10,w0
+	add	w21,w21,w17			// h+=Sigma0(a)
+	add	w10,w10,w15
+	ldr	w15,[sp,#0]
+	str	w2,[sp,#12]
+	ror	w16,w25,#6
+	add	w20,w20,w28			// h+=K[i]
+	ror	w1,w12,#7
+	and	w17,w26,w25
+	ror	w0,w9,#17
+	bic	w28,w27,w25
+	ror	w2,w21,#2
+	add	w20,w20,w10			// h+=X[i]
+	eor	w16,w16,w25,ror#11
+	eor	w1,w1,w12,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w21,w22			// a^b, b^c in next round
+	eor	w16,w16,w25,ror#25	// Sigma1(e)
+	eor	w2,w2,w21,ror#13
+	add	w20,w20,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w0,w0,w9,ror#19
+	eor	w1,w1,w12,lsr#3	// sigma0(X[i+1])
+	add	w20,w20,w16			// h+=Sigma1(e)
+	eor	w19,w19,w22			// Maj(a,b,c)
+	eor	w17,w2,w21,ror#22	// Sigma0(a)
+	eor	w0,w0,w9,lsr#10	// sigma1(X[i+14])
+	add	w11,w11,w4
+	add	w24,w24,w20			// d+=h
+	add	w20,w20,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w11,w11,w1
+	add	w20,w20,w17			// h+=Sigma0(a)
+	add	w11,w11,w0
+	ldr	w0,[sp,#4]
+	str	w3,[sp,#0]
+	ror	w16,w24,#6
+	add	w27,w27,w19			// h+=K[i]
+	ror	w2,w13,#7
+	and	w17,w25,w24
+	ror	w1,w10,#17
+	bic	w19,w26,w24
+	ror	w3,w20,#2
+	add	w27,w27,w11			// h+=X[i]
+	eor	w16,w16,w24,ror#11
+	eor	w2,w2,w13,ror#18
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w20,w21			// a^b, b^c in next round
+	eor	w16,w16,w24,ror#25	// Sigma1(e)
+	eor	w3,w3,w20,ror#13
+	add	w27,w27,w17			// h+=Ch(e,f,g)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	eor	w1,w1,w10,ror#19
+	eor	w2,w2,w13,lsr#3	// sigma0(X[i+1])
+	add	w27,w27,w16			// h+=Sigma1(e)
+	eor	w28,w28,w21			// Maj(a,b,c)
+	eor	w17,w3,w20,ror#22	// Sigma0(a)
+	eor	w1,w1,w10,lsr#10	// sigma1(X[i+14])
+	add	w12,w12,w5
+	add	w23,w23,w27			// d+=h
+	add	w27,w27,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	add	w12,w12,w2
+	add	w27,w27,w17			// h+=Sigma0(a)
+	add	w12,w12,w1
+	ldr	w1,[sp,#8]
+	str	w4,[sp,#4]
+	ror	w16,w23,#6
+	add	w26,w26,w28			// h+=K[i]
+	ror	w3,w14,#7
+	and	w17,w24,w23
+	ror	w2,w11,#17
+	bic	w28,w25,w23
+	ror	w4,w27,#2
+	add	w26,w26,w12			// h+=X[i]
+	eor	w16,w16,w23,ror#11
+	eor	w3,w3,w14,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w27,w20			// a^b, b^c in next round
+	eor	w16,w16,w23,ror#25	// Sigma1(e)
+	eor	w4,w4,w27,ror#13
+	add	w26,w26,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w2,w2,w11,ror#19
+	eor	w3,w3,w14,lsr#3	// sigma0(X[i+1])
+	add	w26,w26,w16			// h+=Sigma1(e)
+	eor	w19,w19,w20			// Maj(a,b,c)
+	eor	w17,w4,w27,ror#22	// Sigma0(a)
+	eor	w2,w2,w11,lsr#10	// sigma1(X[i+14])
+	add	w13,w13,w6
+	add	w22,w22,w26			// d+=h
+	add	w26,w26,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w13,w13,w3
+	add	w26,w26,w17			// h+=Sigma0(a)
+	add	w13,w13,w2
+	ldr	w2,[sp,#12]
+	str	w5,[sp,#8]
+	ror	w16,w22,#6
+	add	w25,w25,w19			// h+=K[i]
+	ror	w4,w15,#7
+	and	w17,w23,w22
+	ror	w3,w12,#17
+	bic	w19,w24,w22
+	ror	w5,w26,#2
+	add	w25,w25,w13			// h+=X[i]
+	eor	w16,w16,w22,ror#11
+	eor	w4,w4,w15,ror#18
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w26,w27			// a^b, b^c in next round
+	eor	w16,w16,w22,ror#25	// Sigma1(e)
+	eor	w5,w5,w26,ror#13
+	add	w25,w25,w17			// h+=Ch(e,f,g)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	eor	w3,w3,w12,ror#19
+	eor	w4,w4,w15,lsr#3	// sigma0(X[i+1])
+	add	w25,w25,w16			// h+=Sigma1(e)
+	eor	w28,w28,w27			// Maj(a,b,c)
+	eor	w17,w5,w26,ror#22	// Sigma0(a)
+	eor	w3,w3,w12,lsr#10	// sigma1(X[i+14])
+	add	w14,w14,w7
+	add	w21,w21,w25			// d+=h
+	add	w25,w25,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	add	w14,w14,w4
+	add	w25,w25,w17			// h+=Sigma0(a)
+	add	w14,w14,w3
+	ldr	w3,[sp,#0]
+	str	w6,[sp,#12]
+	ror	w16,w21,#6
+	add	w24,w24,w28			// h+=K[i]
+	ror	w5,w0,#7
+	and	w17,w22,w21
+	ror	w4,w13,#17
+	bic	w28,w23,w21
+	ror	w6,w25,#2
+	add	w24,w24,w14			// h+=X[i]
+	eor	w16,w16,w21,ror#11
+	eor	w5,w5,w0,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w25,w26			// a^b, b^c in next round
+	eor	w16,w16,w21,ror#25	// Sigma1(e)
+	eor	w6,w6,w25,ror#13
+	add	w24,w24,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w4,w4,w13,ror#19
+	eor	w5,w5,w0,lsr#3	// sigma0(X[i+1])
+	add	w24,w24,w16			// h+=Sigma1(e)
+	eor	w19,w19,w26			// Maj(a,b,c)
+	eor	w17,w6,w25,ror#22	// Sigma0(a)
+	eor	w4,w4,w13,lsr#10	// sigma1(X[i+14])
+	add	w15,w15,w8
+	add	w20,w20,w24			// d+=h
+	add	w24,w24,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w15,w15,w5
+	add	w24,w24,w17			// h+=Sigma0(a)
+	add	w15,w15,w4
+	ldr	w4,[sp,#4]
+	str	w7,[sp,#0]
+	ror	w16,w20,#6
+	add	w23,w23,w19			// h+=K[i]
+	ror	w6,w1,#7
+	and	w17,w21,w20
+	ror	w5,w14,#17
+	bic	w19,w22,w20
+	ror	w7,w24,#2
+	add	w23,w23,w15			// h+=X[i]
+	eor	w16,w16,w20,ror#11
+	eor	w6,w6,w1,ror#18
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w24,w25			// a^b, b^c in next round
+	eor	w16,w16,w20,ror#25	// Sigma1(e)
+	eor	w7,w7,w24,ror#13
+	add	w23,w23,w17			// h+=Ch(e,f,g)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	eor	w5,w5,w14,ror#19
+	eor	w6,w6,w1,lsr#3	// sigma0(X[i+1])
+	add	w23,w23,w16			// h+=Sigma1(e)
+	eor	w28,w28,w25			// Maj(a,b,c)
+	eor	w17,w7,w24,ror#22	// Sigma0(a)
+	eor	w5,w5,w14,lsr#10	// sigma1(X[i+14])
+	add	w0,w0,w9
+	add	w27,w27,w23			// d+=h
+	add	w23,w23,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	add	w0,w0,w6
+	add	w23,w23,w17			// h+=Sigma0(a)
+	add	w0,w0,w5
+	ldr	w5,[sp,#8]
+	str	w8,[sp,#4]
+	ror	w16,w27,#6
+	add	w22,w22,w28			// h+=K[i]
+	ror	w7,w2,#7
+	and	w17,w20,w27
+	ror	w6,w15,#17
+	bic	w28,w21,w27
+	ror	w8,w23,#2
+	add	w22,w22,w0			// h+=X[i]
+	eor	w16,w16,w27,ror#11
+	eor	w7,w7,w2,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w23,w24			// a^b, b^c in next round
+	eor	w16,w16,w27,ror#25	// Sigma1(e)
+	eor	w8,w8,w23,ror#13
+	add	w22,w22,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w6,w6,w15,ror#19
+	eor	w7,w7,w2,lsr#3	// sigma0(X[i+1])
+	add	w22,w22,w16			// h+=Sigma1(e)
+	eor	w19,w19,w24			// Maj(a,b,c)
+	eor	w17,w8,w23,ror#22	// Sigma0(a)
+	eor	w6,w6,w15,lsr#10	// sigma1(X[i+14])
+	add	w1,w1,w10
+	add	w26,w26,w22			// d+=h
+	add	w22,w22,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w1,w1,w7
+	add	w22,w22,w17			// h+=Sigma0(a)
+	add	w1,w1,w6
+	ldr	w6,[sp,#12]
+	str	w9,[sp,#8]
+	ror	w16,w26,#6
+	add	w21,w21,w19			// h+=K[i]
+	ror	w8,w3,#7
+	and	w17,w27,w26
+	ror	w7,w0,#17
+	bic	w19,w20,w26
+	ror	w9,w22,#2
+	add	w21,w21,w1			// h+=X[i]
+	eor	w16,w16,w26,ror#11
+	eor	w8,w8,w3,ror#18
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w22,w23			// a^b, b^c in next round
+	eor	w16,w16,w26,ror#25	// Sigma1(e)
+	eor	w9,w9,w22,ror#13
+	add	w21,w21,w17			// h+=Ch(e,f,g)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	eor	w7,w7,w0,ror#19
+	eor	w8,w8,w3,lsr#3	// sigma0(X[i+1])
+	add	w21,w21,w16			// h+=Sigma1(e)
+	eor	w28,w28,w23			// Maj(a,b,c)
+	eor	w17,w9,w22,ror#22	// Sigma0(a)
+	eor	w7,w7,w0,lsr#10	// sigma1(X[i+14])
+	add	w2,w2,w11
+	add	w25,w25,w21			// d+=h
+	add	w21,w21,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	add	w2,w2,w8
+	add	w21,w21,w17			// h+=Sigma0(a)
+	add	w2,w2,w7
+	ldr	w7,[sp,#0]
+	str	w10,[sp,#12]
+	ror	w16,w25,#6
+	add	w20,w20,w28			// h+=K[i]
+	ror	w9,w4,#7
+	and	w17,w26,w25
+	ror	w8,w1,#17
+	bic	w28,w27,w25
+	ror	w10,w21,#2
+	add	w20,w20,w2			// h+=X[i]
+	eor	w16,w16,w25,ror#11
+	eor	w9,w9,w4,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w21,w22			// a^b, b^c in next round
+	eor	w16,w16,w25,ror#25	// Sigma1(e)
+	eor	w10,w10,w21,ror#13
+	add	w20,w20,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w8,w8,w1,ror#19
+	eor	w9,w9,w4,lsr#3	// sigma0(X[i+1])
+	add	w20,w20,w16			// h+=Sigma1(e)
+	eor	w19,w19,w22			// Maj(a,b,c)
+	eor	w17,w10,w21,ror#22	// Sigma0(a)
+	eor	w8,w8,w1,lsr#10	// sigma1(X[i+14])
+	add	w3,w3,w12
+	add	w24,w24,w20			// d+=h
+	add	w20,w20,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w3,w3,w9
+	add	w20,w20,w17			// h+=Sigma0(a)
+	add	w3,w3,w8
+	cbnz	w19,Loop_16_xx
+
+	ldp	x0,x2,[x29,#96]
+	ldr	x1,[x29,#112]
+	sub	x30,x30,#260		// rewind
+
+	ldp	w3,w4,[x0]
+	ldp	w5,w6,[x0,#2*4]
+	add	x1,x1,#14*4			// advance input pointer
+	ldp	w7,w8,[x0,#4*4]
+	add	w20,w20,w3
+	ldp	w9,w10,[x0,#6*4]
+	add	w21,w21,w4
+	add	w22,w22,w5
+	add	w23,w23,w6
+	stp	w20,w21,[x0]
+	add	w24,w24,w7
+	add	w25,w25,w8
+	stp	w22,w23,[x0,#2*4]
+	add	w26,w26,w9
+	add	w27,w27,w10
+	cmp	x1,x2
+	stp	w24,w25,[x0,#4*4]
+	stp	w26,w27,[x0,#6*4]
+	b.ne	Loop
+
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#4*4
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#128
+	ret
+
+
+.align	6
+
+LK256:
+.long	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+.long	0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+.long	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+.long	0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+.long	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+.long	0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+.long	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+.long	0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+.long	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+.long	0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+.long	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+.long	0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+.long	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+.long	0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+.long	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+.long	0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+.long	0	//terminator
+
+.align	3
+LOPENSSL_armcap_P:
+.quad	_OPENSSL_armcap_P-.
+.byte	83,72,65,50,53,54,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+.align	2
+
+.align	6
+sha256_block_armv8:
+Lv8_entry:
+	stp	x29,x30,[sp,#-16]!
+	add	x29,sp,#0
+
+	ld1	{v0.4s,v1.4s},[x0]
+	adr	x3,LK256
+
+Loop_hw:
+	ld1	{v4.16b,v5.16b,v6.16b,v7.16b},[x1],#64
+	sub	x2,x2,#1
+	ld1	{v16.4s},[x3],#16
+	rev32	v4.16b,v4.16b
+	rev32	v5.16b,v5.16b
+	rev32	v6.16b,v6.16b
+	rev32	v7.16b,v7.16b
+	orr	v18.16b,v0.16b,v0.16b		// offload
+	orr	v19.16b,v1.16b,v1.16b
+	ld1	{v17.4s},[x3],#16
+	add	v16.4s,v16.4s,v4.4s
+.long	0x5e2828a4	//sha256su0 v4.16b,v5.16b
+	orr	v2.16b,v0.16b,v0.16b
+.long	0x5e104020	//sha256h v0.16b,v1.16b,v16.4s
+.long	0x5e105041	//sha256h2 v1.16b,v2.16b,v16.4s
+.long	0x5e0760c4	//sha256su1 v4.16b,v6.16b,v7.16b
+	ld1	{v16.4s},[x3],#16
+	add	v17.4s,v17.4s,v5.4s
+.long	0x5e2828c5	//sha256su0 v5.16b,v6.16b
+	orr	v2.16b,v0.16b,v0.16b
+.long	0x5e114020	//sha256h v0.16b,v1.16b,v17.4s
+.long	0x5e115041	//sha256h2 v1.16b,v2.16b,v17.4s
+.long	0x5e0460e5	//sha256su1 v5.16b,v7.16b,v4.16b
+	ld1	{v17.4s},[x3],#16
+	add	v16.4s,v16.4s,v6.4s
+.long	0x5e2828e6	//sha256su0 v6.16b,v7.16b
+	orr	v2.16b,v0.16b,v0.16b
+.long	0x5e104020	//sha256h v0.16b,v1.16b,v16.4s
+.long	0x5e105041	//sha256h2 v1.16b,v2.16b,v16.4s
+.long	0x5e056086	//sha256su1 v6.16b,v4.16b,v5.16b
+	ld1	{v16.4s},[x3],#16
+	add	v17.4s,v17.4s,v7.4s
+.long	0x5e282887	//sha256su0 v7.16b,v4.16b
+	orr	v2.16b,v0.16b,v0.16b
+.long	0x5e114020	//sha256h v0.16b,v1.16b,v17.4s
+.long	0x5e115041	//sha256h2 v1.16b,v2.16b,v17.4s
+.long	0x5e0660a7	//sha256su1 v7.16b,v5.16b,v6.16b
+	ld1	{v17.4s},[x3],#16
+	add	v16.4s,v16.4s,v4.4s
+.long	0x5e2828a4	//sha256su0 v4.16b,v5.16b
+	orr	v2.16b,v0.16b,v0.16b
+.long	0x5e104020	//sha256h v0.16b,v1.16b,v16.4s
+.long	0x5e105041	//sha256h2 v1.16b,v2.16b,v16.4s
+.long	0x5e0760c4	//sha256su1 v4.16b,v6.16b,v7.16b
+	ld1	{v16.4s},[x3],#16
+	add	v17.4s,v17.4s,v5.4s
+.long	0x5e2828c5	//sha256su0 v5.16b,v6.16b
+	orr	v2.16b,v0.16b,v0.16b
+.long	0x5e114020	//sha256h v0.16b,v1.16b,v17.4s
+.long	0x5e115041	//sha256h2 v1.16b,v2.16b,v17.4s
+.long	0x5e0460e5	//sha256su1 v5.16b,v7.16b,v4.16b
+	ld1	{v17.4s},[x3],#16
+	add	v16.4s,v16.4s,v6.4s
+.long	0x5e2828e6	//sha256su0 v6.16b,v7.16b
+	orr	v2.16b,v0.16b,v0.16b
+.long	0x5e104020	//sha256h v0.16b,v1.16b,v16.4s
+.long	0x5e105041	//sha256h2 v1.16b,v2.16b,v16.4s
+.long	0x5e056086	//sha256su1 v6.16b,v4.16b,v5.16b
+	ld1	{v16.4s},[x3],#16
+	add	v17.4s,v17.4s,v7.4s
+.long	0x5e282887	//sha256su0 v7.16b,v4.16b
+	orr	v2.16b,v0.16b,v0.16b
+.long	0x5e114020	//sha256h v0.16b,v1.16b,v17.4s
+.long	0x5e115041	//sha256h2 v1.16b,v2.16b,v17.4s
+.long	0x5e0660a7	//sha256su1 v7.16b,v5.16b,v6.16b
+	ld1	{v17.4s},[x3],#16
+	add	v16.4s,v16.4s,v4.4s
+.long	0x5e2828a4	//sha256su0 v4.16b,v5.16b
+	orr	v2.16b,v0.16b,v0.16b
+.long	0x5e104020	//sha256h v0.16b,v1.16b,v16.4s
+.long	0x5e105041	//sha256h2 v1.16b,v2.16b,v16.4s
+.long	0x5e0760c4	//sha256su1 v4.16b,v6.16b,v7.16b
+	ld1	{v16.4s},[x3],#16
+	add	v17.4s,v17.4s,v5.4s
+.long	0x5e2828c5	//sha256su0 v5.16b,v6.16b
+	orr	v2.16b,v0.16b,v0.16b
+.long	0x5e114020	//sha256h v0.16b,v1.16b,v17.4s
+.long	0x5e115041	//sha256h2 v1.16b,v2.16b,v17.4s
+.long	0x5e0460e5	//sha256su1 v5.16b,v7.16b,v4.16b
+	ld1	{v17.4s},[x3],#16
+	add	v16.4s,v16.4s,v6.4s
+.long	0x5e2828e6	//sha256su0 v6.16b,v7.16b
+	orr	v2.16b,v0.16b,v0.16b
+.long	0x5e104020	//sha256h v0.16b,v1.16b,v16.4s
+.long	0x5e105041	//sha256h2 v1.16b,v2.16b,v16.4s
+.long	0x5e056086	//sha256su1 v6.16b,v4.16b,v5.16b
+	ld1	{v16.4s},[x3],#16
+	add	v17.4s,v17.4s,v7.4s
+.long	0x5e282887	//sha256su0 v7.16b,v4.16b
+	orr	v2.16b,v0.16b,v0.16b
+.long	0x5e114020	//sha256h v0.16b,v1.16b,v17.4s
+.long	0x5e115041	//sha256h2 v1.16b,v2.16b,v17.4s
+.long	0x5e0660a7	//sha256su1 v7.16b,v5.16b,v6.16b
+	ld1	{v17.4s},[x3],#16
+	add	v16.4s,v16.4s,v4.4s
+	orr	v2.16b,v0.16b,v0.16b
+.long	0x5e104020	//sha256h v0.16b,v1.16b,v16.4s
+.long	0x5e105041	//sha256h2 v1.16b,v2.16b,v16.4s
+
+	ld1	{v16.4s},[x3],#16
+	add	v17.4s,v17.4s,v5.4s
+	orr	v2.16b,v0.16b,v0.16b
+.long	0x5e114020	//sha256h v0.16b,v1.16b,v17.4s
+.long	0x5e115041	//sha256h2 v1.16b,v2.16b,v17.4s
+
+	ld1	{v17.4s},[x3]
+	add	v16.4s,v16.4s,v6.4s
+	sub	x3,x3,#64*4-16	// rewind
+	orr	v2.16b,v0.16b,v0.16b
+.long	0x5e104020	//sha256h v0.16b,v1.16b,v16.4s
+.long	0x5e105041	//sha256h2 v1.16b,v2.16b,v16.4s
+
+	add	v17.4s,v17.4s,v7.4s
+	orr	v2.16b,v0.16b,v0.16b
+.long	0x5e114020	//sha256h v0.16b,v1.16b,v17.4s
+.long	0x5e115041	//sha256h2 v1.16b,v2.16b,v17.4s
+
+	add	v0.4s,v0.4s,v18.4s
+	add	v1.4s,v1.4s,v19.4s
+
+	cbnz	x2,Loop_hw
+
+	st1	{v0.4s,v1.4s},[x0]
+
+	ldr	x29,[sp],#16
+	ret
+
+.comm	_OPENSSL_armcap_P,4,4
diff --git a/third_party/boringssl/ios-aarch64/crypto/fipsmodule/sha512-armv8.S b/third_party/boringssl/ios-aarch64/crypto/fipsmodule/sha512-armv8.S
new file mode 100644
index 0000000..cc668e2
--- /dev/null
+++ b/third_party/boringssl/ios-aarch64/crypto/fipsmodule/sha512-armv8.S
@@ -0,0 +1,1024 @@
+#include <openssl/arm_arch.h>
+
+.text
+
+
+.globl	_sha512_block_data_order
+.private_extern	_sha512_block_data_order
+
+.align	6
+_sha512_block_data_order:
+	stp	x29,x30,[sp,#-128]!
+	add	x29,sp,#0
+
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+	sub	sp,sp,#4*8
+
+	ldp	x20,x21,[x0]				// load context
+	ldp	x22,x23,[x0,#2*8]
+	ldp	x24,x25,[x0,#4*8]
+	add	x2,x1,x2,lsl#7	// end of input
+	ldp	x26,x27,[x0,#6*8]
+	adr	x30,LK512
+	stp	x0,x2,[x29,#96]
+
+Loop:
+	ldp	x3,x4,[x1],#2*8
+	ldr	x19,[x30],#8			// *K++
+	eor	x28,x21,x22				// magic seed
+	str	x1,[x29,#112]
+#ifndef	__ARMEB__
+	rev	x3,x3			// 0
+#endif
+	ror	x16,x24,#14
+	add	x27,x27,x19			// h+=K[i]
+	eor	x6,x24,x24,ror#23
+	and	x17,x25,x24
+	bic	x19,x26,x24
+	add	x27,x27,x3			// h+=X[i]
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x20,x21			// a^b, b^c in next round
+	eor	x16,x16,x6,ror#18	// Sigma1(e)
+	ror	x6,x20,#28
+	add	x27,x27,x17			// h+=Ch(e,f,g)
+	eor	x17,x20,x20,ror#5
+	add	x27,x27,x16			// h+=Sigma1(e)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	add	x23,x23,x27			// d+=h
+	eor	x28,x28,x21			// Maj(a,b,c)
+	eor	x17,x6,x17,ror#34	// Sigma0(a)
+	add	x27,x27,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	//add	x27,x27,x17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	x4,x4			// 1
+#endif
+	ldp	x5,x6,[x1],#2*8
+	add	x27,x27,x17			// h+=Sigma0(a)
+	ror	x16,x23,#14
+	add	x26,x26,x28			// h+=K[i]
+	eor	x7,x23,x23,ror#23
+	and	x17,x24,x23
+	bic	x28,x25,x23
+	add	x26,x26,x4			// h+=X[i]
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x27,x20			// a^b, b^c in next round
+	eor	x16,x16,x7,ror#18	// Sigma1(e)
+	ror	x7,x27,#28
+	add	x26,x26,x17			// h+=Ch(e,f,g)
+	eor	x17,x27,x27,ror#5
+	add	x26,x26,x16			// h+=Sigma1(e)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	add	x22,x22,x26			// d+=h
+	eor	x19,x19,x20			// Maj(a,b,c)
+	eor	x17,x7,x17,ror#34	// Sigma0(a)
+	add	x26,x26,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	//add	x26,x26,x17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	x5,x5			// 2
+#endif
+	add	x26,x26,x17			// h+=Sigma0(a)
+	ror	x16,x22,#14
+	add	x25,x25,x19			// h+=K[i]
+	eor	x8,x22,x22,ror#23
+	and	x17,x23,x22
+	bic	x19,x24,x22
+	add	x25,x25,x5			// h+=X[i]
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x26,x27			// a^b, b^c in next round
+	eor	x16,x16,x8,ror#18	// Sigma1(e)
+	ror	x8,x26,#28
+	add	x25,x25,x17			// h+=Ch(e,f,g)
+	eor	x17,x26,x26,ror#5
+	add	x25,x25,x16			// h+=Sigma1(e)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	add	x21,x21,x25			// d+=h
+	eor	x28,x28,x27			// Maj(a,b,c)
+	eor	x17,x8,x17,ror#34	// Sigma0(a)
+	add	x25,x25,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	//add	x25,x25,x17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	x6,x6			// 3
+#endif
+	ldp	x7,x8,[x1],#2*8
+	add	x25,x25,x17			// h+=Sigma0(a)
+	ror	x16,x21,#14
+	add	x24,x24,x28			// h+=K[i]
+	eor	x9,x21,x21,ror#23
+	and	x17,x22,x21
+	bic	x28,x23,x21
+	add	x24,x24,x6			// h+=X[i]
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x25,x26			// a^b, b^c in next round
+	eor	x16,x16,x9,ror#18	// Sigma1(e)
+	ror	x9,x25,#28
+	add	x24,x24,x17			// h+=Ch(e,f,g)
+	eor	x17,x25,x25,ror#5
+	add	x24,x24,x16			// h+=Sigma1(e)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	add	x20,x20,x24			// d+=h
+	eor	x19,x19,x26			// Maj(a,b,c)
+	eor	x17,x9,x17,ror#34	// Sigma0(a)
+	add	x24,x24,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	//add	x24,x24,x17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	x7,x7			// 4
+#endif
+	add	x24,x24,x17			// h+=Sigma0(a)
+	ror	x16,x20,#14
+	add	x23,x23,x19			// h+=K[i]
+	eor	x10,x20,x20,ror#23
+	and	x17,x21,x20
+	bic	x19,x22,x20
+	add	x23,x23,x7			// h+=X[i]
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x24,x25			// a^b, b^c in next round
+	eor	x16,x16,x10,ror#18	// Sigma1(e)
+	ror	x10,x24,#28
+	add	x23,x23,x17			// h+=Ch(e,f,g)
+	eor	x17,x24,x24,ror#5
+	add	x23,x23,x16			// h+=Sigma1(e)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	add	x27,x27,x23			// d+=h
+	eor	x28,x28,x25			// Maj(a,b,c)
+	eor	x17,x10,x17,ror#34	// Sigma0(a)
+	add	x23,x23,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	//add	x23,x23,x17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	x8,x8			// 5
+#endif
+	ldp	x9,x10,[x1],#2*8
+	add	x23,x23,x17			// h+=Sigma0(a)
+	ror	x16,x27,#14
+	add	x22,x22,x28			// h+=K[i]
+	eor	x11,x27,x27,ror#23
+	and	x17,x20,x27
+	bic	x28,x21,x27
+	add	x22,x22,x8			// h+=X[i]
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x23,x24			// a^b, b^c in next round
+	eor	x16,x16,x11,ror#18	// Sigma1(e)
+	ror	x11,x23,#28
+	add	x22,x22,x17			// h+=Ch(e,f,g)
+	eor	x17,x23,x23,ror#5
+	add	x22,x22,x16			// h+=Sigma1(e)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	add	x26,x26,x22			// d+=h
+	eor	x19,x19,x24			// Maj(a,b,c)
+	eor	x17,x11,x17,ror#34	// Sigma0(a)
+	add	x22,x22,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	//add	x22,x22,x17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	x9,x9			// 6
+#endif
+	add	x22,x22,x17			// h+=Sigma0(a)
+	ror	x16,x26,#14
+	add	x21,x21,x19			// h+=K[i]
+	eor	x12,x26,x26,ror#23
+	and	x17,x27,x26
+	bic	x19,x20,x26
+	add	x21,x21,x9			// h+=X[i]
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x22,x23			// a^b, b^c in next round
+	eor	x16,x16,x12,ror#18	// Sigma1(e)
+	ror	x12,x22,#28
+	add	x21,x21,x17			// h+=Ch(e,f,g)
+	eor	x17,x22,x22,ror#5
+	add	x21,x21,x16			// h+=Sigma1(e)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	add	x25,x25,x21			// d+=h
+	eor	x28,x28,x23			// Maj(a,b,c)
+	eor	x17,x12,x17,ror#34	// Sigma0(a)
+	add	x21,x21,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	//add	x21,x21,x17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	x10,x10			// 7
+#endif
+	ldp	x11,x12,[x1],#2*8
+	add	x21,x21,x17			// h+=Sigma0(a)
+	ror	x16,x25,#14
+	add	x20,x20,x28			// h+=K[i]
+	eor	x13,x25,x25,ror#23
+	and	x17,x26,x25
+	bic	x28,x27,x25
+	add	x20,x20,x10			// h+=X[i]
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x21,x22			// a^b, b^c in next round
+	eor	x16,x16,x13,ror#18	// Sigma1(e)
+	ror	x13,x21,#28
+	add	x20,x20,x17			// h+=Ch(e,f,g)
+	eor	x17,x21,x21,ror#5
+	add	x20,x20,x16			// h+=Sigma1(e)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	add	x24,x24,x20			// d+=h
+	eor	x19,x19,x22			// Maj(a,b,c)
+	eor	x17,x13,x17,ror#34	// Sigma0(a)
+	add	x20,x20,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	//add	x20,x20,x17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	x11,x11			// 8
+#endif
+	add	x20,x20,x17			// h+=Sigma0(a)
+	ror	x16,x24,#14
+	add	x27,x27,x19			// h+=K[i]
+	eor	x14,x24,x24,ror#23
+	and	x17,x25,x24
+	bic	x19,x26,x24
+	add	x27,x27,x11			// h+=X[i]
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x20,x21			// a^b, b^c in next round
+	eor	x16,x16,x14,ror#18	// Sigma1(e)
+	ror	x14,x20,#28
+	add	x27,x27,x17			// h+=Ch(e,f,g)
+	eor	x17,x20,x20,ror#5
+	add	x27,x27,x16			// h+=Sigma1(e)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	add	x23,x23,x27			// d+=h
+	eor	x28,x28,x21			// Maj(a,b,c)
+	eor	x17,x14,x17,ror#34	// Sigma0(a)
+	add	x27,x27,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	//add	x27,x27,x17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	x12,x12			// 9
+#endif
+	ldp	x13,x14,[x1],#2*8
+	add	x27,x27,x17			// h+=Sigma0(a)
+	ror	x16,x23,#14
+	add	x26,x26,x28			// h+=K[i]
+	eor	x15,x23,x23,ror#23
+	and	x17,x24,x23
+	bic	x28,x25,x23
+	add	x26,x26,x12			// h+=X[i]
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x27,x20			// a^b, b^c in next round
+	eor	x16,x16,x15,ror#18	// Sigma1(e)
+	ror	x15,x27,#28
+	add	x26,x26,x17			// h+=Ch(e,f,g)
+	eor	x17,x27,x27,ror#5
+	add	x26,x26,x16			// h+=Sigma1(e)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	add	x22,x22,x26			// d+=h
+	eor	x19,x19,x20			// Maj(a,b,c)
+	eor	x17,x15,x17,ror#34	// Sigma0(a)
+	add	x26,x26,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	//add	x26,x26,x17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	x13,x13			// 10
+#endif
+	add	x26,x26,x17			// h+=Sigma0(a)
+	ror	x16,x22,#14
+	add	x25,x25,x19			// h+=K[i]
+	eor	x0,x22,x22,ror#23
+	and	x17,x23,x22
+	bic	x19,x24,x22
+	add	x25,x25,x13			// h+=X[i]
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x26,x27			// a^b, b^c in next round
+	eor	x16,x16,x0,ror#18	// Sigma1(e)
+	ror	x0,x26,#28
+	add	x25,x25,x17			// h+=Ch(e,f,g)
+	eor	x17,x26,x26,ror#5
+	add	x25,x25,x16			// h+=Sigma1(e)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	add	x21,x21,x25			// d+=h
+	eor	x28,x28,x27			// Maj(a,b,c)
+	eor	x17,x0,x17,ror#34	// Sigma0(a)
+	add	x25,x25,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	//add	x25,x25,x17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	x14,x14			// 11
+#endif
+	ldp	x15,x0,[x1],#2*8
+	add	x25,x25,x17			// h+=Sigma0(a)
+	str	x6,[sp,#24]
+	ror	x16,x21,#14
+	add	x24,x24,x28			// h+=K[i]
+	eor	x6,x21,x21,ror#23
+	and	x17,x22,x21
+	bic	x28,x23,x21
+	add	x24,x24,x14			// h+=X[i]
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x25,x26			// a^b, b^c in next round
+	eor	x16,x16,x6,ror#18	// Sigma1(e)
+	ror	x6,x25,#28
+	add	x24,x24,x17			// h+=Ch(e,f,g)
+	eor	x17,x25,x25,ror#5
+	add	x24,x24,x16			// h+=Sigma1(e)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	add	x20,x20,x24			// d+=h
+	eor	x19,x19,x26			// Maj(a,b,c)
+	eor	x17,x6,x17,ror#34	// Sigma0(a)
+	add	x24,x24,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	//add	x24,x24,x17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	x15,x15			// 12
+#endif
+	add	x24,x24,x17			// h+=Sigma0(a)
+	str	x7,[sp,#0]
+	ror	x16,x20,#14
+	add	x23,x23,x19			// h+=K[i]
+	eor	x7,x20,x20,ror#23
+	and	x17,x21,x20
+	bic	x19,x22,x20
+	add	x23,x23,x15			// h+=X[i]
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x24,x25			// a^b, b^c in next round
+	eor	x16,x16,x7,ror#18	// Sigma1(e)
+	ror	x7,x24,#28
+	add	x23,x23,x17			// h+=Ch(e,f,g)
+	eor	x17,x24,x24,ror#5
+	add	x23,x23,x16			// h+=Sigma1(e)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	add	x27,x27,x23			// d+=h
+	eor	x28,x28,x25			// Maj(a,b,c)
+	eor	x17,x7,x17,ror#34	// Sigma0(a)
+	add	x23,x23,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	//add	x23,x23,x17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	x0,x0			// 13
+#endif
+	ldp	x1,x2,[x1]
+	add	x23,x23,x17			// h+=Sigma0(a)
+	str	x8,[sp,#8]
+	ror	x16,x27,#14
+	add	x22,x22,x28			// h+=K[i]
+	eor	x8,x27,x27,ror#23
+	and	x17,x20,x27
+	bic	x28,x21,x27
+	add	x22,x22,x0			// h+=X[i]
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x23,x24			// a^b, b^c in next round
+	eor	x16,x16,x8,ror#18	// Sigma1(e)
+	ror	x8,x23,#28
+	add	x22,x22,x17			// h+=Ch(e,f,g)
+	eor	x17,x23,x23,ror#5
+	add	x22,x22,x16			// h+=Sigma1(e)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	add	x26,x26,x22			// d+=h
+	eor	x19,x19,x24			// Maj(a,b,c)
+	eor	x17,x8,x17,ror#34	// Sigma0(a)
+	add	x22,x22,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	//add	x22,x22,x17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	x1,x1			// 14
+#endif
+	ldr	x6,[sp,#24]
+	add	x22,x22,x17			// h+=Sigma0(a)
+	str	x9,[sp,#16]
+	ror	x16,x26,#14
+	add	x21,x21,x19			// h+=K[i]
+	eor	x9,x26,x26,ror#23
+	and	x17,x27,x26
+	bic	x19,x20,x26
+	add	x21,x21,x1			// h+=X[i]
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x22,x23			// a^b, b^c in next round
+	eor	x16,x16,x9,ror#18	// Sigma1(e)
+	ror	x9,x22,#28
+	add	x21,x21,x17			// h+=Ch(e,f,g)
+	eor	x17,x22,x22,ror#5
+	add	x21,x21,x16			// h+=Sigma1(e)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	add	x25,x25,x21			// d+=h
+	eor	x28,x28,x23			// Maj(a,b,c)
+	eor	x17,x9,x17,ror#34	// Sigma0(a)
+	add	x21,x21,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	//add	x21,x21,x17			// h+=Sigma0(a)
+#ifndef	__ARMEB__
+	rev	x2,x2			// 15
+#endif
+	ldr	x7,[sp,#0]
+	add	x21,x21,x17			// h+=Sigma0(a)
+	str	x10,[sp,#24]
+	ror	x16,x25,#14
+	add	x20,x20,x28			// h+=K[i]
+	ror	x9,x4,#1
+	and	x17,x26,x25
+	ror	x8,x1,#19
+	bic	x28,x27,x25
+	ror	x10,x21,#28
+	add	x20,x20,x2			// h+=X[i]
+	eor	x16,x16,x25,ror#18
+	eor	x9,x9,x4,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x21,x22			// a^b, b^c in next round
+	eor	x16,x16,x25,ror#41	// Sigma1(e)
+	eor	x10,x10,x21,ror#34
+	add	x20,x20,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x8,x8,x1,ror#61
+	eor	x9,x9,x4,lsr#7	// sigma0(X[i+1])
+	add	x20,x20,x16			// h+=Sigma1(e)
+	eor	x19,x19,x22			// Maj(a,b,c)
+	eor	x17,x10,x21,ror#39	// Sigma0(a)
+	eor	x8,x8,x1,lsr#6	// sigma1(X[i+14])
+	add	x3,x3,x12
+	add	x24,x24,x20			// d+=h
+	add	x20,x20,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x3,x3,x9
+	add	x20,x20,x17			// h+=Sigma0(a)
+	add	x3,x3,x8
+Loop_16_xx:
+	ldr	x8,[sp,#8]
+	str	x11,[sp,#0]
+	ror	x16,x24,#14
+	add	x27,x27,x19			// h+=K[i]
+	ror	x10,x5,#1
+	and	x17,x25,x24
+	ror	x9,x2,#19
+	bic	x19,x26,x24
+	ror	x11,x20,#28
+	add	x27,x27,x3			// h+=X[i]
+	eor	x16,x16,x24,ror#18
+	eor	x10,x10,x5,ror#8
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x20,x21			// a^b, b^c in next round
+	eor	x16,x16,x24,ror#41	// Sigma1(e)
+	eor	x11,x11,x20,ror#34
+	add	x27,x27,x17			// h+=Ch(e,f,g)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	eor	x9,x9,x2,ror#61
+	eor	x10,x10,x5,lsr#7	// sigma0(X[i+1])
+	add	x27,x27,x16			// h+=Sigma1(e)
+	eor	x28,x28,x21			// Maj(a,b,c)
+	eor	x17,x11,x20,ror#39	// Sigma0(a)
+	eor	x9,x9,x2,lsr#6	// sigma1(X[i+14])
+	add	x4,x4,x13
+	add	x23,x23,x27			// d+=h
+	add	x27,x27,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	add	x4,x4,x10
+	add	x27,x27,x17			// h+=Sigma0(a)
+	add	x4,x4,x9
+	ldr	x9,[sp,#16]
+	str	x12,[sp,#8]
+	ror	x16,x23,#14
+	add	x26,x26,x28			// h+=K[i]
+	ror	x11,x6,#1
+	and	x17,x24,x23
+	ror	x10,x3,#19
+	bic	x28,x25,x23
+	ror	x12,x27,#28
+	add	x26,x26,x4			// h+=X[i]
+	eor	x16,x16,x23,ror#18
+	eor	x11,x11,x6,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x27,x20			// a^b, b^c in next round
+	eor	x16,x16,x23,ror#41	// Sigma1(e)
+	eor	x12,x12,x27,ror#34
+	add	x26,x26,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x10,x10,x3,ror#61
+	eor	x11,x11,x6,lsr#7	// sigma0(X[i+1])
+	add	x26,x26,x16			// h+=Sigma1(e)
+	eor	x19,x19,x20			// Maj(a,b,c)
+	eor	x17,x12,x27,ror#39	// Sigma0(a)
+	eor	x10,x10,x3,lsr#6	// sigma1(X[i+14])
+	add	x5,x5,x14
+	add	x22,x22,x26			// d+=h
+	add	x26,x26,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x5,x5,x11
+	add	x26,x26,x17			// h+=Sigma0(a)
+	add	x5,x5,x10
+	ldr	x10,[sp,#24]
+	str	x13,[sp,#16]
+	ror	x16,x22,#14
+	add	x25,x25,x19			// h+=K[i]
+	ror	x12,x7,#1
+	and	x17,x23,x22
+	ror	x11,x4,#19
+	bic	x19,x24,x22
+	ror	x13,x26,#28
+	add	x25,x25,x5			// h+=X[i]
+	eor	x16,x16,x22,ror#18
+	eor	x12,x12,x7,ror#8
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x26,x27			// a^b, b^c in next round
+	eor	x16,x16,x22,ror#41	// Sigma1(e)
+	eor	x13,x13,x26,ror#34
+	add	x25,x25,x17			// h+=Ch(e,f,g)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	eor	x11,x11,x4,ror#61
+	eor	x12,x12,x7,lsr#7	// sigma0(X[i+1])
+	add	x25,x25,x16			// h+=Sigma1(e)
+	eor	x28,x28,x27			// Maj(a,b,c)
+	eor	x17,x13,x26,ror#39	// Sigma0(a)
+	eor	x11,x11,x4,lsr#6	// sigma1(X[i+14])
+	add	x6,x6,x15
+	add	x21,x21,x25			// d+=h
+	add	x25,x25,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	add	x6,x6,x12
+	add	x25,x25,x17			// h+=Sigma0(a)
+	add	x6,x6,x11
+	ldr	x11,[sp,#0]
+	str	x14,[sp,#24]
+	ror	x16,x21,#14
+	add	x24,x24,x28			// h+=K[i]
+	ror	x13,x8,#1
+	and	x17,x22,x21
+	ror	x12,x5,#19
+	bic	x28,x23,x21
+	ror	x14,x25,#28
+	add	x24,x24,x6			// h+=X[i]
+	eor	x16,x16,x21,ror#18
+	eor	x13,x13,x8,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x25,x26			// a^b, b^c in next round
+	eor	x16,x16,x21,ror#41	// Sigma1(e)
+	eor	x14,x14,x25,ror#34
+	add	x24,x24,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x12,x12,x5,ror#61
+	eor	x13,x13,x8,lsr#7	// sigma0(X[i+1])
+	add	x24,x24,x16			// h+=Sigma1(e)
+	eor	x19,x19,x26			// Maj(a,b,c)
+	eor	x17,x14,x25,ror#39	// Sigma0(a)
+	eor	x12,x12,x5,lsr#6	// sigma1(X[i+14])
+	add	x7,x7,x0
+	add	x20,x20,x24			// d+=h
+	add	x24,x24,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x7,x7,x13
+	add	x24,x24,x17			// h+=Sigma0(a)
+	add	x7,x7,x12
+	ldr	x12,[sp,#8]
+	str	x15,[sp,#0]
+	ror	x16,x20,#14
+	add	x23,x23,x19			// h+=K[i]
+	ror	x14,x9,#1
+	and	x17,x21,x20
+	ror	x13,x6,#19
+	bic	x19,x22,x20
+	ror	x15,x24,#28
+	add	x23,x23,x7			// h+=X[i]
+	eor	x16,x16,x20,ror#18
+	eor	x14,x14,x9,ror#8
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x24,x25			// a^b, b^c in next round
+	eor	x16,x16,x20,ror#41	// Sigma1(e)
+	eor	x15,x15,x24,ror#34
+	add	x23,x23,x17			// h+=Ch(e,f,g)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	eor	x13,x13,x6,ror#61
+	eor	x14,x14,x9,lsr#7	// sigma0(X[i+1])
+	add	x23,x23,x16			// h+=Sigma1(e)
+	eor	x28,x28,x25			// Maj(a,b,c)
+	eor	x17,x15,x24,ror#39	// Sigma0(a)
+	eor	x13,x13,x6,lsr#6	// sigma1(X[i+14])
+	add	x8,x8,x1
+	add	x27,x27,x23			// d+=h
+	add	x23,x23,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	add	x8,x8,x14
+	add	x23,x23,x17			// h+=Sigma0(a)
+	add	x8,x8,x13
+	ldr	x13,[sp,#16]
+	str	x0,[sp,#8]
+	ror	x16,x27,#14
+	add	x22,x22,x28			// h+=K[i]
+	ror	x15,x10,#1
+	and	x17,x20,x27
+	ror	x14,x7,#19
+	bic	x28,x21,x27
+	ror	x0,x23,#28
+	add	x22,x22,x8			// h+=X[i]
+	eor	x16,x16,x27,ror#18
+	eor	x15,x15,x10,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x23,x24			// a^b, b^c in next round
+	eor	x16,x16,x27,ror#41	// Sigma1(e)
+	eor	x0,x0,x23,ror#34
+	add	x22,x22,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x14,x14,x7,ror#61
+	eor	x15,x15,x10,lsr#7	// sigma0(X[i+1])
+	add	x22,x22,x16			// h+=Sigma1(e)
+	eor	x19,x19,x24			// Maj(a,b,c)
+	eor	x17,x0,x23,ror#39	// Sigma0(a)
+	eor	x14,x14,x7,lsr#6	// sigma1(X[i+14])
+	add	x9,x9,x2
+	add	x26,x26,x22			// d+=h
+	add	x22,x22,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x9,x9,x15
+	add	x22,x22,x17			// h+=Sigma0(a)
+	add	x9,x9,x14
+	ldr	x14,[sp,#24]
+	str	x1,[sp,#16]
+	ror	x16,x26,#14
+	add	x21,x21,x19			// h+=K[i]
+	ror	x0,x11,#1
+	and	x17,x27,x26
+	ror	x15,x8,#19
+	bic	x19,x20,x26
+	ror	x1,x22,#28
+	add	x21,x21,x9			// h+=X[i]
+	eor	x16,x16,x26,ror#18
+	eor	x0,x0,x11,ror#8
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x22,x23			// a^b, b^c in next round
+	eor	x16,x16,x26,ror#41	// Sigma1(e)
+	eor	x1,x1,x22,ror#34
+	add	x21,x21,x17			// h+=Ch(e,f,g)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	eor	x15,x15,x8,ror#61
+	eor	x0,x0,x11,lsr#7	// sigma0(X[i+1])
+	add	x21,x21,x16			// h+=Sigma1(e)
+	eor	x28,x28,x23			// Maj(a,b,c)
+	eor	x17,x1,x22,ror#39	// Sigma0(a)
+	eor	x15,x15,x8,lsr#6	// sigma1(X[i+14])
+	add	x10,x10,x3
+	add	x25,x25,x21			// d+=h
+	add	x21,x21,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	add	x10,x10,x0
+	add	x21,x21,x17			// h+=Sigma0(a)
+	add	x10,x10,x15
+	ldr	x15,[sp,#0]
+	str	x2,[sp,#24]
+	ror	x16,x25,#14
+	add	x20,x20,x28			// h+=K[i]
+	ror	x1,x12,#1
+	and	x17,x26,x25
+	ror	x0,x9,#19
+	bic	x28,x27,x25
+	ror	x2,x21,#28
+	add	x20,x20,x10			// h+=X[i]
+	eor	x16,x16,x25,ror#18
+	eor	x1,x1,x12,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x21,x22			// a^b, b^c in next round
+	eor	x16,x16,x25,ror#41	// Sigma1(e)
+	eor	x2,x2,x21,ror#34
+	add	x20,x20,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x0,x0,x9,ror#61
+	eor	x1,x1,x12,lsr#7	// sigma0(X[i+1])
+	add	x20,x20,x16			// h+=Sigma1(e)
+	eor	x19,x19,x22			// Maj(a,b,c)
+	eor	x17,x2,x21,ror#39	// Sigma0(a)
+	eor	x0,x0,x9,lsr#6	// sigma1(X[i+14])
+	add	x11,x11,x4
+	add	x24,x24,x20			// d+=h
+	add	x20,x20,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x11,x11,x1
+	add	x20,x20,x17			// h+=Sigma0(a)
+	add	x11,x11,x0
+	ldr	x0,[sp,#8]
+	str	x3,[sp,#0]
+	ror	x16,x24,#14
+	add	x27,x27,x19			// h+=K[i]
+	ror	x2,x13,#1
+	and	x17,x25,x24
+	ror	x1,x10,#19
+	bic	x19,x26,x24
+	ror	x3,x20,#28
+	add	x27,x27,x11			// h+=X[i]
+	eor	x16,x16,x24,ror#18
+	eor	x2,x2,x13,ror#8
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x20,x21			// a^b, b^c in next round
+	eor	x16,x16,x24,ror#41	// Sigma1(e)
+	eor	x3,x3,x20,ror#34
+	add	x27,x27,x17			// h+=Ch(e,f,g)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	eor	x1,x1,x10,ror#61
+	eor	x2,x2,x13,lsr#7	// sigma0(X[i+1])
+	add	x27,x27,x16			// h+=Sigma1(e)
+	eor	x28,x28,x21			// Maj(a,b,c)
+	eor	x17,x3,x20,ror#39	// Sigma0(a)
+	eor	x1,x1,x10,lsr#6	// sigma1(X[i+14])
+	add	x12,x12,x5
+	add	x23,x23,x27			// d+=h
+	add	x27,x27,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	add	x12,x12,x2
+	add	x27,x27,x17			// h+=Sigma0(a)
+	add	x12,x12,x1
+	ldr	x1,[sp,#16]
+	str	x4,[sp,#8]
+	ror	x16,x23,#14
+	add	x26,x26,x28			// h+=K[i]
+	ror	x3,x14,#1
+	and	x17,x24,x23
+	ror	x2,x11,#19
+	bic	x28,x25,x23
+	ror	x4,x27,#28
+	add	x26,x26,x12			// h+=X[i]
+	eor	x16,x16,x23,ror#18
+	eor	x3,x3,x14,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x27,x20			// a^b, b^c in next round
+	eor	x16,x16,x23,ror#41	// Sigma1(e)
+	eor	x4,x4,x27,ror#34
+	add	x26,x26,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x2,x2,x11,ror#61
+	eor	x3,x3,x14,lsr#7	// sigma0(X[i+1])
+	add	x26,x26,x16			// h+=Sigma1(e)
+	eor	x19,x19,x20			// Maj(a,b,c)
+	eor	x17,x4,x27,ror#39	// Sigma0(a)
+	eor	x2,x2,x11,lsr#6	// sigma1(X[i+14])
+	add	x13,x13,x6
+	add	x22,x22,x26			// d+=h
+	add	x26,x26,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x13,x13,x3
+	add	x26,x26,x17			// h+=Sigma0(a)
+	add	x13,x13,x2
+	ldr	x2,[sp,#24]
+	str	x5,[sp,#16]
+	ror	x16,x22,#14
+	add	x25,x25,x19			// h+=K[i]
+	ror	x4,x15,#1
+	and	x17,x23,x22
+	ror	x3,x12,#19
+	bic	x19,x24,x22
+	ror	x5,x26,#28
+	add	x25,x25,x13			// h+=X[i]
+	eor	x16,x16,x22,ror#18
+	eor	x4,x4,x15,ror#8
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x26,x27			// a^b, b^c in next round
+	eor	x16,x16,x22,ror#41	// Sigma1(e)
+	eor	x5,x5,x26,ror#34
+	add	x25,x25,x17			// h+=Ch(e,f,g)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	eor	x3,x3,x12,ror#61
+	eor	x4,x4,x15,lsr#7	// sigma0(X[i+1])
+	add	x25,x25,x16			// h+=Sigma1(e)
+	eor	x28,x28,x27			// Maj(a,b,c)
+	eor	x17,x5,x26,ror#39	// Sigma0(a)
+	eor	x3,x3,x12,lsr#6	// sigma1(X[i+14])
+	add	x14,x14,x7
+	add	x21,x21,x25			// d+=h
+	add	x25,x25,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	add	x14,x14,x4
+	add	x25,x25,x17			// h+=Sigma0(a)
+	add	x14,x14,x3
+	ldr	x3,[sp,#0]
+	str	x6,[sp,#24]
+	ror	x16,x21,#14
+	add	x24,x24,x28			// h+=K[i]
+	ror	x5,x0,#1
+	and	x17,x22,x21
+	ror	x4,x13,#19
+	bic	x28,x23,x21
+	ror	x6,x25,#28
+	add	x24,x24,x14			// h+=X[i]
+	eor	x16,x16,x21,ror#18
+	eor	x5,x5,x0,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x25,x26			// a^b, b^c in next round
+	eor	x16,x16,x21,ror#41	// Sigma1(e)
+	eor	x6,x6,x25,ror#34
+	add	x24,x24,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x4,x4,x13,ror#61
+	eor	x5,x5,x0,lsr#7	// sigma0(X[i+1])
+	add	x24,x24,x16			// h+=Sigma1(e)
+	eor	x19,x19,x26			// Maj(a,b,c)
+	eor	x17,x6,x25,ror#39	// Sigma0(a)
+	eor	x4,x4,x13,lsr#6	// sigma1(X[i+14])
+	add	x15,x15,x8
+	add	x20,x20,x24			// d+=h
+	add	x24,x24,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x15,x15,x5
+	add	x24,x24,x17			// h+=Sigma0(a)
+	add	x15,x15,x4
+	ldr	x4,[sp,#8]
+	str	x7,[sp,#0]
+	ror	x16,x20,#14
+	add	x23,x23,x19			// h+=K[i]
+	ror	x6,x1,#1
+	and	x17,x21,x20
+	ror	x5,x14,#19
+	bic	x19,x22,x20
+	ror	x7,x24,#28
+	add	x23,x23,x15			// h+=X[i]
+	eor	x16,x16,x20,ror#18
+	eor	x6,x6,x1,ror#8
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x24,x25			// a^b, b^c in next round
+	eor	x16,x16,x20,ror#41	// Sigma1(e)
+	eor	x7,x7,x24,ror#34
+	add	x23,x23,x17			// h+=Ch(e,f,g)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	eor	x5,x5,x14,ror#61
+	eor	x6,x6,x1,lsr#7	// sigma0(X[i+1])
+	add	x23,x23,x16			// h+=Sigma1(e)
+	eor	x28,x28,x25			// Maj(a,b,c)
+	eor	x17,x7,x24,ror#39	// Sigma0(a)
+	eor	x5,x5,x14,lsr#6	// sigma1(X[i+14])
+	add	x0,x0,x9
+	add	x27,x27,x23			// d+=h
+	add	x23,x23,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	add	x0,x0,x6
+	add	x23,x23,x17			// h+=Sigma0(a)
+	add	x0,x0,x5
+	ldr	x5,[sp,#16]
+	str	x8,[sp,#8]
+	ror	x16,x27,#14
+	add	x22,x22,x28			// h+=K[i]
+	ror	x7,x2,#1
+	and	x17,x20,x27
+	ror	x6,x15,#19
+	bic	x28,x21,x27
+	ror	x8,x23,#28
+	add	x22,x22,x0			// h+=X[i]
+	eor	x16,x16,x27,ror#18
+	eor	x7,x7,x2,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x23,x24			// a^b, b^c in next round
+	eor	x16,x16,x27,ror#41	// Sigma1(e)
+	eor	x8,x8,x23,ror#34
+	add	x22,x22,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x6,x6,x15,ror#61
+	eor	x7,x7,x2,lsr#7	// sigma0(X[i+1])
+	add	x22,x22,x16			// h+=Sigma1(e)
+	eor	x19,x19,x24			// Maj(a,b,c)
+	eor	x17,x8,x23,ror#39	// Sigma0(a)
+	eor	x6,x6,x15,lsr#6	// sigma1(X[i+14])
+	add	x1,x1,x10
+	add	x26,x26,x22			// d+=h
+	add	x22,x22,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x1,x1,x7
+	add	x22,x22,x17			// h+=Sigma0(a)
+	add	x1,x1,x6
+	ldr	x6,[sp,#24]
+	str	x9,[sp,#16]
+	ror	x16,x26,#14
+	add	x21,x21,x19			// h+=K[i]
+	ror	x8,x3,#1
+	and	x17,x27,x26
+	ror	x7,x0,#19
+	bic	x19,x20,x26
+	ror	x9,x22,#28
+	add	x21,x21,x1			// h+=X[i]
+	eor	x16,x16,x26,ror#18
+	eor	x8,x8,x3,ror#8
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x22,x23			// a^b, b^c in next round
+	eor	x16,x16,x26,ror#41	// Sigma1(e)
+	eor	x9,x9,x22,ror#34
+	add	x21,x21,x17			// h+=Ch(e,f,g)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	eor	x7,x7,x0,ror#61
+	eor	x8,x8,x3,lsr#7	// sigma0(X[i+1])
+	add	x21,x21,x16			// h+=Sigma1(e)
+	eor	x28,x28,x23			// Maj(a,b,c)
+	eor	x17,x9,x22,ror#39	// Sigma0(a)
+	eor	x7,x7,x0,lsr#6	// sigma1(X[i+14])
+	add	x2,x2,x11
+	add	x25,x25,x21			// d+=h
+	add	x21,x21,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	add	x2,x2,x8
+	add	x21,x21,x17			// h+=Sigma0(a)
+	add	x2,x2,x7
+	ldr	x7,[sp,#0]
+	str	x10,[sp,#24]
+	ror	x16,x25,#14
+	add	x20,x20,x28			// h+=K[i]
+	ror	x9,x4,#1
+	and	x17,x26,x25
+	ror	x8,x1,#19
+	bic	x28,x27,x25
+	ror	x10,x21,#28
+	add	x20,x20,x2			// h+=X[i]
+	eor	x16,x16,x25,ror#18
+	eor	x9,x9,x4,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x21,x22			// a^b, b^c in next round
+	eor	x16,x16,x25,ror#41	// Sigma1(e)
+	eor	x10,x10,x21,ror#34
+	add	x20,x20,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x8,x8,x1,ror#61
+	eor	x9,x9,x4,lsr#7	// sigma0(X[i+1])
+	add	x20,x20,x16			// h+=Sigma1(e)
+	eor	x19,x19,x22			// Maj(a,b,c)
+	eor	x17,x10,x21,ror#39	// Sigma0(a)
+	eor	x8,x8,x1,lsr#6	// sigma1(X[i+14])
+	add	x3,x3,x12
+	add	x24,x24,x20			// d+=h
+	add	x20,x20,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x3,x3,x9
+	add	x20,x20,x17			// h+=Sigma0(a)
+	add	x3,x3,x8
+	cbnz	x19,Loop_16_xx
+
+	ldp	x0,x2,[x29,#96]
+	ldr	x1,[x29,#112]
+	sub	x30,x30,#648		// rewind
+
+	ldp	x3,x4,[x0]
+	ldp	x5,x6,[x0,#2*8]
+	add	x1,x1,#14*8			// advance input pointer
+	ldp	x7,x8,[x0,#4*8]
+	add	x20,x20,x3
+	ldp	x9,x10,[x0,#6*8]
+	add	x21,x21,x4
+	add	x22,x22,x5
+	add	x23,x23,x6
+	stp	x20,x21,[x0]
+	add	x24,x24,x7
+	add	x25,x25,x8
+	stp	x22,x23,[x0,#2*8]
+	add	x26,x26,x9
+	add	x27,x27,x10
+	cmp	x1,x2
+	stp	x24,x25,[x0,#4*8]
+	stp	x26,x27,[x0,#6*8]
+	b.ne	Loop
+
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#4*8
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#128
+	ret
+
+
+.align	6
+
+LK512:
+.quad	0x428a2f98d728ae22,0x7137449123ef65cd
+.quad	0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+.quad	0x3956c25bf348b538,0x59f111f1b605d019
+.quad	0x923f82a4af194f9b,0xab1c5ed5da6d8118
+.quad	0xd807aa98a3030242,0x12835b0145706fbe
+.quad	0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+.quad	0x72be5d74f27b896f,0x80deb1fe3b1696b1
+.quad	0x9bdc06a725c71235,0xc19bf174cf692694
+.quad	0xe49b69c19ef14ad2,0xefbe4786384f25e3
+.quad	0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+.quad	0x2de92c6f592b0275,0x4a7484aa6ea6e483
+.quad	0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+.quad	0x983e5152ee66dfab,0xa831c66d2db43210
+.quad	0xb00327c898fb213f,0xbf597fc7beef0ee4
+.quad	0xc6e00bf33da88fc2,0xd5a79147930aa725
+.quad	0x06ca6351e003826f,0x142929670a0e6e70
+.quad	0x27b70a8546d22ffc,0x2e1b21385c26c926
+.quad	0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+.quad	0x650a73548baf63de,0x766a0abb3c77b2a8
+.quad	0x81c2c92e47edaee6,0x92722c851482353b
+.quad	0xa2bfe8a14cf10364,0xa81a664bbc423001
+.quad	0xc24b8b70d0f89791,0xc76c51a30654be30
+.quad	0xd192e819d6ef5218,0xd69906245565a910
+.quad	0xf40e35855771202a,0x106aa07032bbd1b8
+.quad	0x19a4c116b8d2d0c8,0x1e376c085141ab53
+.quad	0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+.quad	0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+.quad	0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+.quad	0x748f82ee5defb2fc,0x78a5636f43172f60
+.quad	0x84c87814a1f0ab72,0x8cc702081a6439ec
+.quad	0x90befffa23631e28,0xa4506cebde82bde9
+.quad	0xbef9a3f7b2c67915,0xc67178f2e372532b
+.quad	0xca273eceea26619c,0xd186b8c721c0c207
+.quad	0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+.quad	0x06f067aa72176fba,0x0a637dc5a2c898a6
+.quad	0x113f9804bef90dae,0x1b710b35131c471b
+.quad	0x28db77f523047d84,0x32caab7b40c72493
+.quad	0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+.quad	0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+.quad	0x5fcb6fab3ad6faec,0x6c44198c4a475817
+.quad	0	// terminator
+
+.align	3
+LOPENSSL_armcap_P:
+.quad	_OPENSSL_armcap_P-.
+.byte	83,72,65,53,49,50,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+.align	2
+.comm	_OPENSSL_armcap_P,4,4
diff --git a/third_party/boringssl/ios-arm/crypto/chacha/chacha-armv4.S b/third_party/boringssl/ios-arm/crypto/chacha/chacha-armv4.S
new file mode 100644
index 0000000..3eaecba
--- /dev/null
+++ b/third_party/boringssl/ios-arm/crypto/chacha/chacha-armv4.S
@@ -0,0 +1,1473 @@
+#include <openssl/arm_arch.h>
+
+.text
+#if defined(__thumb2__)
+.syntax	unified
+.thumb
+#else
+.code	32
+#endif
+
+#if defined(__thumb2__) || defined(__clang__)
+#define ldrhsb	ldrbhs
+#endif
+
+.align	5
+Lsigma:
+.long	0x61707865,0x3320646e,0x79622d32,0x6b206574	@ endian-neutral
+Lone:
+.long	1,0,0,0
+#if __ARM_MAX_ARCH__>=7
+LOPENSSL_armcap:
+.word	OPENSSL_armcap_P-LChaCha20_ctr32
+#else
+.word	-1
+#endif
+
+.globl	_ChaCha20_ctr32
+.private_extern	_ChaCha20_ctr32
+
+.align	5
+_ChaCha20_ctr32:
+LChaCha20_ctr32:
+	ldr	r12,[sp,#0]		@ pull pointer to counter and nonce
+	stmdb	sp!,{r0,r1,r2,r4-r11,lr}
+#if __ARM_ARCH__<7 && !defined(__thumb2__)
+	sub	r14,pc,#16		@ _ChaCha20_ctr32
+#else
+	adr	r14,LChaCha20_ctr32
+#endif
+	cmp	r2,#0			@ len==0?
+#ifdef	__thumb2__
+	itt	eq
+#endif
+	addeq	sp,sp,#4*3
+	beq	Lno_data
+#if __ARM_MAX_ARCH__>=7
+	cmp	r2,#192			@ test len
+	bls	Lshort
+	ldr	r4,[r14,#-32]
+	ldr	r4,[r14,r4]
+# ifdef	__APPLE__
+	ldr	r4,[r4]
+# endif
+	tst	r4,#ARMV7_NEON
+	bne	LChaCha20_neon
+Lshort:
+#endif
+	ldmia	r12,{r4,r5,r6,r7}		@ load counter and nonce
+	sub	sp,sp,#4*(16)		@ off-load area
+	sub	r14,r14,#64		@ Lsigma
+	stmdb	sp!,{r4,r5,r6,r7}		@ copy counter and nonce
+	ldmia	r3,{r4,r5,r6,r7,r8,r9,r10,r11}		@ load key
+	ldmia	r14,{r0,r1,r2,r3}		@ load sigma
+	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11}		@ copy key
+	stmdb	sp!,{r0,r1,r2,r3}		@ copy sigma
+	str	r10,[sp,#4*(16+10)]	@ off-load "rx"
+	str	r11,[sp,#4*(16+11)]	@ off-load "rx"
+	b	Loop_outer_enter
+
+.align	4
+Loop_outer:
+	ldmia	sp,{r0,r1,r2,r3,r4,r5,r6,r7,r8,r9}		@ load key material
+	str	r11,[sp,#4*(32+2)]	@ save len
+	str	r12,  [sp,#4*(32+1)]	@ save inp
+	str	r14,  [sp,#4*(32+0)]	@ save out
+Loop_outer_enter:
+	ldr	r11, [sp,#4*(15)]
+	ldr	r12,[sp,#4*(12)]	@ modulo-scheduled load
+	ldr	r10, [sp,#4*(13)]
+	ldr	r14,[sp,#4*(14)]
+	str	r11, [sp,#4*(16+15)]
+	mov	r11,#10
+	b	Loop
+
+.align	4
+Loop:
+	subs	r11,r11,#1
+	add	r0,r0,r4
+	mov	r12,r12,ror#16
+	add	r1,r1,r5
+	mov	r10,r10,ror#16
+	eor	r12,r12,r0,ror#16
+	eor	r10,r10,r1,ror#16
+	add	r8,r8,r12
+	mov	r4,r4,ror#20
+	add	r9,r9,r10
+	mov	r5,r5,ror#20
+	eor	r4,r4,r8,ror#20
+	eor	r5,r5,r9,ror#20
+	add	r0,r0,r4
+	mov	r12,r12,ror#24
+	add	r1,r1,r5
+	mov	r10,r10,ror#24
+	eor	r12,r12,r0,ror#24
+	eor	r10,r10,r1,ror#24
+	add	r8,r8,r12
+	mov	r4,r4,ror#25
+	add	r9,r9,r10
+	mov	r5,r5,ror#25
+	str	r10,[sp,#4*(16+13)]
+	ldr	r10,[sp,#4*(16+15)]
+	eor	r4,r4,r8,ror#25
+	eor	r5,r5,r9,ror#25
+	str	r8,[sp,#4*(16+8)]
+	ldr	r8,[sp,#4*(16+10)]
+	add	r2,r2,r6
+	mov	r14,r14,ror#16
+	str	r9,[sp,#4*(16+9)]
+	ldr	r9,[sp,#4*(16+11)]
+	add	r3,r3,r7
+	mov	r10,r10,ror#16
+	eor	r14,r14,r2,ror#16
+	eor	r10,r10,r3,ror#16
+	add	r8,r8,r14
+	mov	r6,r6,ror#20
+	add	r9,r9,r10
+	mov	r7,r7,ror#20
+	eor	r6,r6,r8,ror#20
+	eor	r7,r7,r9,ror#20
+	add	r2,r2,r6
+	mov	r14,r14,ror#24
+	add	r3,r3,r7
+	mov	r10,r10,ror#24
+	eor	r14,r14,r2,ror#24
+	eor	r10,r10,r3,ror#24
+	add	r8,r8,r14
+	mov	r6,r6,ror#25
+	add	r9,r9,r10
+	mov	r7,r7,ror#25
+	eor	r6,r6,r8,ror#25
+	eor	r7,r7,r9,ror#25
+	add	r0,r0,r5
+	mov	r10,r10,ror#16
+	add	r1,r1,r6
+	mov	r12,r12,ror#16
+	eor	r10,r10,r0,ror#16
+	eor	r12,r12,r1,ror#16
+	add	r8,r8,r10
+	mov	r5,r5,ror#20
+	add	r9,r9,r12
+	mov	r6,r6,ror#20
+	eor	r5,r5,r8,ror#20
+	eor	r6,r6,r9,ror#20
+	add	r0,r0,r5
+	mov	r10,r10,ror#24
+	add	r1,r1,r6
+	mov	r12,r12,ror#24
+	eor	r10,r10,r0,ror#24
+	eor	r12,r12,r1,ror#24
+	add	r8,r8,r10
+	mov	r5,r5,ror#25
+	str	r10,[sp,#4*(16+15)]
+	ldr	r10,[sp,#4*(16+13)]
+	add	r9,r9,r12
+	mov	r6,r6,ror#25
+	eor	r5,r5,r8,ror#25
+	eor	r6,r6,r9,ror#25
+	str	r8,[sp,#4*(16+10)]
+	ldr	r8,[sp,#4*(16+8)]
+	add	r2,r2,r7
+	mov	r10,r10,ror#16
+	str	r9,[sp,#4*(16+11)]
+	ldr	r9,[sp,#4*(16+9)]
+	add	r3,r3,r4
+	mov	r14,r14,ror#16
+	eor	r10,r10,r2,ror#16
+	eor	r14,r14,r3,ror#16
+	add	r8,r8,r10
+	mov	r7,r7,ror#20
+	add	r9,r9,r14
+	mov	r4,r4,ror#20
+	eor	r7,r7,r8,ror#20
+	eor	r4,r4,r9,ror#20
+	add	r2,r2,r7
+	mov	r10,r10,ror#24
+	add	r3,r3,r4
+	mov	r14,r14,ror#24
+	eor	r10,r10,r2,ror#24
+	eor	r14,r14,r3,ror#24
+	add	r8,r8,r10
+	mov	r7,r7,ror#25
+	add	r9,r9,r14
+	mov	r4,r4,ror#25
+	eor	r7,r7,r8,ror#25
+	eor	r4,r4,r9,ror#25
+	bne	Loop
+
+	ldr	r11,[sp,#4*(32+2)]	@ load len
+
+	str	r8, [sp,#4*(16+8)]	@ modulo-scheduled store
+	str	r9, [sp,#4*(16+9)]
+	str	r12,[sp,#4*(16+12)]
+	str	r10, [sp,#4*(16+13)]
+	str	r14,[sp,#4*(16+14)]
+
+	@ at this point we have first half of 512-bit result in
+	@ rx and second half at sp+4*(16+8)
+
+	cmp	r11,#64		@ done yet?
+#ifdef	__thumb2__
+	itete	lo
+#endif
+	addlo	r12,sp,#4*(0)		@ shortcut or ...
+	ldrhs	r12,[sp,#4*(32+1)]	@ ... load inp
+	addlo	r14,sp,#4*(0)		@ shortcut or ...
+	ldrhs	r14,[sp,#4*(32+0)]	@ ... load out
+
+	ldr	r8,[sp,#4*(0)]	@ load key material
+	ldr	r9,[sp,#4*(1)]
+
+#if __ARM_ARCH__>=6 || !defined(__ARMEB__)
+# if __ARM_ARCH__<7
+	orr	r10,r12,r14
+	tst	r10,#3		@ are input and output aligned?
+	ldr	r10,[sp,#4*(2)]
+	bne	Lunaligned
+	cmp	r11,#64		@ restore flags
+# else
+	ldr	r10,[sp,#4*(2)]
+# endif
+	ldr	r11,[sp,#4*(3)]
+
+	add	r0,r0,r8	@ accumulate key material
+	add	r1,r1,r9
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	r8,[r12],#16		@ load input
+	ldrhs	r9,[r12,#-12]
+
+	add	r2,r2,r10
+	add	r3,r3,r11
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	r10,[r12,#-8]
+	ldrhs	r11,[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+# endif
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	r0,r0,r8	@ xor with input
+	eorhs	r1,r1,r9
+	add	r8,sp,#4*(4)
+	str	r0,[r14],#16		@ store output
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	r2,r2,r10
+	eorhs	r3,r3,r11
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+	str	r1,[r14,#-12]
+	str	r2,[r14,#-8]
+	str	r3,[r14,#-4]
+
+	add	r4,r4,r8	@ accumulate key material
+	add	r5,r5,r9
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	r8,[r12],#16		@ load input
+	ldrhs	r9,[r12,#-12]
+	add	r6,r6,r10
+	add	r7,r7,r11
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	r10,[r12,#-8]
+	ldrhs	r11,[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+	rev	r4,r4
+	rev	r5,r5
+	rev	r6,r6
+	rev	r7,r7
+# endif
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	r4,r4,r8
+	eorhs	r5,r5,r9
+	add	r8,sp,#4*(8)
+	str	r4,[r14],#16		@ store output
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	r6,r6,r10
+	eorhs	r7,r7,r11
+	str	r5,[r14,#-12]
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+	str	r6,[r14,#-8]
+	add	r0,sp,#4*(16+8)
+	str	r7,[r14,#-4]
+
+	ldmia	r0,{r0,r1,r2,r3,r4,r5,r6,r7}	@ load second half
+
+	add	r0,r0,r8	@ accumulate key material
+	add	r1,r1,r9
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	r8,[r12],#16		@ load input
+	ldrhs	r9,[r12,#-12]
+# ifdef	__thumb2__
+	itt	hi
+# endif
+	strhi	r10,[sp,#4*(16+10)]	@ copy "rx" while at it
+	strhi	r11,[sp,#4*(16+11)]	@ copy "rx" while at it
+	add	r2,r2,r10
+	add	r3,r3,r11
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	r10,[r12,#-8]
+	ldrhs	r11,[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+# endif
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	r0,r0,r8
+	eorhs	r1,r1,r9
+	add	r8,sp,#4*(12)
+	str	r0,[r14],#16		@ store output
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	r2,r2,r10
+	eorhs	r3,r3,r11
+	str	r1,[r14,#-12]
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+	str	r2,[r14,#-8]
+	str	r3,[r14,#-4]
+
+	add	r4,r4,r8	@ accumulate key material
+	add	r5,r5,r9
+# ifdef	__thumb2__
+	itt	hi
+# endif
+	addhi	r8,r8,#1		@ next counter value
+	strhi	r8,[sp,#4*(12)]	@ save next counter value
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	r8,[r12],#16		@ load input
+	ldrhs	r9,[r12,#-12]
+	add	r6,r6,r10
+	add	r7,r7,r11
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	r10,[r12,#-8]
+	ldrhs	r11,[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+	rev	r4,r4
+	rev	r5,r5
+	rev	r6,r6
+	rev	r7,r7
+# endif
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	r4,r4,r8
+	eorhs	r5,r5,r9
+# ifdef	__thumb2__
+	it	ne
+# endif
+	ldrne	r8,[sp,#4*(32+2)]	@ re-load len
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	r6,r6,r10
+	eorhs	r7,r7,r11
+	str	r4,[r14],#16		@ store output
+	str	r5,[r14,#-12]
+# ifdef	__thumb2__
+	it	hs
+# endif
+	subhs	r11,r8,#64		@ len-=64
+	str	r6,[r14,#-8]
+	str	r7,[r14,#-4]
+	bhi	Loop_outer
+
+	beq	Ldone
+# if __ARM_ARCH__<7
+	b	Ltail
+
+.align	4
+Lunaligned:@ unaligned endian-neutral path
+	cmp	r11,#64		@ restore flags
+# endif
+#endif
+#if __ARM_ARCH__<7
+	ldr	r11,[sp,#4*(3)]
+	add	r0,r0,r8		@ accumulate key material
+	add	r1,r1,r9
+	add	r2,r2,r10
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	r8,r8,r8		@ zero or ...
+	ldrhsb	r8,[r12],#16			@ ... load input
+	eorlo	r9,r9,r9
+	ldrhsb	r9,[r12,#-12]
+
+	add	r3,r3,r11
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	r10,r10,r10
+	ldrhsb	r10,[r12,#-8]
+	eorlo	r11,r11,r11
+	ldrhsb	r11,[r12,#-4]
+
+	eor	r0,r8,r0		@ xor with input (or zero)
+	eor	r1,r9,r1
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-15]		@ load more input
+	ldrhsb	r9,[r12,#-11]
+	eor	r2,r10,r2
+	strb	r0,[r14],#16		@ store output
+	eor	r3,r11,r3
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-7]
+	ldrhsb	r11,[r12,#-3]
+	strb	r1,[r14,#-12]
+	eor	r0,r8,r0,lsr#8
+	strb	r2,[r14,#-8]
+	eor	r1,r9,r1,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-14]		@ load more input
+	ldrhsb	r9,[r12,#-10]
+	strb	r3,[r14,#-4]
+	eor	r2,r10,r2,lsr#8
+	strb	r0,[r14,#-15]
+	eor	r3,r11,r3,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-6]
+	ldrhsb	r11,[r12,#-2]
+	strb	r1,[r14,#-11]
+	eor	r0,r8,r0,lsr#8
+	strb	r2,[r14,#-7]
+	eor	r1,r9,r1,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-13]		@ load more input
+	ldrhsb	r9,[r12,#-9]
+	strb	r3,[r14,#-3]
+	eor	r2,r10,r2,lsr#8
+	strb	r0,[r14,#-14]
+	eor	r3,r11,r3,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-5]
+	ldrhsb	r11,[r12,#-1]
+	strb	r1,[r14,#-10]
+	strb	r2,[r14,#-6]
+	eor	r0,r8,r0,lsr#8
+	strb	r3,[r14,#-2]
+	eor	r1,r9,r1,lsr#8
+	strb	r0,[r14,#-13]
+	eor	r2,r10,r2,lsr#8
+	strb	r1,[r14,#-9]
+	eor	r3,r11,r3,lsr#8
+	strb	r2,[r14,#-5]
+	strb	r3,[r14,#-1]
+	add	r8,sp,#4*(4+0)
+	ldmia	r8,{r8,r9,r10,r11}		@ load key material
+	add	r0,sp,#4*(16+8)
+	add	r4,r4,r8		@ accumulate key material
+	add	r5,r5,r9
+	add	r6,r6,r10
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	r8,r8,r8		@ zero or ...
+	ldrhsb	r8,[r12],#16			@ ... load input
+	eorlo	r9,r9,r9
+	ldrhsb	r9,[r12,#-12]
+
+	add	r7,r7,r11
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	r10,r10,r10
+	ldrhsb	r10,[r12,#-8]
+	eorlo	r11,r11,r11
+	ldrhsb	r11,[r12,#-4]
+
+	eor	r4,r8,r4		@ xor with input (or zero)
+	eor	r5,r9,r5
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-15]		@ load more input
+	ldrhsb	r9,[r12,#-11]
+	eor	r6,r10,r6
+	strb	r4,[r14],#16		@ store output
+	eor	r7,r11,r7
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-7]
+	ldrhsb	r11,[r12,#-3]
+	strb	r5,[r14,#-12]
+	eor	r4,r8,r4,lsr#8
+	strb	r6,[r14,#-8]
+	eor	r5,r9,r5,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-14]		@ load more input
+	ldrhsb	r9,[r12,#-10]
+	strb	r7,[r14,#-4]
+	eor	r6,r10,r6,lsr#8
+	strb	r4,[r14,#-15]
+	eor	r7,r11,r7,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-6]
+	ldrhsb	r11,[r12,#-2]
+	strb	r5,[r14,#-11]
+	eor	r4,r8,r4,lsr#8
+	strb	r6,[r14,#-7]
+	eor	r5,r9,r5,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-13]		@ load more input
+	ldrhsb	r9,[r12,#-9]
+	strb	r7,[r14,#-3]
+	eor	r6,r10,r6,lsr#8
+	strb	r4,[r14,#-14]
+	eor	r7,r11,r7,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-5]
+	ldrhsb	r11,[r12,#-1]
+	strb	r5,[r14,#-10]
+	strb	r6,[r14,#-6]
+	eor	r4,r8,r4,lsr#8
+	strb	r7,[r14,#-2]
+	eor	r5,r9,r5,lsr#8
+	strb	r4,[r14,#-13]
+	eor	r6,r10,r6,lsr#8
+	strb	r5,[r14,#-9]
+	eor	r7,r11,r7,lsr#8
+	strb	r6,[r14,#-5]
+	strb	r7,[r14,#-1]
+	add	r8,sp,#4*(4+4)
+	ldmia	r8,{r8,r9,r10,r11}		@ load key material
+	ldmia	r0,{r0,r1,r2,r3,r4,r5,r6,r7}		@ load second half
+# ifdef	__thumb2__
+	itt	hi
+# endif
+	strhi	r10,[sp,#4*(16+10)]		@ copy "rx"
+	strhi	r11,[sp,#4*(16+11)]		@ copy "rx"
+	add	r0,r0,r8		@ accumulate key material
+	add	r1,r1,r9
+	add	r2,r2,r10
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	r8,r8,r8		@ zero or ...
+	ldrhsb	r8,[r12],#16			@ ... load input
+	eorlo	r9,r9,r9
+	ldrhsb	r9,[r12,#-12]
+
+	add	r3,r3,r11
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	r10,r10,r10
+	ldrhsb	r10,[r12,#-8]
+	eorlo	r11,r11,r11
+	ldrhsb	r11,[r12,#-4]
+
+	eor	r0,r8,r0		@ xor with input (or zero)
+	eor	r1,r9,r1
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-15]		@ load more input
+	ldrhsb	r9,[r12,#-11]
+	eor	r2,r10,r2
+	strb	r0,[r14],#16		@ store output
+	eor	r3,r11,r3
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-7]
+	ldrhsb	r11,[r12,#-3]
+	strb	r1,[r14,#-12]
+	eor	r0,r8,r0,lsr#8
+	strb	r2,[r14,#-8]
+	eor	r1,r9,r1,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-14]		@ load more input
+	ldrhsb	r9,[r12,#-10]
+	strb	r3,[r14,#-4]
+	eor	r2,r10,r2,lsr#8
+	strb	r0,[r14,#-15]
+	eor	r3,r11,r3,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-6]
+	ldrhsb	r11,[r12,#-2]
+	strb	r1,[r14,#-11]
+	eor	r0,r8,r0,lsr#8
+	strb	r2,[r14,#-7]
+	eor	r1,r9,r1,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-13]		@ load more input
+	ldrhsb	r9,[r12,#-9]
+	strb	r3,[r14,#-3]
+	eor	r2,r10,r2,lsr#8
+	strb	r0,[r14,#-14]
+	eor	r3,r11,r3,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-5]
+	ldrhsb	r11,[r12,#-1]
+	strb	r1,[r14,#-10]
+	strb	r2,[r14,#-6]
+	eor	r0,r8,r0,lsr#8
+	strb	r3,[r14,#-2]
+	eor	r1,r9,r1,lsr#8
+	strb	r0,[r14,#-13]
+	eor	r2,r10,r2,lsr#8
+	strb	r1,[r14,#-9]
+	eor	r3,r11,r3,lsr#8
+	strb	r2,[r14,#-5]
+	strb	r3,[r14,#-1]
+	add	r8,sp,#4*(4+8)
+	ldmia	r8,{r8,r9,r10,r11}		@ load key material
+	add	r4,r4,r8		@ accumulate key material
+# ifdef	__thumb2__
+	itt	hi
+# endif
+	addhi	r8,r8,#1			@ next counter value
+	strhi	r8,[sp,#4*(12)]		@ save next counter value
+	add	r5,r5,r9
+	add	r6,r6,r10
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	r8,r8,r8		@ zero or ...
+	ldrhsb	r8,[r12],#16			@ ... load input
+	eorlo	r9,r9,r9
+	ldrhsb	r9,[r12,#-12]
+
+	add	r7,r7,r11
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	r10,r10,r10
+	ldrhsb	r10,[r12,#-8]
+	eorlo	r11,r11,r11
+	ldrhsb	r11,[r12,#-4]
+
+	eor	r4,r8,r4		@ xor with input (or zero)
+	eor	r5,r9,r5
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-15]		@ load more input
+	ldrhsb	r9,[r12,#-11]
+	eor	r6,r10,r6
+	strb	r4,[r14],#16		@ store output
+	eor	r7,r11,r7
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-7]
+	ldrhsb	r11,[r12,#-3]
+	strb	r5,[r14,#-12]
+	eor	r4,r8,r4,lsr#8
+	strb	r6,[r14,#-8]
+	eor	r5,r9,r5,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-14]		@ load more input
+	ldrhsb	r9,[r12,#-10]
+	strb	r7,[r14,#-4]
+	eor	r6,r10,r6,lsr#8
+	strb	r4,[r14,#-15]
+	eor	r7,r11,r7,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-6]
+	ldrhsb	r11,[r12,#-2]
+	strb	r5,[r14,#-11]
+	eor	r4,r8,r4,lsr#8
+	strb	r6,[r14,#-7]
+	eor	r5,r9,r5,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-13]		@ load more input
+	ldrhsb	r9,[r12,#-9]
+	strb	r7,[r14,#-3]
+	eor	r6,r10,r6,lsr#8
+	strb	r4,[r14,#-14]
+	eor	r7,r11,r7,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-5]
+	ldrhsb	r11,[r12,#-1]
+	strb	r5,[r14,#-10]
+	strb	r6,[r14,#-6]
+	eor	r4,r8,r4,lsr#8
+	strb	r7,[r14,#-2]
+	eor	r5,r9,r5,lsr#8
+	strb	r4,[r14,#-13]
+	eor	r6,r10,r6,lsr#8
+	strb	r5,[r14,#-9]
+	eor	r7,r11,r7,lsr#8
+	strb	r6,[r14,#-5]
+	strb	r7,[r14,#-1]
+# ifdef	__thumb2__
+	it	ne
+# endif
+	ldrne	r8,[sp,#4*(32+2)]		@ re-load len
+# ifdef	__thumb2__
+	it	hs
+# endif
+	subhs	r11,r8,#64			@ len-=64
+	bhi	Loop_outer
+
+	beq	Ldone
+#endif
+
+Ltail:
+	ldr	r12,[sp,#4*(32+1)]	@ load inp
+	add	r9,sp,#4*(0)
+	ldr	r14,[sp,#4*(32+0)]	@ load out
+
+Loop_tail:
+	ldrb	r10,[r9],#1	@ read buffer on stack
+	ldrb	r11,[r12],#1		@ read input
+	subs	r8,r8,#1
+	eor	r11,r11,r10
+	strb	r11,[r14],#1		@ store output
+	bne	Loop_tail
+
+Ldone:
+	add	sp,sp,#4*(32+3)
+Lno_data:
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,pc}
+
+#if __ARM_MAX_ARCH__>=7
+
+
+
+
+.align	5
+ChaCha20_neon:
+	ldr	r12,[sp,#0]		@ pull pointer to counter and nonce
+	stmdb	sp!,{r0,r1,r2,r4-r11,lr}
+LChaCha20_neon:
+	adr	r14,Lsigma
+	vstmdb	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}		@ ABI spec says so
+	stmdb	sp!,{r0,r1,r2,r3}
+
+	vld1.32	{q1,q2},[r3]		@ load key
+	ldmia	r3,{r4,r5,r6,r7,r8,r9,r10,r11}		@ load key
+
+	sub	sp,sp,#4*(16+16)
+	vld1.32	{q3},[r12]		@ load counter and nonce
+	add	r12,sp,#4*8
+	ldmia	r14,{r0,r1,r2,r3}		@ load sigma
+	vld1.32	{q0},[r14]!		@ load sigma
+	vld1.32	{q12},[r14]		@ one
+	vst1.32	{q2,q3},[r12]		@ copy 1/2key|counter|nonce
+	vst1.32	{q0,q1},[sp]		@ copy sigma|1/2key
+
+	str	r10,[sp,#4*(16+10)]	@ off-load "rx"
+	str	r11,[sp,#4*(16+11)]	@ off-load "rx"
+	vshl.i32	d26,d24,#1	@ two
+	vstr	d24,[sp,#4*(16+0)]
+	vshl.i32	d28,d24,#2	@ four
+	vstr	d26,[sp,#4*(16+2)]
+	vmov	q4,q0
+	vstr	d28,[sp,#4*(16+4)]
+	vmov	q8,q0
+	vmov	q5,q1
+	vmov	q9,q1
+	b	Loop_neon_enter
+
+.align	4
+Loop_neon_outer:
+	ldmia	sp,{r0,r1,r2,r3,r4,r5,r6,r7,r8,r9}		@ load key material
+	cmp	r11,#64*2		@ if len<=64*2
+	bls	Lbreak_neon		@ switch to integer-only
+	vmov	q4,q0
+	str	r11,[sp,#4*(32+2)]	@ save len
+	vmov	q8,q0
+	str	r12,  [sp,#4*(32+1)]	@ save inp
+	vmov	q5,q1
+	str	r14,  [sp,#4*(32+0)]	@ save out
+	vmov	q9,q1
+Loop_neon_enter:
+	ldr	r11, [sp,#4*(15)]
+	vadd.i32	q7,q3,q12		@ counter+1
+	ldr	r12,[sp,#4*(12)]	@ modulo-scheduled load
+	vmov	q6,q2
+	ldr	r10, [sp,#4*(13)]
+	vmov	q10,q2
+	ldr	r14,[sp,#4*(14)]
+	vadd.i32	q11,q7,q12		@ counter+2
+	str	r11, [sp,#4*(16+15)]
+	mov	r11,#10
+	add	r12,r12,#3	@ counter+3
+	b	Loop_neon
+
+.align	4
+Loop_neon:
+	subs	r11,r11,#1
+	vadd.i32	q0,q0,q1
+	add	r0,r0,r4
+	vadd.i32	q4,q4,q5
+	mov	r12,r12,ror#16
+	vadd.i32	q8,q8,q9
+	add	r1,r1,r5
+	veor	q3,q3,q0
+	mov	r10,r10,ror#16
+	veor	q7,q7,q4
+	eor	r12,r12,r0,ror#16
+	veor	q11,q11,q8
+	eor	r10,r10,r1,ror#16
+	vrev32.16	q3,q3
+	add	r8,r8,r12
+	vrev32.16	q7,q7
+	mov	r4,r4,ror#20
+	vrev32.16	q11,q11
+	add	r9,r9,r10
+	vadd.i32	q2,q2,q3
+	mov	r5,r5,ror#20
+	vadd.i32	q6,q6,q7
+	eor	r4,r4,r8,ror#20
+	vadd.i32	q10,q10,q11
+	eor	r5,r5,r9,ror#20
+	veor	q12,q1,q2
+	add	r0,r0,r4
+	veor	q13,q5,q6
+	mov	r12,r12,ror#24
+	veor	q14,q9,q10
+	add	r1,r1,r5
+	vshr.u32	q1,q12,#20
+	mov	r10,r10,ror#24
+	vshr.u32	q5,q13,#20
+	eor	r12,r12,r0,ror#24
+	vshr.u32	q9,q14,#20
+	eor	r10,r10,r1,ror#24
+	vsli.32	q1,q12,#12
+	add	r8,r8,r12
+	vsli.32	q5,q13,#12
+	mov	r4,r4,ror#25
+	vsli.32	q9,q14,#12
+	add	r9,r9,r10
+	vadd.i32	q0,q0,q1
+	mov	r5,r5,ror#25
+	vadd.i32	q4,q4,q5
+	str	r10,[sp,#4*(16+13)]
+	vadd.i32	q8,q8,q9
+	ldr	r10,[sp,#4*(16+15)]
+	veor	q12,q3,q0
+	eor	r4,r4,r8,ror#25
+	veor	q13,q7,q4
+	eor	r5,r5,r9,ror#25
+	veor	q14,q11,q8
+	str	r8,[sp,#4*(16+8)]
+	vshr.u32	q3,q12,#24
+	ldr	r8,[sp,#4*(16+10)]
+	vshr.u32	q7,q13,#24
+	add	r2,r2,r6
+	vshr.u32	q11,q14,#24
+	mov	r14,r14,ror#16
+	vsli.32	q3,q12,#8
+	str	r9,[sp,#4*(16+9)]
+	vsli.32	q7,q13,#8
+	ldr	r9,[sp,#4*(16+11)]
+	vsli.32	q11,q14,#8
+	add	r3,r3,r7
+	vadd.i32	q2,q2,q3
+	mov	r10,r10,ror#16
+	vadd.i32	q6,q6,q7
+	eor	r14,r14,r2,ror#16
+	vadd.i32	q10,q10,q11
+	eor	r10,r10,r3,ror#16
+	veor	q12,q1,q2
+	add	r8,r8,r14
+	veor	q13,q5,q6
+	mov	r6,r6,ror#20
+	veor	q14,q9,q10
+	add	r9,r9,r10
+	vshr.u32	q1,q12,#25
+	mov	r7,r7,ror#20
+	vshr.u32	q5,q13,#25
+	eor	r6,r6,r8,ror#20
+	vshr.u32	q9,q14,#25
+	eor	r7,r7,r9,ror#20
+	vsli.32	q1,q12,#7
+	add	r2,r2,r6
+	vsli.32	q5,q13,#7
+	mov	r14,r14,ror#24
+	vsli.32	q9,q14,#7
+	add	r3,r3,r7
+	vext.8	q2,q2,q2,#8
+	mov	r10,r10,ror#24
+	vext.8	q6,q6,q6,#8
+	eor	r14,r14,r2,ror#24
+	vext.8	q10,q10,q10,#8
+	eor	r10,r10,r3,ror#24
+	vext.8	q1,q1,q1,#4
+	add	r8,r8,r14
+	vext.8	q5,q5,q5,#4
+	mov	r6,r6,ror#25
+	vext.8	q9,q9,q9,#4
+	add	r9,r9,r10
+	vext.8	q3,q3,q3,#12
+	mov	r7,r7,ror#25
+	vext.8	q7,q7,q7,#12
+	eor	r6,r6,r8,ror#25
+	vext.8	q11,q11,q11,#12
+	eor	r7,r7,r9,ror#25
+	vadd.i32	q0,q0,q1
+	add	r0,r0,r5
+	vadd.i32	q4,q4,q5
+	mov	r10,r10,ror#16
+	vadd.i32	q8,q8,q9
+	add	r1,r1,r6
+	veor	q3,q3,q0
+	mov	r12,r12,ror#16
+	veor	q7,q7,q4
+	eor	r10,r10,r0,ror#16
+	veor	q11,q11,q8
+	eor	r12,r12,r1,ror#16
+	vrev32.16	q3,q3
+	add	r8,r8,r10
+	vrev32.16	q7,q7
+	mov	r5,r5,ror#20
+	vrev32.16	q11,q11
+	add	r9,r9,r12
+	vadd.i32	q2,q2,q3
+	mov	r6,r6,ror#20
+	vadd.i32	q6,q6,q7
+	eor	r5,r5,r8,ror#20
+	vadd.i32	q10,q10,q11
+	eor	r6,r6,r9,ror#20
+	veor	q12,q1,q2
+	add	r0,r0,r5
+	veor	q13,q5,q6
+	mov	r10,r10,ror#24
+	veor	q14,q9,q10
+	add	r1,r1,r6
+	vshr.u32	q1,q12,#20
+	mov	r12,r12,ror#24
+	vshr.u32	q5,q13,#20
+	eor	r10,r10,r0,ror#24
+	vshr.u32	q9,q14,#20
+	eor	r12,r12,r1,ror#24
+	vsli.32	q1,q12,#12
+	add	r8,r8,r10
+	vsli.32	q5,q13,#12
+	mov	r5,r5,ror#25
+	vsli.32	q9,q14,#12
+	str	r10,[sp,#4*(16+15)]
+	vadd.i32	q0,q0,q1
+	ldr	r10,[sp,#4*(16+13)]
+	vadd.i32	q4,q4,q5
+	add	r9,r9,r12
+	vadd.i32	q8,q8,q9
+	mov	r6,r6,ror#25
+	veor	q12,q3,q0
+	eor	r5,r5,r8,ror#25
+	veor	q13,q7,q4
+	eor	r6,r6,r9,ror#25
+	veor	q14,q11,q8
+	str	r8,[sp,#4*(16+10)]
+	vshr.u32	q3,q12,#24
+	ldr	r8,[sp,#4*(16+8)]
+	vshr.u32	q7,q13,#24
+	add	r2,r2,r7
+	vshr.u32	q11,q14,#24
+	mov	r10,r10,ror#16
+	vsli.32	q3,q12,#8
+	str	r9,[sp,#4*(16+11)]
+	vsli.32	q7,q13,#8
+	ldr	r9,[sp,#4*(16+9)]
+	vsli.32	q11,q14,#8
+	add	r3,r3,r4
+	vadd.i32	q2,q2,q3
+	mov	r14,r14,ror#16
+	vadd.i32	q6,q6,q7
+	eor	r10,r10,r2,ror#16
+	vadd.i32	q10,q10,q11
+	eor	r14,r14,r3,ror#16
+	veor	q12,q1,q2
+	add	r8,r8,r10
+	veor	q13,q5,q6
+	mov	r7,r7,ror#20
+	veor	q14,q9,q10
+	add	r9,r9,r14
+	vshr.u32	q1,q12,#25
+	mov	r4,r4,ror#20
+	vshr.u32	q5,q13,#25
+	eor	r7,r7,r8,ror#20
+	vshr.u32	q9,q14,#25
+	eor	r4,r4,r9,ror#20
+	vsli.32	q1,q12,#7
+	add	r2,r2,r7
+	vsli.32	q5,q13,#7
+	mov	r10,r10,ror#24
+	vsli.32	q9,q14,#7
+	add	r3,r3,r4
+	vext.8	q2,q2,q2,#8
+	mov	r14,r14,ror#24
+	vext.8	q6,q6,q6,#8
+	eor	r10,r10,r2,ror#24
+	vext.8	q10,q10,q10,#8
+	eor	r14,r14,r3,ror#24
+	vext.8	q1,q1,q1,#12
+	add	r8,r8,r10
+	vext.8	q5,q5,q5,#12
+	mov	r7,r7,ror#25
+	vext.8	q9,q9,q9,#12
+	add	r9,r9,r14
+	vext.8	q3,q3,q3,#4
+	mov	r4,r4,ror#25
+	vext.8	q7,q7,q7,#4
+	eor	r7,r7,r8,ror#25
+	vext.8	q11,q11,q11,#4
+	eor	r4,r4,r9,ror#25
+	bne	Loop_neon
+
+	add	r11,sp,#32
+	vld1.32	{q12,q13},[sp]		@ load key material
+	vld1.32	{q14,q15},[r11]
+
+	ldr	r11,[sp,#4*(32+2)]	@ load len
+
+	str	r8, [sp,#4*(16+8)]	@ modulo-scheduled store
+	str	r9, [sp,#4*(16+9)]
+	str	r12,[sp,#4*(16+12)]
+	str	r10, [sp,#4*(16+13)]
+	str	r14,[sp,#4*(16+14)]
+
+	@ at this point we have first half of 512-bit result in
+	@ rx and second half at sp+4*(16+8)
+
+	ldr	r12,[sp,#4*(32+1)]	@ load inp
+	ldr	r14,[sp,#4*(32+0)]	@ load out
+
+	vadd.i32	q0,q0,q12		@ accumulate key material
+	vadd.i32	q4,q4,q12
+	vadd.i32	q8,q8,q12
+	vldr	d24,[sp,#4*(16+0)]	@ one
+
+	vadd.i32	q1,q1,q13
+	vadd.i32	q5,q5,q13
+	vadd.i32	q9,q9,q13
+	vldr	d26,[sp,#4*(16+2)]	@ two
+
+	vadd.i32	q2,q2,q14
+	vadd.i32	q6,q6,q14
+	vadd.i32	q10,q10,q14
+	vadd.i32	d14,d14,d24	@ counter+1
+	vadd.i32	d22,d22,d26	@ counter+2
+
+	vadd.i32	q3,q3,q15
+	vadd.i32	q7,q7,q15
+	vadd.i32	q11,q11,q15
+
+	cmp	r11,#64*4
+	blo	Ltail_neon
+
+	vld1.8	{q12,q13},[r12]!	@ load input
+	mov	r11,sp
+	vld1.8	{q14,q15},[r12]!
+	veor	q0,q0,q12		@ xor with input
+	veor	q1,q1,q13
+	vld1.8	{q12,q13},[r12]!
+	veor	q2,q2,q14
+	veor	q3,q3,q15
+	vld1.8	{q14,q15},[r12]!
+
+	veor	q4,q4,q12
+	vst1.8	{q0,q1},[r14]!	@ store output
+	veor	q5,q5,q13
+	vld1.8	{q12,q13},[r12]!
+	veor	q6,q6,q14
+	vst1.8	{q2,q3},[r14]!
+	veor	q7,q7,q15
+	vld1.8	{q14,q15},[r12]!
+
+	veor	q8,q8,q12
+	vld1.32	{q0,q1},[r11]!	@ load for next iteration
+	veor	d25,d25,d25
+	vldr	d24,[sp,#4*(16+4)]	@ four
+	veor	q9,q9,q13
+	vld1.32	{q2,q3},[r11]
+	veor	q10,q10,q14
+	vst1.8	{q4,q5},[r14]!
+	veor	q11,q11,q15
+	vst1.8	{q6,q7},[r14]!
+
+	vadd.i32	d6,d6,d24	@ next counter value
+	vldr	d24,[sp,#4*(16+0)]	@ one
+
+	ldmia	sp,{r8,r9,r10,r11}	@ load key material
+	add	r0,r0,r8	@ accumulate key material
+	ldr	r8,[r12],#16		@ load input
+	vst1.8	{q8,q9},[r14]!
+	add	r1,r1,r9
+	ldr	r9,[r12,#-12]
+	vst1.8	{q10,q11},[r14]!
+	add	r2,r2,r10
+	ldr	r10,[r12,#-8]
+	add	r3,r3,r11
+	ldr	r11,[r12,#-4]
+# ifdef	__ARMEB__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+# endif
+	eor	r0,r0,r8	@ xor with input
+	add	r8,sp,#4*(4)
+	eor	r1,r1,r9
+	str	r0,[r14],#16		@ store output
+	eor	r2,r2,r10
+	str	r1,[r14,#-12]
+	eor	r3,r3,r11
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+	str	r2,[r14,#-8]
+	str	r3,[r14,#-4]
+
+	add	r4,r4,r8	@ accumulate key material
+	ldr	r8,[r12],#16		@ load input
+	add	r5,r5,r9
+	ldr	r9,[r12,#-12]
+	add	r6,r6,r10
+	ldr	r10,[r12,#-8]
+	add	r7,r7,r11
+	ldr	r11,[r12,#-4]
+# ifdef	__ARMEB__
+	rev	r4,r4
+	rev	r5,r5
+	rev	r6,r6
+	rev	r7,r7
+# endif
+	eor	r4,r4,r8
+	add	r8,sp,#4*(8)
+	eor	r5,r5,r9
+	str	r4,[r14],#16		@ store output
+	eor	r6,r6,r10
+	str	r5,[r14,#-12]
+	eor	r7,r7,r11
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+	str	r6,[r14,#-8]
+	add	r0,sp,#4*(16+8)
+	str	r7,[r14,#-4]
+
+	ldmia	r0,{r0,r1,r2,r3,r4,r5,r6,r7}	@ load second half
+
+	add	r0,r0,r8	@ accumulate key material
+	ldr	r8,[r12],#16		@ load input
+	add	r1,r1,r9
+	ldr	r9,[r12,#-12]
+# ifdef	__thumb2__
+	it	hi
+# endif
+	strhi	r10,[sp,#4*(16+10)]	@ copy "rx" while at it
+	add	r2,r2,r10
+	ldr	r10,[r12,#-8]
+# ifdef	__thumb2__
+	it	hi
+# endif
+	strhi	r11,[sp,#4*(16+11)]	@ copy "rx" while at it
+	add	r3,r3,r11
+	ldr	r11,[r12,#-4]
+# ifdef	__ARMEB__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+# endif
+	eor	r0,r0,r8
+	add	r8,sp,#4*(12)
+	eor	r1,r1,r9
+	str	r0,[r14],#16		@ store output
+	eor	r2,r2,r10
+	str	r1,[r14,#-12]
+	eor	r3,r3,r11
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+	str	r2,[r14,#-8]
+	str	r3,[r14,#-4]
+
+	add	r4,r4,r8	@ accumulate key material
+	add	r8,r8,#4		@ next counter value
+	add	r5,r5,r9
+	str	r8,[sp,#4*(12)]	@ save next counter value
+	ldr	r8,[r12],#16		@ load input
+	add	r6,r6,r10
+	add	r4,r4,#3		@ counter+3
+	ldr	r9,[r12,#-12]
+	add	r7,r7,r11
+	ldr	r10,[r12,#-8]
+	ldr	r11,[r12,#-4]
+# ifdef	__ARMEB__
+	rev	r4,r4
+	rev	r5,r5
+	rev	r6,r6
+	rev	r7,r7
+# endif
+	eor	r4,r4,r8
+# ifdef	__thumb2__
+	it	hi
+# endif
+	ldrhi	r8,[sp,#4*(32+2)]	@ re-load len
+	eor	r5,r5,r9
+	eor	r6,r6,r10
+	str	r4,[r14],#16		@ store output
+	eor	r7,r7,r11
+	str	r5,[r14,#-12]
+	sub	r11,r8,#64*4	@ len-=64*4
+	str	r6,[r14,#-8]
+	str	r7,[r14,#-4]
+	bhi	Loop_neon_outer
+
+	b	Ldone_neon
+
+.align	4
+Lbreak_neon:
+	@ harmonize NEON and integer-only stack frames: load data
+	@ from NEON frame, but save to integer-only one; distance
+	@ between the two is 4*(32+4+16-32)=4*(20).
+
+	str	r11, [sp,#4*(20+32+2)]	@ save len
+	add	r11,sp,#4*(32+4)
+	str	r12,   [sp,#4*(20+32+1)]	@ save inp
+	str	r14,   [sp,#4*(20+32+0)]	@ save out
+
+	ldr	r12,[sp,#4*(16+10)]
+	ldr	r14,[sp,#4*(16+11)]
+	vldmia	r11,{d8,d9,d10,d11,d12,d13,d14,d15}			@ fulfill ABI requirement
+	str	r12,[sp,#4*(20+16+10)]	@ copy "rx"
+	str	r14,[sp,#4*(20+16+11)]	@ copy "rx"
+
+	ldr	r11, [sp,#4*(15)]
+	ldr	r12,[sp,#4*(12)]		@ modulo-scheduled load
+	ldr	r10, [sp,#4*(13)]
+	ldr	r14,[sp,#4*(14)]
+	str	r11, [sp,#4*(20+16+15)]
+	add	r11,sp,#4*(20)
+	vst1.32	{q0,q1},[r11]!		@ copy key
+	add	sp,sp,#4*(20)			@ switch frame
+	vst1.32	{q2,q3},[r11]
+	mov	r11,#10
+	b	Loop				@ go integer-only
+
+.align	4
+Ltail_neon:
+	cmp	r11,#64*3
+	bhs	L192_or_more_neon
+	cmp	r11,#64*2
+	bhs	L128_or_more_neon
+	cmp	r11,#64*1
+	bhs	L64_or_more_neon
+
+	add	r8,sp,#4*(8)
+	vst1.8	{q0,q1},[sp]
+	add	r10,sp,#4*(0)
+	vst1.8	{q2,q3},[r8]
+	b	Loop_tail_neon
+
+.align	4
+L64_or_more_neon:
+	vld1.8	{q12,q13},[r12]!
+	vld1.8	{q14,q15},[r12]!
+	veor	q0,q0,q12
+	veor	q1,q1,q13
+	veor	q2,q2,q14
+	veor	q3,q3,q15
+	vst1.8	{q0,q1},[r14]!
+	vst1.8	{q2,q3},[r14]!
+
+	beq	Ldone_neon
+
+	add	r8,sp,#4*(8)
+	vst1.8	{q4,q5},[sp]
+	add	r10,sp,#4*(0)
+	vst1.8	{q6,q7},[r8]
+	sub	r11,r11,#64*1	@ len-=64*1
+	b	Loop_tail_neon
+
+.align	4
+L128_or_more_neon:
+	vld1.8	{q12,q13},[r12]!
+	vld1.8	{q14,q15},[r12]!
+	veor	q0,q0,q12
+	veor	q1,q1,q13
+	vld1.8	{q12,q13},[r12]!
+	veor	q2,q2,q14
+	veor	q3,q3,q15
+	vld1.8	{q14,q15},[r12]!
+
+	veor	q4,q4,q12
+	veor	q5,q5,q13
+	vst1.8	{q0,q1},[r14]!
+	veor	q6,q6,q14
+	vst1.8	{q2,q3},[r14]!
+	veor	q7,q7,q15
+	vst1.8	{q4,q5},[r14]!
+	vst1.8	{q6,q7},[r14]!
+
+	beq	Ldone_neon
+
+	add	r8,sp,#4*(8)
+	vst1.8	{q8,q9},[sp]
+	add	r10,sp,#4*(0)
+	vst1.8	{q10,q11},[r8]
+	sub	r11,r11,#64*2	@ len-=64*2
+	b	Loop_tail_neon
+
+.align	4
+L192_or_more_neon:
+	vld1.8	{q12,q13},[r12]!
+	vld1.8	{q14,q15},[r12]!
+	veor	q0,q0,q12
+	veor	q1,q1,q13
+	vld1.8	{q12,q13},[r12]!
+	veor	q2,q2,q14
+	veor	q3,q3,q15
+	vld1.8	{q14,q15},[r12]!
+
+	veor	q4,q4,q12
+	veor	q5,q5,q13
+	vld1.8	{q12,q13},[r12]!
+	veor	q6,q6,q14
+	vst1.8	{q0,q1},[r14]!
+	veor	q7,q7,q15
+	vld1.8	{q14,q15},[r12]!
+
+	veor	q8,q8,q12
+	vst1.8	{q2,q3},[r14]!
+	veor	q9,q9,q13
+	vst1.8	{q4,q5},[r14]!
+	veor	q10,q10,q14
+	vst1.8	{q6,q7},[r14]!
+	veor	q11,q11,q15
+	vst1.8	{q8,q9},[r14]!
+	vst1.8	{q10,q11},[r14]!
+
+	beq	Ldone_neon
+
+	ldmia	sp,{r8,r9,r10,r11}	@ load key material
+	add	r0,r0,r8	@ accumulate key material
+	add	r8,sp,#4*(4)
+	add	r1,r1,r9
+	add	r2,r2,r10
+	add	r3,r3,r11
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+
+	add	r4,r4,r8	@ accumulate key material
+	add	r8,sp,#4*(8)
+	add	r5,r5,r9
+	add	r6,r6,r10
+	add	r7,r7,r11
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+# ifdef	__ARMEB__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+	rev	r4,r4
+	rev	r5,r5
+	rev	r6,r6
+	rev	r7,r7
+# endif
+	stmia	sp,{r0,r1,r2,r3,r4,r5,r6,r7}
+	add	r0,sp,#4*(16+8)
+
+	ldmia	r0,{r0,r1,r2,r3,r4,r5,r6,r7}	@ load second half
+
+	add	r0,r0,r8	@ accumulate key material
+	add	r8,sp,#4*(12)
+	add	r1,r1,r9
+	add	r2,r2,r10
+	add	r3,r3,r11
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+
+	add	r4,r4,r8	@ accumulate key material
+	add	r8,sp,#4*(8)
+	add	r5,r5,r9
+	add	r4,r4,#3		@ counter+3
+	add	r6,r6,r10
+	add	r7,r7,r11
+	ldr	r11,[sp,#4*(32+2)]	@ re-load len
+# ifdef	__ARMEB__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+	rev	r4,r4
+	rev	r5,r5
+	rev	r6,r6
+	rev	r7,r7
+# endif
+	stmia	r8,{r0,r1,r2,r3,r4,r5,r6,r7}
+	add	r10,sp,#4*(0)
+	sub	r11,r11,#64*3	@ len-=64*3
+
+Loop_tail_neon:
+	ldrb	r8,[r10],#1	@ read buffer on stack
+	ldrb	r9,[r12],#1		@ read input
+	subs	r11,r11,#1
+	eor	r8,r8,r9
+	strb	r8,[r14],#1		@ store output
+	bne	Loop_tail_neon
+
+Ldone_neon:
+	add	sp,sp,#4*(32+4)
+	vldmia	sp,{d8,d9,d10,d11,d12,d13,d14,d15}
+	add	sp,sp,#4*(16+3)
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,pc}
+
+.comm	_OPENSSL_armcap_P,4
+.non_lazy_symbol_pointer
+OPENSSL_armcap_P:
+.indirect_symbol	_OPENSSL_armcap_P
+.long	0
+#endif
diff --git a/third_party/boringssl/ios-arm/crypto/fipsmodule/aes-armv4.S b/third_party/boringssl/ios-arm/crypto/fipsmodule/aes-armv4.S
new file mode 100644
index 0000000..cddbb67
--- /dev/null
+++ b/third_party/boringssl/ios-arm/crypto/fipsmodule/aes-armv4.S
@@ -0,0 +1,1198 @@
+
+@ ====================================================================
+@ Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+@ project. The module is, however, dual licensed under OpenSSL and
+@ CRYPTOGAMS licenses depending on where you obtain it. For further
+@ details see http://www.openssl.org/~appro/cryptogams/.
+@ ====================================================================
+
+@ AES for ARMv4
+
+@ January 2007.
+@
+@ Code uses single 1K S-box and is >2 times faster than code generated
+@ by gcc-3.4.1. This is thanks to unique feature of ARMv4 ISA, which
+@ allows to merge logical or arithmetic operation with shift or rotate
+@ in one instruction and emit combined result every cycle. The module
+@ is endian-neutral. The performance is ~42 cycles/byte for 128-bit
+@ key [on single-issue Xscale PXA250 core].
+
+@ May 2007.
+@
+@ AES_set_[en|de]crypt_key is added.
+
+@ July 2010.
+@
+@ Rescheduling for dual-issue pipeline resulted in 12% improvement on
+@ Cortex A8 core and ~25 cycles per byte processed with 128-bit key.
+
+@ February 2011.
+@
+@ Profiler-assisted and platform-specific optimization resulted in 16%
+@ improvement on Cortex A8 core and ~21.5 cycles per byte.
+
+#if defined(__arm__)
+#ifndef __KERNEL__
+# include <openssl/arm_arch.h>
+#else
+# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+#endif
+
+.text
+#if __ARM_ARCH__<7
+.code	32
+#else
+.syntax	unified
+# if defined(__thumb2__) && !defined(__APPLE__)
+.thumb
+# else
+.code	32
+# endif
+#endif
+
+
+.align	5
+AES_Te:
+.word	0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d
+.word	0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554
+.word	0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d
+.word	0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a
+.word	0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87
+.word	0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b
+.word	0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea
+.word	0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b
+.word	0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a
+.word	0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f
+.word	0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108
+.word	0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f
+.word	0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e
+.word	0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5
+.word	0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d
+.word	0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f
+.word	0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e
+.word	0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb
+.word	0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce
+.word	0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497
+.word	0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c
+.word	0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed
+.word	0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b
+.word	0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a
+.word	0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16
+.word	0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594
+.word	0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81
+.word	0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3
+.word	0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a
+.word	0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504
+.word	0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163
+.word	0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d
+.word	0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f
+.word	0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739
+.word	0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47
+.word	0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395
+.word	0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f
+.word	0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883
+.word	0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c
+.word	0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76
+.word	0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e
+.word	0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4
+.word	0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6
+.word	0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b
+.word	0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7
+.word	0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0
+.word	0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25
+.word	0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818
+.word	0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72
+.word	0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651
+.word	0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21
+.word	0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85
+.word	0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa
+.word	0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12
+.word	0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0
+.word	0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9
+.word	0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133
+.word	0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7
+.word	0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920
+.word	0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a
+.word	0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17
+.word	0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8
+.word	0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11
+.word	0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a
+@ Te4[256]
+.byte	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5
+.byte	0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76
+.byte	0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0
+.byte	0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0
+.byte	0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc
+.byte	0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15
+.byte	0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a
+.byte	0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75
+.byte	0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0
+.byte	0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84
+.byte	0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b
+.byte	0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf
+.byte	0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85
+.byte	0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8
+.byte	0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5
+.byte	0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2
+.byte	0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17
+.byte	0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73
+.byte	0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88
+.byte	0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb
+.byte	0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c
+.byte	0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79
+.byte	0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9
+.byte	0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08
+.byte	0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6
+.byte	0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a
+.byte	0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e
+.byte	0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e
+.byte	0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94
+.byte	0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf
+.byte	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68
+.byte	0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+@ rcon[]
+.word	0x01000000, 0x02000000, 0x04000000, 0x08000000
+.word	0x10000000, 0x20000000, 0x40000000, 0x80000000
+.word	0x1B000000, 0x36000000, 0, 0, 0, 0, 0, 0
+
+
+@ void asm_AES_encrypt(const unsigned char *in, unsigned char *out,
+@ 		       const AES_KEY *key) {
+.globl	_asm_AES_encrypt
+.private_extern	_asm_AES_encrypt
+
+.align	5
+_asm_AES_encrypt:
+#if __ARM_ARCH__<7
+	sub	r3,pc,#8		@ _asm_AES_encrypt
+#else
+	adr	r3,_asm_AES_encrypt
+#endif
+	stmdb	sp!,{r1,r4-r12,lr}
+#ifdef	__APPLE__
+	adr	r10,AES_Te
+#else
+	sub	r10,r3,#_asm_AES_encrypt-AES_Te	@ Te
+#endif
+	mov	r12,r0		@ inp
+	mov	r11,r2
+#if __ARM_ARCH__<7
+	ldrb	r0,[r12,#3]	@ load input data in endian-neutral
+	ldrb	r4,[r12,#2]	@ manner...
+	ldrb	r5,[r12,#1]
+	ldrb	r6,[r12,#0]
+	orr	r0,r0,r4,lsl#8
+	ldrb	r1,[r12,#7]
+	orr	r0,r0,r5,lsl#16
+	ldrb	r4,[r12,#6]
+	orr	r0,r0,r6,lsl#24
+	ldrb	r5,[r12,#5]
+	ldrb	r6,[r12,#4]
+	orr	r1,r1,r4,lsl#8
+	ldrb	r2,[r12,#11]
+	orr	r1,r1,r5,lsl#16
+	ldrb	r4,[r12,#10]
+	orr	r1,r1,r6,lsl#24
+	ldrb	r5,[r12,#9]
+	ldrb	r6,[r12,#8]
+	orr	r2,r2,r4,lsl#8
+	ldrb	r3,[r12,#15]
+	orr	r2,r2,r5,lsl#16
+	ldrb	r4,[r12,#14]
+	orr	r2,r2,r6,lsl#24
+	ldrb	r5,[r12,#13]
+	ldrb	r6,[r12,#12]
+	orr	r3,r3,r4,lsl#8
+	orr	r3,r3,r5,lsl#16
+	orr	r3,r3,r6,lsl#24
+#else
+	ldr	r0,[r12,#0]
+	ldr	r1,[r12,#4]
+	ldr	r2,[r12,#8]
+	ldr	r3,[r12,#12]
+#ifdef __ARMEL__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+#endif
+#endif
+	bl	_armv4_AES_encrypt
+
+	ldr	r12,[sp],#4		@ pop out
+#if __ARM_ARCH__>=7
+#ifdef __ARMEL__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+#endif
+	str	r0,[r12,#0]
+	str	r1,[r12,#4]
+	str	r2,[r12,#8]
+	str	r3,[r12,#12]
+#else
+	mov	r4,r0,lsr#24		@ write output in endian-neutral
+	mov	r5,r0,lsr#16		@ manner...
+	mov	r6,r0,lsr#8
+	strb	r4,[r12,#0]
+	strb	r5,[r12,#1]
+	mov	r4,r1,lsr#24
+	strb	r6,[r12,#2]
+	mov	r5,r1,lsr#16
+	strb	r0,[r12,#3]
+	mov	r6,r1,lsr#8
+	strb	r4,[r12,#4]
+	strb	r5,[r12,#5]
+	mov	r4,r2,lsr#24
+	strb	r6,[r12,#6]
+	mov	r5,r2,lsr#16
+	strb	r1,[r12,#7]
+	mov	r6,r2,lsr#8
+	strb	r4,[r12,#8]
+	strb	r5,[r12,#9]
+	mov	r4,r3,lsr#24
+	strb	r6,[r12,#10]
+	mov	r5,r3,lsr#16
+	strb	r2,[r12,#11]
+	mov	r6,r3,lsr#8
+	strb	r4,[r12,#12]
+	strb	r5,[r12,#13]
+	strb	r6,[r12,#14]
+	strb	r3,[r12,#15]
+#endif
+#if __ARM_ARCH__>=5
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
+#else
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
+	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+
+
+
+.align	2
+_armv4_AES_encrypt:
+	str	lr,[sp,#-4]!		@ push lr
+	ldmia	r11!,{r4,r5,r6,r7}
+	eor	r0,r0,r4
+	ldr	r12,[r11,#240-16]
+	eor	r1,r1,r5
+	eor	r2,r2,r6
+	eor	r3,r3,r7
+	sub	r12,r12,#1
+	mov	lr,#255
+
+	and	r7,lr,r0
+	and	r8,lr,r0,lsr#8
+	and	r9,lr,r0,lsr#16
+	mov	r0,r0,lsr#24
+Lenc_loop:
+	ldr	r4,[r10,r7,lsl#2]	@ Te3[s0>>0]
+	and	r7,lr,r1,lsr#16	@ i0
+	ldr	r5,[r10,r8,lsl#2]	@ Te2[s0>>8]
+	and	r8,lr,r1
+	ldr	r6,[r10,r9,lsl#2]	@ Te1[s0>>16]
+	and	r9,lr,r1,lsr#8
+	ldr	r0,[r10,r0,lsl#2]	@ Te0[s0>>24]
+	mov	r1,r1,lsr#24
+
+	ldr	r7,[r10,r7,lsl#2]	@ Te1[s1>>16]
+	ldr	r8,[r10,r8,lsl#2]	@ Te3[s1>>0]
+	ldr	r9,[r10,r9,lsl#2]	@ Te2[s1>>8]
+	eor	r0,r0,r7,ror#8
+	ldr	r1,[r10,r1,lsl#2]	@ Te0[s1>>24]
+	and	r7,lr,r2,lsr#8	@ i0
+	eor	r5,r5,r8,ror#8
+	and	r8,lr,r2,lsr#16	@ i1
+	eor	r6,r6,r9,ror#8
+	and	r9,lr,r2
+	ldr	r7,[r10,r7,lsl#2]	@ Te2[s2>>8]
+	eor	r1,r1,r4,ror#24
+	ldr	r8,[r10,r8,lsl#2]	@ Te1[s2>>16]
+	mov	r2,r2,lsr#24
+
+	ldr	r9,[r10,r9,lsl#2]	@ Te3[s2>>0]
+	eor	r0,r0,r7,ror#16
+	ldr	r2,[r10,r2,lsl#2]	@ Te0[s2>>24]
+	and	r7,lr,r3		@ i0
+	eor	r1,r1,r8,ror#8
+	and	r8,lr,r3,lsr#8	@ i1
+	eor	r6,r6,r9,ror#16
+	and	r9,lr,r3,lsr#16	@ i2
+	ldr	r7,[r10,r7,lsl#2]	@ Te3[s3>>0]
+	eor	r2,r2,r5,ror#16
+	ldr	r8,[r10,r8,lsl#2]	@ Te2[s3>>8]
+	mov	r3,r3,lsr#24
+
+	ldr	r9,[r10,r9,lsl#2]	@ Te1[s3>>16]
+	eor	r0,r0,r7,ror#24
+	ldr	r7,[r11],#16
+	eor	r1,r1,r8,ror#16
+	ldr	r3,[r10,r3,lsl#2]	@ Te0[s3>>24]
+	eor	r2,r2,r9,ror#8
+	ldr	r4,[r11,#-12]
+	eor	r3,r3,r6,ror#8
+
+	ldr	r5,[r11,#-8]
+	eor	r0,r0,r7
+	ldr	r6,[r11,#-4]
+	and	r7,lr,r0
+	eor	r1,r1,r4
+	and	r8,lr,r0,lsr#8
+	eor	r2,r2,r5
+	and	r9,lr,r0,lsr#16
+	eor	r3,r3,r6
+	mov	r0,r0,lsr#24
+
+	subs	r12,r12,#1
+	bne	Lenc_loop
+
+	add	r10,r10,#2
+
+	ldrb	r4,[r10,r7,lsl#2]	@ Te4[s0>>0]
+	and	r7,lr,r1,lsr#16	@ i0
+	ldrb	r5,[r10,r8,lsl#2]	@ Te4[s0>>8]
+	and	r8,lr,r1
+	ldrb	r6,[r10,r9,lsl#2]	@ Te4[s0>>16]
+	and	r9,lr,r1,lsr#8
+	ldrb	r0,[r10,r0,lsl#2]	@ Te4[s0>>24]
+	mov	r1,r1,lsr#24
+
+	ldrb	r7,[r10,r7,lsl#2]	@ Te4[s1>>16]
+	ldrb	r8,[r10,r8,lsl#2]	@ Te4[s1>>0]
+	ldrb	r9,[r10,r9,lsl#2]	@ Te4[s1>>8]
+	eor	r0,r7,r0,lsl#8
+	ldrb	r1,[r10,r1,lsl#2]	@ Te4[s1>>24]
+	and	r7,lr,r2,lsr#8	@ i0
+	eor	r5,r8,r5,lsl#8
+	and	r8,lr,r2,lsr#16	@ i1
+	eor	r6,r9,r6,lsl#8
+	and	r9,lr,r2
+	ldrb	r7,[r10,r7,lsl#2]	@ Te4[s2>>8]
+	eor	r1,r4,r1,lsl#24
+	ldrb	r8,[r10,r8,lsl#2]	@ Te4[s2>>16]
+	mov	r2,r2,lsr#24
+
+	ldrb	r9,[r10,r9,lsl#2]	@ Te4[s2>>0]
+	eor	r0,r7,r0,lsl#8
+	ldrb	r2,[r10,r2,lsl#2]	@ Te4[s2>>24]
+	and	r7,lr,r3		@ i0
+	eor	r1,r1,r8,lsl#16
+	and	r8,lr,r3,lsr#8	@ i1
+	eor	r6,r9,r6,lsl#8
+	and	r9,lr,r3,lsr#16	@ i2
+	ldrb	r7,[r10,r7,lsl#2]	@ Te4[s3>>0]
+	eor	r2,r5,r2,lsl#24
+	ldrb	r8,[r10,r8,lsl#2]	@ Te4[s3>>8]
+	mov	r3,r3,lsr#24
+
+	ldrb	r9,[r10,r9,lsl#2]	@ Te4[s3>>16]
+	eor	r0,r7,r0,lsl#8
+	ldr	r7,[r11,#0]
+	ldrb	r3,[r10,r3,lsl#2]	@ Te4[s3>>24]
+	eor	r1,r1,r8,lsl#8
+	ldr	r4,[r11,#4]
+	eor	r2,r2,r9,lsl#16
+	ldr	r5,[r11,#8]
+	eor	r3,r6,r3,lsl#24
+	ldr	r6,[r11,#12]
+
+	eor	r0,r0,r7
+	eor	r1,r1,r4
+	eor	r2,r2,r5
+	eor	r3,r3,r6
+
+	sub	r10,r10,#2
+	ldr	pc,[sp],#4		@ pop and return
+
+
+.globl	_asm_AES_set_encrypt_key
+.private_extern	_asm_AES_set_encrypt_key
+
+.align	5
+_asm_AES_set_encrypt_key:
+_armv4_AES_set_encrypt_key:
+#if __ARM_ARCH__<7
+	sub	r3,pc,#8		@ _asm_AES_set_encrypt_key
+#else
+	adr	r3,_asm_AES_set_encrypt_key
+#endif
+	teq	r0,#0
+#if __ARM_ARCH__>=7
+	itt	eq			@ Thumb2 thing, sanity check in ARM
+#endif
+	moveq	r0,#-1
+	beq	Labrt
+	teq	r2,#0
+#if __ARM_ARCH__>=7
+	itt	eq			@ Thumb2 thing, sanity check in ARM
+#endif
+	moveq	r0,#-1
+	beq	Labrt
+
+	teq	r1,#128
+	beq	Lok
+	teq	r1,#192
+	beq	Lok
+	teq	r1,#256
+#if __ARM_ARCH__>=7
+	itt	ne			@ Thumb2 thing, sanity check in ARM
+#endif
+	movne	r0,#-1
+	bne	Labrt
+
+Lok:	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
+	mov	r12,r0		@ inp
+	mov	lr,r1			@ bits
+	mov	r11,r2			@ key
+
+#ifdef	__APPLE__
+	adr	r10,AES_Te+1024				@ Te4
+#else
+	sub	r10,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024	@ Te4
+#endif
+
+#if __ARM_ARCH__<7
+	ldrb	r0,[r12,#3]	@ load input data in endian-neutral
+	ldrb	r4,[r12,#2]	@ manner...
+	ldrb	r5,[r12,#1]
+	ldrb	r6,[r12,#0]
+	orr	r0,r0,r4,lsl#8
+	ldrb	r1,[r12,#7]
+	orr	r0,r0,r5,lsl#16
+	ldrb	r4,[r12,#6]
+	orr	r0,r0,r6,lsl#24
+	ldrb	r5,[r12,#5]
+	ldrb	r6,[r12,#4]
+	orr	r1,r1,r4,lsl#8
+	ldrb	r2,[r12,#11]
+	orr	r1,r1,r5,lsl#16
+	ldrb	r4,[r12,#10]
+	orr	r1,r1,r6,lsl#24
+	ldrb	r5,[r12,#9]
+	ldrb	r6,[r12,#8]
+	orr	r2,r2,r4,lsl#8
+	ldrb	r3,[r12,#15]
+	orr	r2,r2,r5,lsl#16
+	ldrb	r4,[r12,#14]
+	orr	r2,r2,r6,lsl#24
+	ldrb	r5,[r12,#13]
+	ldrb	r6,[r12,#12]
+	orr	r3,r3,r4,lsl#8
+	str	r0,[r11],#16
+	orr	r3,r3,r5,lsl#16
+	str	r1,[r11,#-12]
+	orr	r3,r3,r6,lsl#24
+	str	r2,[r11,#-8]
+	str	r3,[r11,#-4]
+#else
+	ldr	r0,[r12,#0]
+	ldr	r1,[r12,#4]
+	ldr	r2,[r12,#8]
+	ldr	r3,[r12,#12]
+#ifdef __ARMEL__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+#endif
+	str	r0,[r11],#16
+	str	r1,[r11,#-12]
+	str	r2,[r11,#-8]
+	str	r3,[r11,#-4]
+#endif
+
+	teq	lr,#128
+	bne	Lnot128
+	mov	r12,#10
+	str	r12,[r11,#240-16]
+	add	r6,r10,#256			@ rcon
+	mov	lr,#255
+
+L128_loop:
+	and	r5,lr,r3,lsr#24
+	and	r7,lr,r3,lsr#16
+	ldrb	r5,[r10,r5]
+	and	r8,lr,r3,lsr#8
+	ldrb	r7,[r10,r7]
+	and	r9,lr,r3
+	ldrb	r8,[r10,r8]
+	orr	r5,r5,r7,lsl#24
+	ldrb	r9,[r10,r9]
+	orr	r5,r5,r8,lsl#16
+	ldr	r4,[r6],#4			@ rcon[i++]
+	orr	r5,r5,r9,lsl#8
+	eor	r5,r5,r4
+	eor	r0,r0,r5			@ rk[4]=rk[0]^...
+	eor	r1,r1,r0			@ rk[5]=rk[1]^rk[4]
+	str	r0,[r11],#16
+	eor	r2,r2,r1			@ rk[6]=rk[2]^rk[5]
+	str	r1,[r11,#-12]
+	eor	r3,r3,r2			@ rk[7]=rk[3]^rk[6]
+	str	r2,[r11,#-8]
+	subs	r12,r12,#1
+	str	r3,[r11,#-4]
+	bne	L128_loop
+	sub	r2,r11,#176
+	b	Ldone
+
+Lnot128:
+#if __ARM_ARCH__<7
+	ldrb	r8,[r12,#19]
+	ldrb	r4,[r12,#18]
+	ldrb	r5,[r12,#17]
+	ldrb	r6,[r12,#16]
+	orr	r8,r8,r4,lsl#8
+	ldrb	r9,[r12,#23]
+	orr	r8,r8,r5,lsl#16
+	ldrb	r4,[r12,#22]
+	orr	r8,r8,r6,lsl#24
+	ldrb	r5,[r12,#21]
+	ldrb	r6,[r12,#20]
+	orr	r9,r9,r4,lsl#8
+	orr	r9,r9,r5,lsl#16
+	str	r8,[r11],#8
+	orr	r9,r9,r6,lsl#24
+	str	r9,[r11,#-4]
+#else
+	ldr	r8,[r12,#16]
+	ldr	r9,[r12,#20]
+#ifdef __ARMEL__
+	rev	r8,r8
+	rev	r9,r9
+#endif
+	str	r8,[r11],#8
+	str	r9,[r11,#-4]
+#endif
+
+	teq	lr,#192
+	bne	Lnot192
+	mov	r12,#12
+	str	r12,[r11,#240-24]
+	add	r6,r10,#256			@ rcon
+	mov	lr,#255
+	mov	r12,#8
+
+L192_loop:
+	and	r5,lr,r9,lsr#24
+	and	r7,lr,r9,lsr#16
+	ldrb	r5,[r10,r5]
+	and	r8,lr,r9,lsr#8
+	ldrb	r7,[r10,r7]
+	and	r9,lr,r9
+	ldrb	r8,[r10,r8]
+	orr	r5,r5,r7,lsl#24
+	ldrb	r9,[r10,r9]
+	orr	r5,r5,r8,lsl#16
+	ldr	r4,[r6],#4			@ rcon[i++]
+	orr	r5,r5,r9,lsl#8
+	eor	r9,r5,r4
+	eor	r0,r0,r9			@ rk[6]=rk[0]^...
+	eor	r1,r1,r0			@ rk[7]=rk[1]^rk[6]
+	str	r0,[r11],#24
+	eor	r2,r2,r1			@ rk[8]=rk[2]^rk[7]
+	str	r1,[r11,#-20]
+	eor	r3,r3,r2			@ rk[9]=rk[3]^rk[8]
+	str	r2,[r11,#-16]
+	subs	r12,r12,#1
+	str	r3,[r11,#-12]
+#if __ARM_ARCH__>=7
+	itt	eq				@ Thumb2 thing, sanity check in ARM
+#endif
+	subeq	r2,r11,#216
+	beq	Ldone
+
+	ldr	r7,[r11,#-32]
+	ldr	r8,[r11,#-28]
+	eor	r7,r7,r3			@ rk[10]=rk[4]^rk[9]
+	eor	r9,r8,r7			@ rk[11]=rk[5]^rk[10]
+	str	r7,[r11,#-8]
+	str	r9,[r11,#-4]
+	b	L192_loop
+
+Lnot192:
+#if __ARM_ARCH__<7
+	ldrb	r8,[r12,#27]
+	ldrb	r4,[r12,#26]
+	ldrb	r5,[r12,#25]
+	ldrb	r6,[r12,#24]
+	orr	r8,r8,r4,lsl#8
+	ldrb	r9,[r12,#31]
+	orr	r8,r8,r5,lsl#16
+	ldrb	r4,[r12,#30]
+	orr	r8,r8,r6,lsl#24
+	ldrb	r5,[r12,#29]
+	ldrb	r6,[r12,#28]
+	orr	r9,r9,r4,lsl#8
+	orr	r9,r9,r5,lsl#16
+	str	r8,[r11],#8
+	orr	r9,r9,r6,lsl#24
+	str	r9,[r11,#-4]
+#else
+	ldr	r8,[r12,#24]
+	ldr	r9,[r12,#28]
+#ifdef __ARMEL__
+	rev	r8,r8
+	rev	r9,r9
+#endif
+	str	r8,[r11],#8
+	str	r9,[r11,#-4]
+#endif
+
+	mov	r12,#14
+	str	r12,[r11,#240-32]
+	add	r6,r10,#256			@ rcon
+	mov	lr,#255
+	mov	r12,#7
+
+L256_loop:
+	and	r5,lr,r9,lsr#24
+	and	r7,lr,r9,lsr#16
+	ldrb	r5,[r10,r5]
+	and	r8,lr,r9,lsr#8
+	ldrb	r7,[r10,r7]
+	and	r9,lr,r9
+	ldrb	r8,[r10,r8]
+	orr	r5,r5,r7,lsl#24
+	ldrb	r9,[r10,r9]
+	orr	r5,r5,r8,lsl#16
+	ldr	r4,[r6],#4			@ rcon[i++]
+	orr	r5,r5,r9,lsl#8
+	eor	r9,r5,r4
+	eor	r0,r0,r9			@ rk[8]=rk[0]^...
+	eor	r1,r1,r0			@ rk[9]=rk[1]^rk[8]
+	str	r0,[r11],#32
+	eor	r2,r2,r1			@ rk[10]=rk[2]^rk[9]
+	str	r1,[r11,#-28]
+	eor	r3,r3,r2			@ rk[11]=rk[3]^rk[10]
+	str	r2,[r11,#-24]
+	subs	r12,r12,#1
+	str	r3,[r11,#-20]
+#if __ARM_ARCH__>=7
+	itt	eq				@ Thumb2 thing, sanity check in ARM
+#endif
+	subeq	r2,r11,#256
+	beq	Ldone
+
+	and	r5,lr,r3
+	and	r7,lr,r3,lsr#8
+	ldrb	r5,[r10,r5]
+	and	r8,lr,r3,lsr#16
+	ldrb	r7,[r10,r7]
+	and	r9,lr,r3,lsr#24
+	ldrb	r8,[r10,r8]
+	orr	r5,r5,r7,lsl#8
+	ldrb	r9,[r10,r9]
+	orr	r5,r5,r8,lsl#16
+	ldr	r4,[r11,#-48]
+	orr	r5,r5,r9,lsl#24
+
+	ldr	r7,[r11,#-44]
+	ldr	r8,[r11,#-40]
+	eor	r4,r4,r5			@ rk[12]=rk[4]^...
+	ldr	r9,[r11,#-36]
+	eor	r7,r7,r4			@ rk[13]=rk[5]^rk[12]
+	str	r4,[r11,#-16]
+	eor	r8,r8,r7			@ rk[14]=rk[6]^rk[13]
+	str	r7,[r11,#-12]
+	eor	r9,r9,r8			@ rk[15]=rk[7]^rk[14]
+	str	r8,[r11,#-8]
+	str	r9,[r11,#-4]
+	b	L256_loop
+
+.align	2
+Ldone:	mov	r0,#0
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
+Labrt:
+#if __ARM_ARCH__>=5
+	bx	lr				@ .word	0xe12fff1e
+#else
+	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+
+
+.globl	_asm_AES_set_decrypt_key
+.private_extern	_asm_AES_set_decrypt_key
+
+.align	5
+_asm_AES_set_decrypt_key:
+	str	lr,[sp,#-4]!            @ push lr
+	bl	_armv4_AES_set_encrypt_key
+	teq	r0,#0
+	ldr	lr,[sp],#4              @ pop lr
+	bne	Labrt
+
+	mov	r0,r2			@ _asm_AES_set_encrypt_key preserves r2,
+	mov	r1,r2			@ which is AES_KEY *key
+	b	_armv4_AES_set_enc2dec_key
+
+
+@ void AES_set_enc2dec_key(const AES_KEY *inp,AES_KEY *out)
+.globl	_AES_set_enc2dec_key
+.private_extern	_AES_set_enc2dec_key
+
+.align	5
+_AES_set_enc2dec_key:
+_armv4_AES_set_enc2dec_key:
+	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
+
+	ldr	r12,[r0,#240]
+	mov	r7,r0			@ input
+	add	r8,r0,r12,lsl#4
+	mov	r11,r1			@ ouput
+	add	r10,r1,r12,lsl#4
+	str	r12,[r1,#240]
+
+Linv:	ldr	r0,[r7],#16
+	ldr	r1,[r7,#-12]
+	ldr	r2,[r7,#-8]
+	ldr	r3,[r7,#-4]
+	ldr	r4,[r8],#-16
+	ldr	r5,[r8,#16+4]
+	ldr	r6,[r8,#16+8]
+	ldr	r9,[r8,#16+12]
+	str	r0,[r10],#-16
+	str	r1,[r10,#16+4]
+	str	r2,[r10,#16+8]
+	str	r3,[r10,#16+12]
+	str	r4,[r11],#16
+	str	r5,[r11,#-12]
+	str	r6,[r11,#-8]
+	str	r9,[r11,#-4]
+	teq	r7,r8
+	bne	Linv
+
+	ldr	r0,[r7]
+	ldr	r1,[r7,#4]
+	ldr	r2,[r7,#8]
+	ldr	r3,[r7,#12]
+	str	r0,[r11]
+	str	r1,[r11,#4]
+	str	r2,[r11,#8]
+	str	r3,[r11,#12]
+	sub	r11,r11,r12,lsl#3
+	ldr	r0,[r11,#16]!		@ prefetch tp1
+	mov	r7,#0x80
+	mov	r8,#0x1b
+	orr	r7,r7,#0x8000
+	orr	r8,r8,#0x1b00
+	orr	r7,r7,r7,lsl#16
+	orr	r8,r8,r8,lsl#16
+	sub	r12,r12,#1
+	mvn	r9,r7
+	mov	r12,r12,lsl#2	@ (rounds-1)*4
+
+Lmix:	and	r4,r0,r7
+	and	r1,r0,r9
+	sub	r4,r4,r4,lsr#7
+	and	r4,r4,r8
+	eor	r1,r4,r1,lsl#1	@ tp2
+
+	and	r4,r1,r7
+	and	r2,r1,r9
+	sub	r4,r4,r4,lsr#7
+	and	r4,r4,r8
+	eor	r2,r4,r2,lsl#1	@ tp4
+
+	and	r4,r2,r7
+	and	r3,r2,r9
+	sub	r4,r4,r4,lsr#7
+	and	r4,r4,r8
+	eor	r3,r4,r3,lsl#1	@ tp8
+
+	eor	r4,r1,r2
+	eor	r5,r0,r3		@ tp9
+	eor	r4,r4,r3		@ tpe
+	eor	r4,r4,r1,ror#24
+	eor	r4,r4,r5,ror#24	@ ^= ROTATE(tpb=tp9^tp2,8)
+	eor	r4,r4,r2,ror#16
+	eor	r4,r4,r5,ror#16	@ ^= ROTATE(tpd=tp9^tp4,16)
+	eor	r4,r4,r5,ror#8	@ ^= ROTATE(tp9,24)
+
+	ldr	r0,[r11,#4]		@ prefetch tp1
+	str	r4,[r11],#4
+	subs	r12,r12,#1
+	bne	Lmix
+
+	mov	r0,#0
+#if __ARM_ARCH__>=5
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
+#else
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
+	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+
+
+
+.align	5
+AES_Td:
+.word	0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96
+.word	0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393
+.word	0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25
+.word	0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f
+.word	0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1
+.word	0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6
+.word	0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da
+.word	0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844
+.word	0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd
+.word	0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4
+.word	0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45
+.word	0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94
+.word	0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7
+.word	0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a
+.word	0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5
+.word	0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c
+.word	0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1
+.word	0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a
+.word	0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75
+.word	0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051
+.word	0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46
+.word	0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff
+.word	0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77
+.word	0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb
+.word	0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000
+.word	0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e
+.word	0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927
+.word	0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a
+.word	0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e
+.word	0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16
+.word	0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d
+.word	0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8
+.word	0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd
+.word	0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34
+.word	0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163
+.word	0xd731dcca, 0x42638510, 0x13972240, 0x84c61120
+.word	0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d
+.word	0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0
+.word	0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422
+.word	0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef
+.word	0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36
+.word	0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4
+.word	0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662
+.word	0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5
+.word	0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3
+.word	0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b
+.word	0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8
+.word	0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6
+.word	0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6
+.word	0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0
+.word	0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815
+.word	0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f
+.word	0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df
+.word	0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f
+.word	0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e
+.word	0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713
+.word	0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89
+.word	0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c
+.word	0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf
+.word	0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86
+.word	0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f
+.word	0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541
+.word	0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190
+.word	0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742
+@ Td4[256]
+.byte	0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38
+.byte	0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
+.byte	0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87
+.byte	0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
+.byte	0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d
+.byte	0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
+.byte	0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2
+.byte	0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
+.byte	0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16
+.byte	0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
+.byte	0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda
+.byte	0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
+.byte	0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a
+.byte	0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
+.byte	0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02
+.byte	0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
+.byte	0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea
+.byte	0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
+.byte	0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85
+.byte	0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
+.byte	0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89
+.byte	0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
+.byte	0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20
+.byte	0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
+.byte	0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31
+.byte	0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
+.byte	0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d
+.byte	0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
+.byte	0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0
+.byte	0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
+.byte	0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26
+.byte	0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
+
+
+@ void asm_AES_decrypt(const unsigned char *in, unsigned char *out,
+@ 		       const AES_KEY *key) {
+.globl	_asm_AES_decrypt
+.private_extern	_asm_AES_decrypt
+
+.align	5
+_asm_AES_decrypt:
+#if __ARM_ARCH__<7
+	sub	r3,pc,#8		@ _asm_AES_decrypt
+#else
+	adr	r3,_asm_AES_decrypt
+#endif
+	stmdb	sp!,{r1,r4-r12,lr}
+#ifdef	__APPLE__
+	adr	r10,AES_Td
+#else
+	sub	r10,r3,#_asm_AES_decrypt-AES_Td	@ Td
+#endif
+	mov	r12,r0		@ inp
+	mov	r11,r2
+#if __ARM_ARCH__<7
+	ldrb	r0,[r12,#3]	@ load input data in endian-neutral
+	ldrb	r4,[r12,#2]	@ manner...
+	ldrb	r5,[r12,#1]
+	ldrb	r6,[r12,#0]
+	orr	r0,r0,r4,lsl#8
+	ldrb	r1,[r12,#7]
+	orr	r0,r0,r5,lsl#16
+	ldrb	r4,[r12,#6]
+	orr	r0,r0,r6,lsl#24
+	ldrb	r5,[r12,#5]
+	ldrb	r6,[r12,#4]
+	orr	r1,r1,r4,lsl#8
+	ldrb	r2,[r12,#11]
+	orr	r1,r1,r5,lsl#16
+	ldrb	r4,[r12,#10]
+	orr	r1,r1,r6,lsl#24
+	ldrb	r5,[r12,#9]
+	ldrb	r6,[r12,#8]
+	orr	r2,r2,r4,lsl#8
+	ldrb	r3,[r12,#15]
+	orr	r2,r2,r5,lsl#16
+	ldrb	r4,[r12,#14]
+	orr	r2,r2,r6,lsl#24
+	ldrb	r5,[r12,#13]
+	ldrb	r6,[r12,#12]
+	orr	r3,r3,r4,lsl#8
+	orr	r3,r3,r5,lsl#16
+	orr	r3,r3,r6,lsl#24
+#else
+	ldr	r0,[r12,#0]
+	ldr	r1,[r12,#4]
+	ldr	r2,[r12,#8]
+	ldr	r3,[r12,#12]
+#ifdef __ARMEL__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+#endif
+#endif
+	bl	_armv4_AES_decrypt
+
+	ldr	r12,[sp],#4		@ pop out
+#if __ARM_ARCH__>=7
+#ifdef __ARMEL__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+#endif
+	str	r0,[r12,#0]
+	str	r1,[r12,#4]
+	str	r2,[r12,#8]
+	str	r3,[r12,#12]
+#else
+	mov	r4,r0,lsr#24		@ write output in endian-neutral
+	mov	r5,r0,lsr#16		@ manner...
+	mov	r6,r0,lsr#8
+	strb	r4,[r12,#0]
+	strb	r5,[r12,#1]
+	mov	r4,r1,lsr#24
+	strb	r6,[r12,#2]
+	mov	r5,r1,lsr#16
+	strb	r0,[r12,#3]
+	mov	r6,r1,lsr#8
+	strb	r4,[r12,#4]
+	strb	r5,[r12,#5]
+	mov	r4,r2,lsr#24
+	strb	r6,[r12,#6]
+	mov	r5,r2,lsr#16
+	strb	r1,[r12,#7]
+	mov	r6,r2,lsr#8
+	strb	r4,[r12,#8]
+	strb	r5,[r12,#9]
+	mov	r4,r3,lsr#24
+	strb	r6,[r12,#10]
+	mov	r5,r3,lsr#16
+	strb	r2,[r12,#11]
+	mov	r6,r3,lsr#8
+	strb	r4,[r12,#12]
+	strb	r5,[r12,#13]
+	strb	r6,[r12,#14]
+	strb	r3,[r12,#15]
+#endif
+#if __ARM_ARCH__>=5
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
+#else
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
+	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+
+
+
+.align	2
+_armv4_AES_decrypt:
+	str	lr,[sp,#-4]!		@ push lr
+	ldmia	r11!,{r4,r5,r6,r7}
+	eor	r0,r0,r4
+	ldr	r12,[r11,#240-16]
+	eor	r1,r1,r5
+	eor	r2,r2,r6
+	eor	r3,r3,r7
+	sub	r12,r12,#1
+	mov	lr,#255
+
+	and	r7,lr,r0,lsr#16
+	and	r8,lr,r0,lsr#8
+	and	r9,lr,r0
+	mov	r0,r0,lsr#24
+Ldec_loop:
+	ldr	r4,[r10,r7,lsl#2]	@ Td1[s0>>16]
+	and	r7,lr,r1		@ i0
+	ldr	r5,[r10,r8,lsl#2]	@ Td2[s0>>8]
+	and	r8,lr,r1,lsr#16
+	ldr	r6,[r10,r9,lsl#2]	@ Td3[s0>>0]
+	and	r9,lr,r1,lsr#8
+	ldr	r0,[r10,r0,lsl#2]	@ Td0[s0>>24]
+	mov	r1,r1,lsr#24
+
+	ldr	r7,[r10,r7,lsl#2]	@ Td3[s1>>0]
+	ldr	r8,[r10,r8,lsl#2]	@ Td1[s1>>16]
+	ldr	r9,[r10,r9,lsl#2]	@ Td2[s1>>8]
+	eor	r0,r0,r7,ror#24
+	ldr	r1,[r10,r1,lsl#2]	@ Td0[s1>>24]
+	and	r7,lr,r2,lsr#8	@ i0
+	eor	r5,r8,r5,ror#8
+	and	r8,lr,r2		@ i1
+	eor	r6,r9,r6,ror#8
+	and	r9,lr,r2,lsr#16
+	ldr	r7,[r10,r7,lsl#2]	@ Td2[s2>>8]
+	eor	r1,r1,r4,ror#8
+	ldr	r8,[r10,r8,lsl#2]	@ Td3[s2>>0]
+	mov	r2,r2,lsr#24
+
+	ldr	r9,[r10,r9,lsl#2]	@ Td1[s2>>16]
+	eor	r0,r0,r7,ror#16
+	ldr	r2,[r10,r2,lsl#2]	@ Td0[s2>>24]
+	and	r7,lr,r3,lsr#16	@ i0
+	eor	r1,r1,r8,ror#24
+	and	r8,lr,r3,lsr#8	@ i1
+	eor	r6,r9,r6,ror#8
+	and	r9,lr,r3		@ i2
+	ldr	r7,[r10,r7,lsl#2]	@ Td1[s3>>16]
+	eor	r2,r2,r5,ror#8
+	ldr	r8,[r10,r8,lsl#2]	@ Td2[s3>>8]
+	mov	r3,r3,lsr#24
+
+	ldr	r9,[r10,r9,lsl#2]	@ Td3[s3>>0]
+	eor	r0,r0,r7,ror#8
+	ldr	r7,[r11],#16
+	eor	r1,r1,r8,ror#16
+	ldr	r3,[r10,r3,lsl#2]	@ Td0[s3>>24]
+	eor	r2,r2,r9,ror#24
+
+	ldr	r4,[r11,#-12]
+	eor	r0,r0,r7
+	ldr	r5,[r11,#-8]
+	eor	r3,r3,r6,ror#8
+	ldr	r6,[r11,#-4]
+	and	r7,lr,r0,lsr#16
+	eor	r1,r1,r4
+	and	r8,lr,r0,lsr#8
+	eor	r2,r2,r5
+	and	r9,lr,r0
+	eor	r3,r3,r6
+	mov	r0,r0,lsr#24
+
+	subs	r12,r12,#1
+	bne	Ldec_loop
+
+	add	r10,r10,#1024
+
+	ldr	r5,[r10,#0]		@ prefetch Td4
+	ldr	r6,[r10,#32]
+	ldr	r4,[r10,#64]
+	ldr	r5,[r10,#96]
+	ldr	r6,[r10,#128]
+	ldr	r4,[r10,#160]
+	ldr	r5,[r10,#192]
+	ldr	r6,[r10,#224]
+
+	ldrb	r0,[r10,r0]		@ Td4[s0>>24]
+	ldrb	r4,[r10,r7]		@ Td4[s0>>16]
+	and	r7,lr,r1		@ i0
+	ldrb	r5,[r10,r8]		@ Td4[s0>>8]
+	and	r8,lr,r1,lsr#16
+	ldrb	r6,[r10,r9]		@ Td4[s0>>0]
+	and	r9,lr,r1,lsr#8
+
+	add	r1,r10,r1,lsr#24
+	ldrb	r7,[r10,r7]		@ Td4[s1>>0]
+	ldrb	r1,[r1]		@ Td4[s1>>24]
+	ldrb	r8,[r10,r8]		@ Td4[s1>>16]
+	eor	r0,r7,r0,lsl#24
+	ldrb	r9,[r10,r9]		@ Td4[s1>>8]
+	eor	r1,r4,r1,lsl#8
+	and	r7,lr,r2,lsr#8	@ i0
+	eor	r5,r5,r8,lsl#8
+	and	r8,lr,r2		@ i1
+	ldrb	r7,[r10,r7]		@ Td4[s2>>8]
+	eor	r6,r6,r9,lsl#8
+	ldrb	r8,[r10,r8]		@ Td4[s2>>0]
+	and	r9,lr,r2,lsr#16
+
+	add	r2,r10,r2,lsr#24
+	ldrb	r2,[r2]		@ Td4[s2>>24]
+	eor	r0,r0,r7,lsl#8
+	ldrb	r9,[r10,r9]		@ Td4[s2>>16]
+	eor	r1,r8,r1,lsl#16
+	and	r7,lr,r3,lsr#16	@ i0
+	eor	r2,r5,r2,lsl#16
+	and	r8,lr,r3,lsr#8	@ i1
+	ldrb	r7,[r10,r7]		@ Td4[s3>>16]
+	eor	r6,r6,r9,lsl#16
+	ldrb	r8,[r10,r8]		@ Td4[s3>>8]
+	and	r9,lr,r3		@ i2
+
+	add	r3,r10,r3,lsr#24
+	ldrb	r9,[r10,r9]		@ Td4[s3>>0]
+	ldrb	r3,[r3]		@ Td4[s3>>24]
+	eor	r0,r0,r7,lsl#16
+	ldr	r7,[r11,#0]
+	eor	r1,r1,r8,lsl#8
+	ldr	r4,[r11,#4]
+	eor	r2,r9,r2,lsl#8
+	ldr	r5,[r11,#8]
+	eor	r3,r6,r3,lsl#24
+	ldr	r6,[r11,#12]
+
+	eor	r0,r0,r7
+	eor	r1,r1,r4
+	eor	r2,r2,r5
+	eor	r3,r3,r6
+
+	sub	r10,r10,#1024
+	ldr	pc,[sp],#4		@ pop and return
+
+.byte	65,69,83,32,102,111,114,32,65,82,77,118,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+.align	2
+
+#endif
diff --git a/third_party/boringssl/ios-arm/crypto/fipsmodule/aesv8-armx32.S b/third_party/boringssl/ios-arm/crypto/fipsmodule/aesv8-armx32.S
new file mode 100644
index 0000000..9f7aacd
--- /dev/null
+++ b/third_party/boringssl/ios-arm/crypto/fipsmodule/aesv8-armx32.S
@@ -0,0 +1,760 @@
+#include <openssl/arm_arch.h>
+
+#if __ARM_MAX_ARCH__>=7
+.text
+
+
+.code	32
+.align	5
+Lrcon:
+.long	0x01,0x01,0x01,0x01
+.long	0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d	@ rotate-n-splat
+.long	0x1b,0x1b,0x1b,0x1b
+
+.globl	_aes_hw_set_encrypt_key
+.private_extern	_aes_hw_set_encrypt_key
+
+.align	5
+_aes_hw_set_encrypt_key:
+Lenc_key:
+	mov	r3,#-1
+	cmp	r0,#0
+	beq	Lenc_key_abort
+	cmp	r2,#0
+	beq	Lenc_key_abort
+	mov	r3,#-2
+	cmp	r1,#128
+	blt	Lenc_key_abort
+	cmp	r1,#256
+	bgt	Lenc_key_abort
+	tst	r1,#0x3f
+	bne	Lenc_key_abort
+
+	adr	r3,Lrcon
+	cmp	r1,#192
+
+	veor	q0,q0,q0
+	vld1.8	{q3},[r0]!
+	mov	r1,#8		@ reuse r1
+	vld1.32	{q1,q2},[r3]!
+
+	blt	Loop128
+	beq	L192
+	b	L256
+
+.align	4
+Loop128:
+	vtbl.8	d20,{q3},d4
+	vtbl.8	d21,{q3},d5
+	vext.8	q9,q0,q3,#12
+	vst1.32	{q3},[r2]!
+.byte	0x00,0x43,0xf0,0xf3	@ aese q10,q0
+	subs	r1,r1,#1
+
+	veor	q3,q3,q9
+	vext.8	q9,q0,q9,#12
+	veor	q3,q3,q9
+	vext.8	q9,q0,q9,#12
+	veor	q10,q10,q1
+	veor	q3,q3,q9
+	vshl.u8	q1,q1,#1
+	veor	q3,q3,q10
+	bne	Loop128
+
+	vld1.32	{q1},[r3]
+
+	vtbl.8	d20,{q3},d4
+	vtbl.8	d21,{q3},d5
+	vext.8	q9,q0,q3,#12
+	vst1.32	{q3},[r2]!
+.byte	0x00,0x43,0xf0,0xf3	@ aese q10,q0
+
+	veor	q3,q3,q9
+	vext.8	q9,q0,q9,#12
+	veor	q3,q3,q9
+	vext.8	q9,q0,q9,#12
+	veor	q10,q10,q1
+	veor	q3,q3,q9
+	vshl.u8	q1,q1,#1
+	veor	q3,q3,q10
+
+	vtbl.8	d20,{q3},d4
+	vtbl.8	d21,{q3},d5
+	vext.8	q9,q0,q3,#12
+	vst1.32	{q3},[r2]!
+.byte	0x00,0x43,0xf0,0xf3	@ aese q10,q0
+
+	veor	q3,q3,q9
+	vext.8	q9,q0,q9,#12
+	veor	q3,q3,q9
+	vext.8	q9,q0,q9,#12
+	veor	q10,q10,q1
+	veor	q3,q3,q9
+	veor	q3,q3,q10
+	vst1.32	{q3},[r2]
+	add	r2,r2,#0x50
+
+	mov	r12,#10
+	b	Ldone
+
+.align	4
+L192:
+	vld1.8	{d16},[r0]!
+	vmov.i8	q10,#8			@ borrow q10
+	vst1.32	{q3},[r2]!
+	vsub.i8	q2,q2,q10	@ adjust the mask
+
+Loop192:
+	vtbl.8	d20,{q8},d4
+	vtbl.8	d21,{q8},d5
+	vext.8	q9,q0,q3,#12
+	vst1.32	{d16},[r2]!
+.byte	0x00,0x43,0xf0,0xf3	@ aese q10,q0
+	subs	r1,r1,#1
+
+	veor	q3,q3,q9
+	vext.8	q9,q0,q9,#12
+	veor	q3,q3,q9
+	vext.8	q9,q0,q9,#12
+	veor	q3,q3,q9
+
+	vdup.32	q9,d7[1]
+	veor	q9,q9,q8
+	veor	q10,q10,q1
+	vext.8	q8,q0,q8,#12
+	vshl.u8	q1,q1,#1
+	veor	q8,q8,q9
+	veor	q3,q3,q10
+	veor	q8,q8,q10
+	vst1.32	{q3},[r2]!
+	bne	Loop192
+
+	mov	r12,#12
+	add	r2,r2,#0x20
+	b	Ldone
+
+.align	4
+L256:
+	vld1.8	{q8},[r0]
+	mov	r1,#7
+	mov	r12,#14
+	vst1.32	{q3},[r2]!
+
+Loop256:
+	vtbl.8	d20,{q8},d4
+	vtbl.8	d21,{q8},d5
+	vext.8	q9,q0,q3,#12
+	vst1.32	{q8},[r2]!
+.byte	0x00,0x43,0xf0,0xf3	@ aese q10,q0
+	subs	r1,r1,#1
+
+	veor	q3,q3,q9
+	vext.8	q9,q0,q9,#12
+	veor	q3,q3,q9
+	vext.8	q9,q0,q9,#12
+	veor	q10,q10,q1
+	veor	q3,q3,q9
+	vshl.u8	q1,q1,#1
+	veor	q3,q3,q10
+	vst1.32	{q3},[r2]!
+	beq	Ldone
+
+	vdup.32	q10,d7[1]
+	vext.8	q9,q0,q8,#12
+.byte	0x00,0x43,0xf0,0xf3	@ aese q10,q0
+
+	veor	q8,q8,q9
+	vext.8	q9,q0,q9,#12
+	veor	q8,q8,q9
+	vext.8	q9,q0,q9,#12
+	veor	q8,q8,q9
+
+	veor	q8,q8,q10
+	b	Loop256
+
+Ldone:
+	str	r12,[r2]
+	mov	r3,#0
+
+Lenc_key_abort:
+	mov	r0,r3			@ return value
+
+	bx	lr
+
+
+.globl	_aes_hw_set_decrypt_key
+.private_extern	_aes_hw_set_decrypt_key
+
+.align	5
+_aes_hw_set_decrypt_key:
+	stmdb	sp!,{r4,lr}
+	bl	Lenc_key
+
+	cmp	r0,#0
+	bne	Ldec_key_abort
+
+	sub	r2,r2,#240		@ restore original r2
+	mov	r4,#-16
+	add	r0,r2,r12,lsl#4	@ end of key schedule
+
+	vld1.32	{q0},[r2]
+	vld1.32	{q1},[r0]
+	vst1.32	{q0},[r0],r4
+	vst1.32	{q1},[r2]!
+
+Loop_imc:
+	vld1.32	{q0},[r2]
+	vld1.32	{q1},[r0]
+.byte	0xc0,0x03,0xb0,0xf3	@ aesimc q0,q0
+.byte	0xc2,0x23,0xb0,0xf3	@ aesimc q1,q1
+	vst1.32	{q0},[r0],r4
+	vst1.32	{q1},[r2]!
+	cmp	r0,r2
+	bhi	Loop_imc
+
+	vld1.32	{q0},[r2]
+.byte	0xc0,0x03,0xb0,0xf3	@ aesimc q0,q0
+	vst1.32	{q0},[r0]
+
+	eor	r0,r0,r0		@ return value
+Ldec_key_abort:
+	ldmia	sp!,{r4,pc}
+
+.globl	_aes_hw_encrypt
+.private_extern	_aes_hw_encrypt
+
+.align	5
+_aes_hw_encrypt:
+	ldr	r3,[r2,#240]
+	vld1.32	{q0},[r2]!
+	vld1.8	{q2},[r0]
+	sub	r3,r3,#2
+	vld1.32	{q1},[r2]!
+
+Loop_enc:
+.byte	0x00,0x43,0xb0,0xf3	@ aese q2,q0
+.byte	0x84,0x43,0xb0,0xf3	@ aesmc q2,q2
+	vld1.32	{q0},[r2]!
+	subs	r3,r3,#2
+.byte	0x02,0x43,0xb0,0xf3	@ aese q2,q1
+.byte	0x84,0x43,0xb0,0xf3	@ aesmc q2,q2
+	vld1.32	{q1},[r2]!
+	bgt	Loop_enc
+
+.byte	0x00,0x43,0xb0,0xf3	@ aese q2,q0
+.byte	0x84,0x43,0xb0,0xf3	@ aesmc q2,q2
+	vld1.32	{q0},[r2]
+.byte	0x02,0x43,0xb0,0xf3	@ aese q2,q1
+	veor	q2,q2,q0
+
+	vst1.8	{q2},[r1]
+	bx	lr
+
+.globl	_aes_hw_decrypt
+.private_extern	_aes_hw_decrypt
+
+.align	5
+_aes_hw_decrypt:
+	ldr	r3,[r2,#240]
+	vld1.32	{q0},[r2]!
+	vld1.8	{q2},[r0]
+	sub	r3,r3,#2
+	vld1.32	{q1},[r2]!
+
+Loop_dec:
+.byte	0x40,0x43,0xb0,0xf3	@ aesd q2,q0
+.byte	0xc4,0x43,0xb0,0xf3	@ aesimc q2,q2
+	vld1.32	{q0},[r2]!
+	subs	r3,r3,#2
+.byte	0x42,0x43,0xb0,0xf3	@ aesd q2,q1
+.byte	0xc4,0x43,0xb0,0xf3	@ aesimc q2,q2
+	vld1.32	{q1},[r2]!
+	bgt	Loop_dec
+
+.byte	0x40,0x43,0xb0,0xf3	@ aesd q2,q0
+.byte	0xc4,0x43,0xb0,0xf3	@ aesimc q2,q2
+	vld1.32	{q0},[r2]
+.byte	0x42,0x43,0xb0,0xf3	@ aesd q2,q1
+	veor	q2,q2,q0
+
+	vst1.8	{q2},[r1]
+	bx	lr
+
+.globl	_aes_hw_cbc_encrypt
+.private_extern	_aes_hw_cbc_encrypt
+
+.align	5
+_aes_hw_cbc_encrypt:
+	mov	ip,sp
+	stmdb	sp!,{r4,r5,r6,r7,r8,lr}
+	vstmdb	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}            @ ABI specification says so
+	ldmia	ip,{r4,r5}		@ load remaining args
+	subs	r2,r2,#16
+	mov	r8,#16
+	blo	Lcbc_abort
+	moveq	r8,#0
+
+	cmp	r5,#0			@ en- or decrypting?
+	ldr	r5,[r3,#240]
+	and	r2,r2,#-16
+	vld1.8	{q6},[r4]
+	vld1.8	{q0},[r0],r8
+
+	vld1.32	{q8,q9},[r3]		@ load key schedule...
+	sub	r5,r5,#6
+	add	r7,r3,r5,lsl#4	@ pointer to last 7 round keys
+	sub	r5,r5,#2
+	vld1.32	{q10,q11},[r7]!
+	vld1.32	{q12,q13},[r7]!
+	vld1.32	{q14,q15},[r7]!
+	vld1.32	{q7},[r7]
+
+	add	r7,r3,#32
+	mov	r6,r5
+	beq	Lcbc_dec
+
+	cmp	r5,#2
+	veor	q0,q0,q6
+	veor	q5,q8,q7
+	beq	Lcbc_enc128
+
+	vld1.32	{q2,q3},[r7]
+	add	r7,r3,#16
+	add	r6,r3,#16*4
+	add	r12,r3,#16*5
+.byte	0x20,0x03,0xb0,0xf3	@ aese q0,q8
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	add	r14,r3,#16*6
+	add	r3,r3,#16*7
+	b	Lenter_cbc_enc
+
+.align	4
+Loop_cbc_enc:
+.byte	0x20,0x03,0xb0,0xf3	@ aese q0,q8
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	vst1.8	{q6},[r1]!
+Lenter_cbc_enc:
+.byte	0x22,0x03,0xb0,0xf3	@ aese q0,q9
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+.byte	0x04,0x03,0xb0,0xf3	@ aese q0,q2
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	vld1.32	{q8},[r6]
+	cmp	r5,#4
+.byte	0x06,0x03,0xb0,0xf3	@ aese q0,q3
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	vld1.32	{q9},[r12]
+	beq	Lcbc_enc192
+
+.byte	0x20,0x03,0xb0,0xf3	@ aese q0,q8
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	vld1.32	{q8},[r14]
+.byte	0x22,0x03,0xb0,0xf3	@ aese q0,q9
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	vld1.32	{q9},[r3]
+	nop
+
+Lcbc_enc192:
+.byte	0x20,0x03,0xb0,0xf3	@ aese q0,q8
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	subs	r2,r2,#16
+.byte	0x22,0x03,0xb0,0xf3	@ aese q0,q9
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	moveq	r8,#0
+.byte	0x24,0x03,0xb0,0xf3	@ aese q0,q10
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+.byte	0x26,0x03,0xb0,0xf3	@ aese q0,q11
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	vld1.8	{q8},[r0],r8
+.byte	0x28,0x03,0xb0,0xf3	@ aese q0,q12
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	veor	q8,q8,q5
+.byte	0x2a,0x03,0xb0,0xf3	@ aese q0,q13
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	vld1.32	{q9},[r7]		@ re-pre-load rndkey[1]
+.byte	0x2c,0x03,0xb0,0xf3	@ aese q0,q14
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+.byte	0x2e,0x03,0xb0,0xf3	@ aese q0,q15
+	veor	q6,q0,q7
+	bhs	Loop_cbc_enc
+
+	vst1.8	{q6},[r1]!
+	b	Lcbc_done
+
+.align	5
+Lcbc_enc128:
+	vld1.32	{q2,q3},[r7]
+.byte	0x20,0x03,0xb0,0xf3	@ aese q0,q8
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	b	Lenter_cbc_enc128
+Loop_cbc_enc128:
+.byte	0x20,0x03,0xb0,0xf3	@ aese q0,q8
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	vst1.8	{q6},[r1]!
+Lenter_cbc_enc128:
+.byte	0x22,0x03,0xb0,0xf3	@ aese q0,q9
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	subs	r2,r2,#16
+.byte	0x04,0x03,0xb0,0xf3	@ aese q0,q2
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	moveq	r8,#0
+.byte	0x06,0x03,0xb0,0xf3	@ aese q0,q3
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+.byte	0x24,0x03,0xb0,0xf3	@ aese q0,q10
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+.byte	0x26,0x03,0xb0,0xf3	@ aese q0,q11
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	vld1.8	{q8},[r0],r8
+.byte	0x28,0x03,0xb0,0xf3	@ aese q0,q12
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+.byte	0x2a,0x03,0xb0,0xf3	@ aese q0,q13
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+.byte	0x2c,0x03,0xb0,0xf3	@ aese q0,q14
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+	veor	q8,q8,q5
+.byte	0x2e,0x03,0xb0,0xf3	@ aese q0,q15
+	veor	q6,q0,q7
+	bhs	Loop_cbc_enc128
+
+	vst1.8	{q6},[r1]!
+	b	Lcbc_done
+.align	5
+Lcbc_dec:
+	vld1.8	{q10},[r0]!
+	subs	r2,r2,#32		@ bias
+	add	r6,r5,#2
+	vorr	q3,q0,q0
+	vorr	q1,q0,q0
+	vorr	q11,q10,q10
+	blo	Lcbc_dec_tail
+
+	vorr	q1,q10,q10
+	vld1.8	{q10},[r0]!
+	vorr	q2,q0,q0
+	vorr	q3,q1,q1
+	vorr	q11,q10,q10
+
+Loop3x_cbc_dec:
+.byte	0x60,0x03,0xb0,0xf3	@ aesd q0,q8
+.byte	0xc0,0x03,0xb0,0xf3	@ aesimc q0,q0
+.byte	0x60,0x23,0xb0,0xf3	@ aesd q1,q8
+.byte	0xc2,0x23,0xb0,0xf3	@ aesimc q1,q1
+.byte	0x60,0x43,0xf0,0xf3	@ aesd q10,q8
+.byte	0xe4,0x43,0xf0,0xf3	@ aesimc q10,q10
+	vld1.32	{q8},[r7]!
+	subs	r6,r6,#2
+.byte	0x62,0x03,0xb0,0xf3	@ aesd q0,q9
+.byte	0xc0,0x03,0xb0,0xf3	@ aesimc q0,q0
+.byte	0x62,0x23,0xb0,0xf3	@ aesd q1,q9
+.byte	0xc2,0x23,0xb0,0xf3	@ aesimc q1,q1
+.byte	0x62,0x43,0xf0,0xf3	@ aesd q10,q9
+.byte	0xe4,0x43,0xf0,0xf3	@ aesimc q10,q10
+	vld1.32	{q9},[r7]!
+	bgt	Loop3x_cbc_dec
+
+.byte	0x60,0x03,0xb0,0xf3	@ aesd q0,q8
+.byte	0xc0,0x03,0xb0,0xf3	@ aesimc q0,q0
+.byte	0x60,0x23,0xb0,0xf3	@ aesd q1,q8
+.byte	0xc2,0x23,0xb0,0xf3	@ aesimc q1,q1
+.byte	0x60,0x43,0xf0,0xf3	@ aesd q10,q8
+.byte	0xe4,0x43,0xf0,0xf3	@ aesimc q10,q10
+	veor	q4,q6,q7
+	subs	r2,r2,#0x30
+	veor	q5,q2,q7
+	movlo	r6,r2			@ r6, r6, is zero at this point
+.byte	0x62,0x03,0xb0,0xf3	@ aesd q0,q9
+.byte	0xc0,0x03,0xb0,0xf3	@ aesimc q0,q0
+.byte	0x62,0x23,0xb0,0xf3	@ aesd q1,q9
+.byte	0xc2,0x23,0xb0,0xf3	@ aesimc q1,q1
+.byte	0x62,0x43,0xf0,0xf3	@ aesd q10,q9
+.byte	0xe4,0x43,0xf0,0xf3	@ aesimc q10,q10
+	veor	q9,q3,q7
+	add	r0,r0,r6		@ r0 is adjusted in such way that
+					@ at exit from the loop q1-q10
+					@ are loaded with last "words"
+	vorr	q6,q11,q11
+	mov	r7,r3
+.byte	0x68,0x03,0xb0,0xf3	@ aesd q0,q12
+.byte	0xc0,0x03,0xb0,0xf3	@ aesimc q0,q0
+.byte	0x68,0x23,0xb0,0xf3	@ aesd q1,q12
+.byte	0xc2,0x23,0xb0,0xf3	@ aesimc q1,q1
+.byte	0x68,0x43,0xf0,0xf3	@ aesd q10,q12
+.byte	0xe4,0x43,0xf0,0xf3	@ aesimc q10,q10
+	vld1.8	{q2},[r0]!
+.byte	0x6a,0x03,0xb0,0xf3	@ aesd q0,q13
+.byte	0xc0,0x03,0xb0,0xf3	@ aesimc q0,q0
+.byte	0x6a,0x23,0xb0,0xf3	@ aesd q1,q13
+.byte	0xc2,0x23,0xb0,0xf3	@ aesimc q1,q1
+.byte	0x6a,0x43,0xf0,0xf3	@ aesd q10,q13
+.byte	0xe4,0x43,0xf0,0xf3	@ aesimc q10,q10
+	vld1.8	{q3},[r0]!
+.byte	0x6c,0x03,0xb0,0xf3	@ aesd q0,q14
+.byte	0xc0,0x03,0xb0,0xf3	@ aesimc q0,q0
+.byte	0x6c,0x23,0xb0,0xf3	@ aesd q1,q14
+.byte	0xc2,0x23,0xb0,0xf3	@ aesimc q1,q1
+.byte	0x6c,0x43,0xf0,0xf3	@ aesd q10,q14
+.byte	0xe4,0x43,0xf0,0xf3	@ aesimc q10,q10
+	vld1.8	{q11},[r0]!
+.byte	0x6e,0x03,0xb0,0xf3	@ aesd q0,q15
+.byte	0x6e,0x23,0xb0,0xf3	@ aesd q1,q15
+.byte	0x6e,0x43,0xf0,0xf3	@ aesd q10,q15
+	vld1.32	{q8},[r7]!	@ re-pre-load rndkey[0]
+	add	r6,r5,#2
+	veor	q4,q4,q0
+	veor	q5,q5,q1
+	veor	q10,q10,q9
+	vld1.32	{q9},[r7]!	@ re-pre-load rndkey[1]
+	vst1.8	{q4},[r1]!
+	vorr	q0,q2,q2
+	vst1.8	{q5},[r1]!
+	vorr	q1,q3,q3
+	vst1.8	{q10},[r1]!
+	vorr	q10,q11,q11
+	bhs	Loop3x_cbc_dec
+
+	cmn	r2,#0x30
+	beq	Lcbc_done
+	nop
+
+Lcbc_dec_tail:
+.byte	0x60,0x23,0xb0,0xf3	@ aesd q1,q8
+.byte	0xc2,0x23,0xb0,0xf3	@ aesimc q1,q1
+.byte	0x60,0x43,0xf0,0xf3	@ aesd q10,q8
+.byte	0xe4,0x43,0xf0,0xf3	@ aesimc q10,q10
+	vld1.32	{q8},[r7]!
+	subs	r6,r6,#2
+.byte	0x62,0x23,0xb0,0xf3	@ aesd q1,q9
+.byte	0xc2,0x23,0xb0,0xf3	@ aesimc q1,q1
+.byte	0x62,0x43,0xf0,0xf3	@ aesd q10,q9
+.byte	0xe4,0x43,0xf0,0xf3	@ aesimc q10,q10
+	vld1.32	{q9},[r7]!
+	bgt	Lcbc_dec_tail
+
+.byte	0x60,0x23,0xb0,0xf3	@ aesd q1,q8
+.byte	0xc2,0x23,0xb0,0xf3	@ aesimc q1,q1
+.byte	0x60,0x43,0xf0,0xf3	@ aesd q10,q8
+.byte	0xe4,0x43,0xf0,0xf3	@ aesimc q10,q10
+.byte	0x62,0x23,0xb0,0xf3	@ aesd q1,q9
+.byte	0xc2,0x23,0xb0,0xf3	@ aesimc q1,q1
+.byte	0x62,0x43,0xf0,0xf3	@ aesd q10,q9
+.byte	0xe4,0x43,0xf0,0xf3	@ aesimc q10,q10
+.byte	0x68,0x23,0xb0,0xf3	@ aesd q1,q12
+.byte	0xc2,0x23,0xb0,0xf3	@ aesimc q1,q1
+.byte	0x68,0x43,0xf0,0xf3	@ aesd q10,q12
+.byte	0xe4,0x43,0xf0,0xf3	@ aesimc q10,q10
+	cmn	r2,#0x20
+.byte	0x6a,0x23,0xb0,0xf3	@ aesd q1,q13
+.byte	0xc2,0x23,0xb0,0xf3	@ aesimc q1,q1
+.byte	0x6a,0x43,0xf0,0xf3	@ aesd q10,q13
+.byte	0xe4,0x43,0xf0,0xf3	@ aesimc q10,q10
+	veor	q5,q6,q7
+.byte	0x6c,0x23,0xb0,0xf3	@ aesd q1,q14
+.byte	0xc2,0x23,0xb0,0xf3	@ aesimc q1,q1
+.byte	0x6c,0x43,0xf0,0xf3	@ aesd q10,q14
+.byte	0xe4,0x43,0xf0,0xf3	@ aesimc q10,q10
+	veor	q9,q3,q7
+.byte	0x6e,0x23,0xb0,0xf3	@ aesd q1,q15
+.byte	0x6e,0x43,0xf0,0xf3	@ aesd q10,q15
+	beq	Lcbc_dec_one
+	veor	q5,q5,q1
+	veor	q9,q9,q10
+	vorr	q6,q11,q11
+	vst1.8	{q5},[r1]!
+	vst1.8	{q9},[r1]!
+	b	Lcbc_done
+
+Lcbc_dec_one:
+	veor	q5,q5,q10
+	vorr	q6,q11,q11
+	vst1.8	{q5},[r1]!
+
+Lcbc_done:
+	vst1.8	{q6},[r4]
+Lcbc_abort:
+	vldmia	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}
+	ldmia	sp!,{r4,r5,r6,r7,r8,pc}
+
+.globl	_aes_hw_ctr32_encrypt_blocks
+.private_extern	_aes_hw_ctr32_encrypt_blocks
+
+.align	5
+_aes_hw_ctr32_encrypt_blocks:
+	mov	ip,sp
+	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,lr}
+	vstmdb	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}            @ ABI specification says so
+	ldr	r4, [ip]		@ load remaining arg
+	ldr	r5,[r3,#240]
+
+	ldr	r8, [r4, #12]
+	vld1.32	{q0},[r4]
+
+	vld1.32	{q8,q9},[r3]		@ load key schedule...
+	sub	r5,r5,#4
+	mov	r12,#16
+	cmp	r2,#2
+	add	r7,r3,r5,lsl#4	@ pointer to last 5 round keys
+	sub	r5,r5,#2
+	vld1.32	{q12,q13},[r7]!
+	vld1.32	{q14,q15},[r7]!
+	vld1.32	{q7},[r7]
+	add	r7,r3,#32
+	mov	r6,r5
+	movlo	r12,#0
+#ifndef __ARMEB__
+	rev	r8, r8
+#endif
+	vorr	q1,q0,q0
+	add	r10, r8, #1
+	vorr	q10,q0,q0
+	add	r8, r8, #2
+	vorr	q6,q0,q0
+	rev	r10, r10
+	vmov.32	d3[1],r10
+	bls	Lctr32_tail
+	rev	r12, r8
+	sub	r2,r2,#3		@ bias
+	vmov.32	d21[1],r12
+	b	Loop3x_ctr32
+
+.align	4
+Loop3x_ctr32:
+.byte	0x20,0x03,0xb0,0xf3	@ aese q0,q8
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+.byte	0x20,0x23,0xb0,0xf3	@ aese q1,q8
+.byte	0x82,0x23,0xb0,0xf3	@ aesmc q1,q1
+.byte	0x20,0x43,0xf0,0xf3	@ aese q10,q8
+.byte	0xa4,0x43,0xf0,0xf3	@ aesmc q10,q10
+	vld1.32	{q8},[r7]!
+	subs	r6,r6,#2
+.byte	0x22,0x03,0xb0,0xf3	@ aese q0,q9
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+.byte	0x22,0x23,0xb0,0xf3	@ aese q1,q9
+.byte	0x82,0x23,0xb0,0xf3	@ aesmc q1,q1
+.byte	0x22,0x43,0xf0,0xf3	@ aese q10,q9
+.byte	0xa4,0x43,0xf0,0xf3	@ aesmc q10,q10
+	vld1.32	{q9},[r7]!
+	bgt	Loop3x_ctr32
+
+.byte	0x20,0x03,0xb0,0xf3	@ aese q0,q8
+.byte	0x80,0x83,0xb0,0xf3	@ aesmc q4,q0
+.byte	0x20,0x23,0xb0,0xf3	@ aese q1,q8
+.byte	0x82,0xa3,0xb0,0xf3	@ aesmc q5,q1
+	vld1.8	{q2},[r0]!
+	vorr	q0,q6,q6
+.byte	0x20,0x43,0xf0,0xf3	@ aese q10,q8
+.byte	0xa4,0x43,0xf0,0xf3	@ aesmc q10,q10
+	vld1.8	{q3},[r0]!
+	vorr	q1,q6,q6
+.byte	0x22,0x83,0xb0,0xf3	@ aese q4,q9
+.byte	0x88,0x83,0xb0,0xf3	@ aesmc q4,q4
+.byte	0x22,0xa3,0xb0,0xf3	@ aese q5,q9
+.byte	0x8a,0xa3,0xb0,0xf3	@ aesmc q5,q5
+	vld1.8	{q11},[r0]!
+	mov	r7,r3
+.byte	0x22,0x43,0xf0,0xf3	@ aese q10,q9
+.byte	0xa4,0x23,0xf0,0xf3	@ aesmc q9,q10
+	vorr	q10,q6,q6
+	add	r9,r8,#1
+.byte	0x28,0x83,0xb0,0xf3	@ aese q4,q12
+.byte	0x88,0x83,0xb0,0xf3	@ aesmc q4,q4
+.byte	0x28,0xa3,0xb0,0xf3	@ aese q5,q12
+.byte	0x8a,0xa3,0xb0,0xf3	@ aesmc q5,q5
+	veor	q2,q2,q7
+	add	r10,r8,#2
+.byte	0x28,0x23,0xf0,0xf3	@ aese q9,q12
+.byte	0xa2,0x23,0xf0,0xf3	@ aesmc q9,q9
+	veor	q3,q3,q7
+	add	r8,r8,#3
+.byte	0x2a,0x83,0xb0,0xf3	@ aese q4,q13
+.byte	0x88,0x83,0xb0,0xf3	@ aesmc q4,q4
+.byte	0x2a,0xa3,0xb0,0xf3	@ aese q5,q13
+.byte	0x8a,0xa3,0xb0,0xf3	@ aesmc q5,q5
+	veor	q11,q11,q7
+	rev	r9,r9
+.byte	0x2a,0x23,0xf0,0xf3	@ aese q9,q13
+.byte	0xa2,0x23,0xf0,0xf3	@ aesmc q9,q9
+	vmov.32	d1[1], r9
+	rev	r10,r10
+.byte	0x2c,0x83,0xb0,0xf3	@ aese q4,q14
+.byte	0x88,0x83,0xb0,0xf3	@ aesmc q4,q4
+.byte	0x2c,0xa3,0xb0,0xf3	@ aese q5,q14
+.byte	0x8a,0xa3,0xb0,0xf3	@ aesmc q5,q5
+	vmov.32	d3[1], r10
+	rev	r12,r8
+.byte	0x2c,0x23,0xf0,0xf3	@ aese q9,q14
+.byte	0xa2,0x23,0xf0,0xf3	@ aesmc q9,q9
+	vmov.32	d21[1], r12
+	subs	r2,r2,#3
+.byte	0x2e,0x83,0xb0,0xf3	@ aese q4,q15
+.byte	0x2e,0xa3,0xb0,0xf3	@ aese q5,q15
+.byte	0x2e,0x23,0xf0,0xf3	@ aese q9,q15
+
+	veor	q2,q2,q4
+	vld1.32	{q8},[r7]!	@ re-pre-load rndkey[0]
+	vst1.8	{q2},[r1]!
+	veor	q3,q3,q5
+	mov	r6,r5
+	vst1.8	{q3},[r1]!
+	veor	q11,q11,q9
+	vld1.32	{q9},[r7]!	@ re-pre-load rndkey[1]
+	vst1.8	{q11},[r1]!
+	bhs	Loop3x_ctr32
+
+	adds	r2,r2,#3
+	beq	Lctr32_done
+	cmp	r2,#1
+	mov	r12,#16
+	moveq	r12,#0
+
+Lctr32_tail:
+.byte	0x20,0x03,0xb0,0xf3	@ aese q0,q8
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+.byte	0x20,0x23,0xb0,0xf3	@ aese q1,q8
+.byte	0x82,0x23,0xb0,0xf3	@ aesmc q1,q1
+	vld1.32	{q8},[r7]!
+	subs	r6,r6,#2
+.byte	0x22,0x03,0xb0,0xf3	@ aese q0,q9
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+.byte	0x22,0x23,0xb0,0xf3	@ aese q1,q9
+.byte	0x82,0x23,0xb0,0xf3	@ aesmc q1,q1
+	vld1.32	{q9},[r7]!
+	bgt	Lctr32_tail
+
+.byte	0x20,0x03,0xb0,0xf3	@ aese q0,q8
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+.byte	0x20,0x23,0xb0,0xf3	@ aese q1,q8
+.byte	0x82,0x23,0xb0,0xf3	@ aesmc q1,q1
+.byte	0x22,0x03,0xb0,0xf3	@ aese q0,q9
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+.byte	0x22,0x23,0xb0,0xf3	@ aese q1,q9
+.byte	0x82,0x23,0xb0,0xf3	@ aesmc q1,q1
+	vld1.8	{q2},[r0],r12
+.byte	0x28,0x03,0xb0,0xf3	@ aese q0,q12
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+.byte	0x28,0x23,0xb0,0xf3	@ aese q1,q12
+.byte	0x82,0x23,0xb0,0xf3	@ aesmc q1,q1
+	vld1.8	{q3},[r0]
+.byte	0x2a,0x03,0xb0,0xf3	@ aese q0,q13
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+.byte	0x2a,0x23,0xb0,0xf3	@ aese q1,q13
+.byte	0x82,0x23,0xb0,0xf3	@ aesmc q1,q1
+	veor	q2,q2,q7
+.byte	0x2c,0x03,0xb0,0xf3	@ aese q0,q14
+.byte	0x80,0x03,0xb0,0xf3	@ aesmc q0,q0
+.byte	0x2c,0x23,0xb0,0xf3	@ aese q1,q14
+.byte	0x82,0x23,0xb0,0xf3	@ aesmc q1,q1
+	veor	q3,q3,q7
+.byte	0x2e,0x03,0xb0,0xf3	@ aese q0,q15
+.byte	0x2e,0x23,0xb0,0xf3	@ aese q1,q15
+
+	cmp	r2,#1
+	veor	q2,q2,q0
+	veor	q3,q3,q1
+	vst1.8	{q2},[r1]!
+	beq	Lctr32_done
+	vst1.8	{q3},[r1]
+
+Lctr32_done:
+	vldmia	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,pc}
+
+#endif
diff --git a/third_party/boringssl/ios-arm/crypto/fipsmodule/armv4-mont.S b/third_party/boringssl/ios-arm/crypto/fipsmodule/armv4-mont.S
new file mode 100644
index 0000000..ba6c2a56
--- /dev/null
+++ b/third_party/boringssl/ios-arm/crypto/fipsmodule/armv4-mont.S
@@ -0,0 +1,591 @@
+#include <openssl/arm_arch.h>
+
+.text
+.code	32
+
+#if __ARM_MAX_ARCH__>=7
+.align	5
+LOPENSSL_armcap:
+.word	OPENSSL_armcap_P-Lbn_mul_mont
+#endif
+
+.globl	_bn_mul_mont
+.private_extern	_bn_mul_mont
+
+
+.align	5
+_bn_mul_mont:
+Lbn_mul_mont:
+	ldr	ip,[sp,#4]		@ load num
+	stmdb	sp!,{r0,r2}		@ sp points at argument block
+#if __ARM_MAX_ARCH__>=7
+	tst	ip,#7
+	bne	Lialu
+	adr	r0,_bn_mul_mont
+	ldr	r2,LOPENSSL_armcap
+	ldr	r0,[r0,r2]
+#ifdef	__APPLE__
+	ldr	r0,[r0]
+#endif
+	tst	r0,#ARMV7_NEON		@ NEON available?
+	ldmia	sp, {r0,r2}
+	beq	Lialu
+	add	sp,sp,#8
+	b	bn_mul8x_mont_neon
+.align	4
+Lialu:
+#endif
+	cmp	ip,#2
+	mov	r0,ip			@ load num
+	movlt	r0,#0
+	addlt	sp,sp,#2*4
+	blt	Labrt
+
+	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}		@ save 10 registers
+
+	mov	r0,r0,lsl#2		@ rescale r0 for byte count
+	sub	sp,sp,r0		@ alloca(4*num)
+	sub	sp,sp,#4		@ +extra dword
+	sub	r0,r0,#4		@ "num=num-1"
+	add	r4,r2,r0		@ &bp[num-1]
+
+	add	r0,sp,r0		@ r0 to point at &tp[num-1]
+	ldr	r8,[r0,#14*4]		@ &n0
+	ldr	r2,[r2]		@ bp[0]
+	ldr	r5,[r1],#4		@ ap[0],ap++
+	ldr	r6,[r3],#4		@ np[0],np++
+	ldr	r8,[r8]		@ *n0
+	str	r4,[r0,#15*4]		@ save &bp[num]
+
+	umull	r10,r11,r5,r2	@ ap[0]*bp[0]
+	str	r8,[r0,#14*4]		@ save n0 value
+	mul	r8,r10,r8		@ "tp[0]"*n0
+	mov	r12,#0
+	umlal	r10,r12,r6,r8	@ np[0]*n0+"t[0]"
+	mov	r4,sp
+
+L1st:
+	ldr	r5,[r1],#4		@ ap[j],ap++
+	mov	r10,r11
+	ldr	r6,[r3],#4		@ np[j],np++
+	mov	r11,#0
+	umlal	r10,r11,r5,r2	@ ap[j]*bp[0]
+	mov	r14,#0
+	umlal	r12,r14,r6,r8	@ np[j]*n0
+	adds	r12,r12,r10
+	str	r12,[r4],#4		@ tp[j-1]=,tp++
+	adc	r12,r14,#0
+	cmp	r4,r0
+	bne	L1st
+
+	adds	r12,r12,r11
+	ldr	r4,[r0,#13*4]		@ restore bp
+	mov	r14,#0
+	ldr	r8,[r0,#14*4]		@ restore n0
+	adc	r14,r14,#0
+	str	r12,[r0]		@ tp[num-1]=
+	str	r14,[r0,#4]		@ tp[num]=
+
+Louter:
+	sub	r7,r0,sp		@ "original" r0-1 value
+	sub	r1,r1,r7		@ "rewind" ap to &ap[1]
+	ldr	r2,[r4,#4]!		@ *(++bp)
+	sub	r3,r3,r7		@ "rewind" np to &np[1]
+	ldr	r5,[r1,#-4]		@ ap[0]
+	ldr	r10,[sp]		@ tp[0]
+	ldr	r6,[r3,#-4]		@ np[0]
+	ldr	r7,[sp,#4]		@ tp[1]
+
+	mov	r11,#0
+	umlal	r10,r11,r5,r2	@ ap[0]*bp[i]+tp[0]
+	str	r4,[r0,#13*4]		@ save bp
+	mul	r8,r10,r8
+	mov	r12,#0
+	umlal	r10,r12,r6,r8	@ np[0]*n0+"tp[0]"
+	mov	r4,sp
+
+Linner:
+	ldr	r5,[r1],#4		@ ap[j],ap++
+	adds	r10,r11,r7		@ +=tp[j]
+	ldr	r6,[r3],#4		@ np[j],np++
+	mov	r11,#0
+	umlal	r10,r11,r5,r2	@ ap[j]*bp[i]
+	mov	r14,#0
+	umlal	r12,r14,r6,r8	@ np[j]*n0
+	adc	r11,r11,#0
+	ldr	r7,[r4,#8]		@ tp[j+1]
+	adds	r12,r12,r10
+	str	r12,[r4],#4		@ tp[j-1]=,tp++
+	adc	r12,r14,#0
+	cmp	r4,r0
+	bne	Linner
+
+	adds	r12,r12,r11
+	mov	r14,#0
+	ldr	r4,[r0,#13*4]		@ restore bp
+	adc	r14,r14,#0
+	ldr	r8,[r0,#14*4]		@ restore n0
+	adds	r12,r12,r7
+	ldr	r7,[r0,#15*4]		@ restore &bp[num]
+	adc	r14,r14,#0
+	str	r12,[r0]		@ tp[num-1]=
+	str	r14,[r0,#4]		@ tp[num]=
+
+	cmp	r4,r7
+	bne	Louter
+
+	ldr	r2,[r0,#12*4]		@ pull rp
+	add	r0,r0,#4		@ r0 to point at &tp[num]
+	sub	r5,r0,sp		@ "original" num value
+	mov	r4,sp			@ "rewind" r4
+	mov	r1,r4			@ "borrow" r1
+	sub	r3,r3,r5		@ "rewind" r3 to &np[0]
+
+	subs	r7,r7,r7		@ "clear" carry flag
+Lsub:	ldr	r7,[r4],#4
+	ldr	r6,[r3],#4
+	sbcs	r7,r7,r6		@ tp[j]-np[j]
+	str	r7,[r2],#4		@ rp[j]=
+	teq	r4,r0		@ preserve carry
+	bne	Lsub
+	sbcs	r14,r14,#0		@ upmost carry
+	mov	r4,sp			@ "rewind" r4
+	sub	r2,r2,r5		@ "rewind" r2
+
+	and	r1,r4,r14
+	bic	r3,r2,r14
+	orr	r1,r1,r3		@ ap=borrow?tp:rp
+
+Lcopy:	ldr	r7,[r1],#4		@ copy or in-place refresh
+	str	sp,[r4],#4		@ zap tp
+	str	r7,[r2],#4
+	cmp	r4,r0
+	bne	Lcopy
+
+	add	sp,r0,#4		@ skip over tp[num+1]
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}		@ restore registers
+	add	sp,sp,#2*4		@ skip over {r0,r2}
+	mov	r0,#1
+Labrt:
+#if __ARM_ARCH__>=5
+	bx	lr				@ .word	0xe12fff1e
+#else
+	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+
+#if __ARM_MAX_ARCH__>=7
+
+
+
+
+.align	5
+bn_mul8x_mont_neon:
+	mov	ip,sp
+	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11}
+	vstmdb	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}		@ ABI specification says so
+	ldmia	ip,{r4,r5}		@ load rest of parameter block
+
+	sub	r7,sp,#16
+	vld1.32	{d28[0]}, [r2,:32]!
+	sub	r7,r7,r5,lsl#4
+	vld1.32	{d0,d1,d2,d3},  [r1]!		@ can't specify :32 :-(
+	and	r7,r7,#-64
+	vld1.32	{d30[0]}, [r4,:32]
+	mov	sp,r7			@ alloca
+	veor	d8,d8,d8
+	subs	r8,r5,#8
+	vzip.16	d28,d8
+
+	vmull.u32	q6,d28,d0[0]
+	vmull.u32	q7,d28,d0[1]
+	vmull.u32	q8,d28,d1[0]
+	vshl.i64	d10,d13,#16
+	vmull.u32	q9,d28,d1[1]
+
+	vadd.u64	d10,d10,d12
+	veor	d8,d8,d8
+	vmul.u32	d29,d10,d30
+
+	vmull.u32	q10,d28,d2[0]
+	vld1.32	{d4,d5,d6,d7}, [r3]!
+	vmull.u32	q11,d28,d2[1]
+	vmull.u32	q12,d28,d3[0]
+	vzip.16	d29,d8
+	vmull.u32	q13,d28,d3[1]
+
+	bne	LNEON_1st
+
+	@ special case for num=8, everything is in register bank...
+
+	vmlal.u32	q6,d29,d4[0]
+	sub	r9,r5,#1
+	vmlal.u32	q7,d29,d4[1]
+	vmlal.u32	q8,d29,d5[0]
+	vmlal.u32	q9,d29,d5[1]
+
+	vmlal.u32	q10,d29,d6[0]
+	vmov	q5,q6
+	vmlal.u32	q11,d29,d6[1]
+	vmov	q6,q7
+	vmlal.u32	q12,d29,d7[0]
+	vmov	q7,q8
+	vmlal.u32	q13,d29,d7[1]
+	vmov	q8,q9
+	vmov	q9,q10
+	vshr.u64	d10,d10,#16
+	vmov	q10,q11
+	vmov	q11,q12
+	vadd.u64	d10,d10,d11
+	vmov	q12,q13
+	veor	q13,q13
+	vshr.u64	d10,d10,#16
+
+	b	LNEON_outer8
+
+.align	4
+LNEON_outer8:
+	vld1.32	{d28[0]}, [r2,:32]!
+	veor	d8,d8,d8
+	vzip.16	d28,d8
+	vadd.u64	d12,d12,d10
+
+	vmlal.u32	q6,d28,d0[0]
+	vmlal.u32	q7,d28,d0[1]
+	vmlal.u32	q8,d28,d1[0]
+	vshl.i64	d10,d13,#16
+	vmlal.u32	q9,d28,d1[1]
+
+	vadd.u64	d10,d10,d12
+	veor	d8,d8,d8
+	subs	r9,r9,#1
+	vmul.u32	d29,d10,d30
+
+	vmlal.u32	q10,d28,d2[0]
+	vmlal.u32	q11,d28,d2[1]
+	vmlal.u32	q12,d28,d3[0]
+	vzip.16	d29,d8
+	vmlal.u32	q13,d28,d3[1]
+
+	vmlal.u32	q6,d29,d4[0]
+	vmlal.u32	q7,d29,d4[1]
+	vmlal.u32	q8,d29,d5[0]
+	vmlal.u32	q9,d29,d5[1]
+
+	vmlal.u32	q10,d29,d6[0]
+	vmov	q5,q6
+	vmlal.u32	q11,d29,d6[1]
+	vmov	q6,q7
+	vmlal.u32	q12,d29,d7[0]
+	vmov	q7,q8
+	vmlal.u32	q13,d29,d7[1]
+	vmov	q8,q9
+	vmov	q9,q10
+	vshr.u64	d10,d10,#16
+	vmov	q10,q11
+	vmov	q11,q12
+	vadd.u64	d10,d10,d11
+	vmov	q12,q13
+	veor	q13,q13
+	vshr.u64	d10,d10,#16
+
+	bne	LNEON_outer8
+
+	vadd.u64	d12,d12,d10
+	mov	r7,sp
+	vshr.u64	d10,d12,#16
+	mov	r8,r5
+	vadd.u64	d13,d13,d10
+	add	r6,sp,#16
+	vshr.u64	d10,d13,#16
+	vzip.16	d12,d13
+
+	b	LNEON_tail2
+
+.align	4
+LNEON_1st:
+	vmlal.u32	q6,d29,d4[0]
+	vld1.32	{d0,d1,d2,d3}, [r1]!
+	vmlal.u32	q7,d29,d4[1]
+	subs	r8,r8,#8
+	vmlal.u32	q8,d29,d5[0]
+	vmlal.u32	q9,d29,d5[1]
+
+	vmlal.u32	q10,d29,d6[0]
+	vld1.32	{d4,d5}, [r3]!
+	vmlal.u32	q11,d29,d6[1]
+	vst1.64	{q6,q7}, [r7,:256]!
+	vmlal.u32	q12,d29,d7[0]
+	vmlal.u32	q13,d29,d7[1]
+	vst1.64	{q8,q9}, [r7,:256]!
+
+	vmull.u32	q6,d28,d0[0]
+	vld1.32	{d6,d7}, [r3]!
+	vmull.u32	q7,d28,d0[1]
+	vst1.64	{q10,q11}, [r7,:256]!
+	vmull.u32	q8,d28,d1[0]
+	vmull.u32	q9,d28,d1[1]
+	vst1.64	{q12,q13}, [r7,:256]!
+
+	vmull.u32	q10,d28,d2[0]
+	vmull.u32	q11,d28,d2[1]
+	vmull.u32	q12,d28,d3[0]
+	vmull.u32	q13,d28,d3[1]
+
+	bne	LNEON_1st
+
+	vmlal.u32	q6,d29,d4[0]
+	add	r6,sp,#16
+	vmlal.u32	q7,d29,d4[1]
+	sub	r1,r1,r5,lsl#2		@ rewind r1
+	vmlal.u32	q8,d29,d5[0]
+	vld1.64	{q5}, [sp,:128]
+	vmlal.u32	q9,d29,d5[1]
+	sub	r9,r5,#1
+
+	vmlal.u32	q10,d29,d6[0]
+	vst1.64	{q6,q7}, [r7,:256]!
+	vmlal.u32	q11,d29,d6[1]
+	vshr.u64	d10,d10,#16
+	vld1.64	{q6},       [r6, :128]!
+	vmlal.u32	q12,d29,d7[0]
+	vst1.64	{q8,q9}, [r7,:256]!
+	vmlal.u32	q13,d29,d7[1]
+
+	vst1.64	{q10,q11}, [r7,:256]!
+	vadd.u64	d10,d10,d11
+	veor	q4,q4,q4
+	vst1.64	{q12,q13}, [r7,:256]!
+	vld1.64	{q7,q8}, [r6, :256]!
+	vst1.64	{q4},          [r7,:128]
+	vshr.u64	d10,d10,#16
+
+	b	LNEON_outer
+
+.align	4
+LNEON_outer:
+	vld1.32	{d28[0]}, [r2,:32]!
+	sub	r3,r3,r5,lsl#2		@ rewind r3
+	vld1.32	{d0,d1,d2,d3},  [r1]!
+	veor	d8,d8,d8
+	mov	r7,sp
+	vzip.16	d28,d8
+	sub	r8,r5,#8
+	vadd.u64	d12,d12,d10
+
+	vmlal.u32	q6,d28,d0[0]
+	vld1.64	{q9,q10},[r6,:256]!
+	vmlal.u32	q7,d28,d0[1]
+	vmlal.u32	q8,d28,d1[0]
+	vld1.64	{q11,q12},[r6,:256]!
+	vmlal.u32	q9,d28,d1[1]
+
+	vshl.i64	d10,d13,#16
+	veor	d8,d8,d8
+	vadd.u64	d10,d10,d12
+	vld1.64	{q13},[r6,:128]!
+	vmul.u32	d29,d10,d30
+
+	vmlal.u32	q10,d28,d2[0]
+	vld1.32	{d4,d5,d6,d7}, [r3]!
+	vmlal.u32	q11,d28,d2[1]
+	vmlal.u32	q12,d28,d3[0]
+	vzip.16	d29,d8
+	vmlal.u32	q13,d28,d3[1]
+
+LNEON_inner:
+	vmlal.u32	q6,d29,d4[0]
+	vld1.32	{d0,d1,d2,d3}, [r1]!
+	vmlal.u32	q7,d29,d4[1]
+	subs	r8,r8,#8
+	vmlal.u32	q8,d29,d5[0]
+	vmlal.u32	q9,d29,d5[1]
+	vst1.64	{q6,q7}, [r7,:256]!
+
+	vmlal.u32	q10,d29,d6[0]
+	vld1.64	{q6},       [r6, :128]!
+	vmlal.u32	q11,d29,d6[1]
+	vst1.64	{q8,q9}, [r7,:256]!
+	vmlal.u32	q12,d29,d7[0]
+	vld1.64	{q7,q8}, [r6, :256]!
+	vmlal.u32	q13,d29,d7[1]
+	vst1.64	{q10,q11}, [r7,:256]!
+
+	vmlal.u32	q6,d28,d0[0]
+	vld1.64	{q9,q10}, [r6, :256]!
+	vmlal.u32	q7,d28,d0[1]
+	vst1.64	{q12,q13}, [r7,:256]!
+	vmlal.u32	q8,d28,d1[0]
+	vld1.64	{q11,q12}, [r6, :256]!
+	vmlal.u32	q9,d28,d1[1]
+	vld1.32	{d4,d5,d6,d7}, [r3]!
+
+	vmlal.u32	q10,d28,d2[0]
+	vld1.64	{q13},       [r6, :128]!
+	vmlal.u32	q11,d28,d2[1]
+	vmlal.u32	q12,d28,d3[0]
+	vmlal.u32	q13,d28,d3[1]
+
+	bne	LNEON_inner
+
+	vmlal.u32	q6,d29,d4[0]
+	add	r6,sp,#16
+	vmlal.u32	q7,d29,d4[1]
+	sub	r1,r1,r5,lsl#2		@ rewind r1
+	vmlal.u32	q8,d29,d5[0]
+	vld1.64	{q5}, [sp,:128]
+	vmlal.u32	q9,d29,d5[1]
+	subs	r9,r9,#1
+
+	vmlal.u32	q10,d29,d6[0]
+	vst1.64	{q6,q7}, [r7,:256]!
+	vmlal.u32	q11,d29,d6[1]
+	vld1.64	{q6},       [r6, :128]!
+	vshr.u64	d10,d10,#16
+	vst1.64	{q8,q9}, [r7,:256]!
+	vmlal.u32	q12,d29,d7[0]
+	vld1.64	{q7,q8}, [r6, :256]!
+	vmlal.u32	q13,d29,d7[1]
+
+	vst1.64	{q10,q11}, [r7,:256]!
+	vadd.u64	d10,d10,d11
+	vst1.64	{q12,q13}, [r7,:256]!
+	vshr.u64	d10,d10,#16
+
+	bne	LNEON_outer
+
+	mov	r7,sp
+	mov	r8,r5
+
+LNEON_tail:
+	vadd.u64	d12,d12,d10
+	vld1.64	{q9,q10}, [r6, :256]!
+	vshr.u64	d10,d12,#16
+	vadd.u64	d13,d13,d10
+	vld1.64	{q11,q12}, [r6, :256]!
+	vshr.u64	d10,d13,#16
+	vld1.64	{q13},       [r6, :128]!
+	vzip.16	d12,d13
+
+LNEON_tail2:
+	vadd.u64	d14,d14,d10
+	vst1.32	{d12[0]}, [r7, :32]!
+	vshr.u64	d10,d14,#16
+	vadd.u64	d15,d15,d10
+	vshr.u64	d10,d15,#16
+	vzip.16	d14,d15
+
+	vadd.u64	d16,d16,d10
+	vst1.32	{d14[0]}, [r7, :32]!
+	vshr.u64	d10,d16,#16
+	vadd.u64	d17,d17,d10
+	vshr.u64	d10,d17,#16
+	vzip.16	d16,d17
+
+	vadd.u64	d18,d18,d10
+	vst1.32	{d16[0]}, [r7, :32]!
+	vshr.u64	d10,d18,#16
+	vadd.u64	d19,d19,d10
+	vshr.u64	d10,d19,#16
+	vzip.16	d18,d19
+
+	vadd.u64	d20,d20,d10
+	vst1.32	{d18[0]}, [r7, :32]!
+	vshr.u64	d10,d20,#16
+	vadd.u64	d21,d21,d10
+	vshr.u64	d10,d21,#16
+	vzip.16	d20,d21
+
+	vadd.u64	d22,d22,d10
+	vst1.32	{d20[0]}, [r7, :32]!
+	vshr.u64	d10,d22,#16
+	vadd.u64	d23,d23,d10
+	vshr.u64	d10,d23,#16
+	vzip.16	d22,d23
+
+	vadd.u64	d24,d24,d10
+	vst1.32	{d22[0]}, [r7, :32]!
+	vshr.u64	d10,d24,#16
+	vadd.u64	d25,d25,d10
+	vld1.64	{q6}, [r6, :128]!
+	vshr.u64	d10,d25,#16
+	vzip.16	d24,d25
+
+	vadd.u64	d26,d26,d10
+	vst1.32	{d24[0]}, [r7, :32]!
+	vshr.u64	d10,d26,#16
+	vadd.u64	d27,d27,d10
+	vld1.64	{q7,q8},	[r6, :256]!
+	vshr.u64	d10,d27,#16
+	vzip.16	d26,d27
+	subs	r8,r8,#8
+	vst1.32	{d26[0]}, [r7, :32]!
+
+	bne	LNEON_tail
+
+	vst1.32	{d10[0]}, [r7, :32]		@ top-most bit
+	sub	r3,r3,r5,lsl#2			@ rewind r3
+	subs	r1,sp,#0				@ clear carry flag
+	add	r2,sp,r5,lsl#2
+
+LNEON_sub:
+	ldmia	r1!, {r4,r5,r6,r7}
+	ldmia	r3!, {r8,r9,r10,r11}
+	sbcs	r8, r4,r8
+	sbcs	r9, r5,r9
+	sbcs	r10,r6,r10
+	sbcs	r11,r7,r11
+	teq	r1,r2				@ preserves carry
+	stmia	r0!, {r8,r9,r10,r11}
+	bne	LNEON_sub
+
+	ldr	r10, [r1]				@ load top-most bit
+	veor	q0,q0,q0
+	sub	r11,r2,sp				@ this is num*4
+	veor	q1,q1,q1
+	mov	r1,sp
+	sub	r0,r0,r11				@ rewind r0
+	mov	r3,r2				@ second 3/4th of frame
+	sbcs	r10,r10,#0				@ result is carry flag
+
+LNEON_copy_n_zap:
+	ldmia	r1!, {r4,r5,r6,r7}
+	ldmia	r0,  {r8,r9,r10,r11}
+	movcc	r8, r4
+	vst1.64	{q0,q1}, [r3,:256]!			@ wipe
+	movcc	r9, r5
+	movcc	r10,r6
+	vst1.64	{q0,q1}, [r3,:256]!			@ wipe
+	movcc	r11,r7
+	ldmia	r1, {r4,r5,r6,r7}
+	stmia	r0!, {r8,r9,r10,r11}
+	sub	r1,r1,#16
+	ldmia	r0, {r8,r9,r10,r11}
+	movcc	r8, r4
+	vst1.64	{q0,q1}, [r1,:256]!			@ wipe
+	movcc	r9, r5
+	movcc	r10,r6
+	vst1.64	{q0,q1}, [r3,:256]!			@ wipe
+	movcc	r11,r7
+	teq	r1,r2				@ preserves carry
+	stmia	r0!, {r8,r9,r10,r11}
+	bne	LNEON_copy_n_zap
+
+	sub	sp,ip,#96
+	vldmia	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11}
+	bx	lr						@ .word	0xe12fff1e
+
+#endif
+.byte	77,111,110,116,103,111,109,101,114,121,32,109,117,108,116,105,112,108,105,99,97,116,105,111,110,32,102,111,114,32,65,82,77,118,52,47,78,69,79,78,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+.align	2
+#if __ARM_MAX_ARCH__>=7
+.comm	_OPENSSL_armcap_P,4
+.non_lazy_symbol_pointer
+OPENSSL_armcap_P:
+.indirect_symbol	_OPENSSL_armcap_P
+.long	0
+.private_extern	_OPENSSL_armcap_P
+#endif
diff --git a/third_party/boringssl/ios-arm/crypto/fipsmodule/bsaes-armv7.S b/third_party/boringssl/ios-arm/crypto/fipsmodule/bsaes-armv7.S
new file mode 100644
index 0000000..77cb269
--- /dev/null
+++ b/third_party/boringssl/ios-arm/crypto/fipsmodule/bsaes-armv7.S
@@ -0,0 +1,2565 @@
+@ Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
+@
+@ Licensed under the OpenSSL license (the "License").  You may not use
+@ this file except in compliance with the License.  You can obtain a copy
+@ in the file LICENSE in the source distribution or at
+@ https://www.openssl.org/source/license.html
+
+
+@ ====================================================================
+@ Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+@ project. The module is, however, dual licensed under OpenSSL and
+@ CRYPTOGAMS licenses depending on where you obtain it. For further
+@ details see http://www.openssl.org/~appro/cryptogams/.
+@
+@ Specific modes and adaptation for Linux kernel by Ard Biesheuvel
+@ <ard.biesheuvel@linaro.org>. Permission to use under GPL terms is
+@ granted.
+@ ====================================================================
+
+@ Bit-sliced AES for ARM NEON
+@
+@ February 2012.
+@
+@ This implementation is direct adaptation of bsaes-x86_64 module for
+@ ARM NEON. Except that this module is endian-neutral [in sense that
+@ it can be compiled for either endianness] by courtesy of vld1.8's
+@ neutrality. Initial version doesn't implement interface to OpenSSL,
+@ only low-level primitives and unsupported entry points, just enough
+@ to collect performance results, which for Cortex-A8 core are:
+@
+@ encrypt	19.5 cycles per byte processed with 128-bit key
+@ decrypt	22.1 cycles per byte processed with 128-bit key
+@ key conv.	440  cycles per 128-bit key/0.18 of 8x block
+@
+@ Snapdragon S4 encrypts byte in 17.6 cycles and decrypts in 19.7,
+@ which is [much] worse than anticipated (for further details see
+@ http://www.openssl.org/~appro/Snapdragon-S4.html).
+@
+@ Cortex-A15 manages in 14.2/16.1 cycles [when integer-only code
+@ manages in 20.0 cycles].
+@
+@ When comparing to x86_64 results keep in mind that NEON unit is
+@ [mostly] single-issue and thus can't [fully] benefit from
+@ instruction-level parallelism. And when comparing to aes-armv4
+@ results keep in mind key schedule conversion overhead (see
+@ bsaes-x86_64.pl for further details)...
+@
+@						<appro@openssl.org>
+
+@ April-August 2013
+@
+@ Add CBC, CTR and XTS subroutines, adapt for kernel use.
+@
+@					<ard.biesheuvel@linaro.org>
+
+#ifndef __KERNEL__
+# include <openssl/arm_arch.h>
+
+# define VFP_ABI_PUSH	vstmdb	sp!,{d8-d15}
+# define VFP_ABI_POP	vldmia	sp!,{d8-d15}
+# define VFP_ABI_FRAME	0x40
+#else
+# define VFP_ABI_PUSH
+# define VFP_ABI_POP
+# define VFP_ABI_FRAME	0
+# define BSAES_ASM_EXTENDED_KEY
+# define XTS_CHAIN_TWEAK
+# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_MAX_ARCH__ 7
+#endif
+
+#ifdef __thumb__
+# define adrl adr
+#endif
+
+#if __ARM_MAX_ARCH__>=7
+
+
+
+.text
+.syntax	unified 	@ ARMv7-capable assembler is expected to handle this
+#if defined(__thumb2__) && !defined(__APPLE__)
+.thumb
+#else
+.code	32
+# undef __thumb2__
+#endif
+
+
+.align	4
+_bsaes_decrypt8:
+	adr	r6,_bsaes_decrypt8
+	vldmia	r4!, {q9}		@ round 0 key
+#ifdef	__APPLE__
+	adr	r6,LM0ISR
+#else
+	add	r6,r6,#LM0ISR-_bsaes_decrypt8
+#endif
+
+	vldmia	r6!, {q8}		@ LM0ISR
+	veor	q10, q0, q9	@ xor with round0 key
+	veor	q11, q1, q9
+	vtbl.8	d0, {q10}, d16
+	vtbl.8	d1, {q10}, d17
+	veor	q12, q2, q9
+	vtbl.8	d2, {q11}, d16
+	vtbl.8	d3, {q11}, d17
+	veor	q13, q3, q9
+	vtbl.8	d4, {q12}, d16
+	vtbl.8	d5, {q12}, d17
+	veor	q14, q4, q9
+	vtbl.8	d6, {q13}, d16
+	vtbl.8	d7, {q13}, d17
+	veor	q15, q5, q9
+	vtbl.8	d8, {q14}, d16
+	vtbl.8	d9, {q14}, d17
+	veor	q10, q6, q9
+	vtbl.8	d10, {q15}, d16
+	vtbl.8	d11, {q15}, d17
+	veor	q11, q7, q9
+	vtbl.8	d12, {q10}, d16
+	vtbl.8	d13, {q10}, d17
+	vtbl.8	d14, {q11}, d16
+	vtbl.8	d15, {q11}, d17
+	vmov.i8	q8,#0x55			@ compose LBS0
+	vmov.i8	q9,#0x33			@ compose LBS1
+	vshr.u64	q10, q6, #1
+	vshr.u64	q11, q4, #1
+	veor	q10, q10, q7
+	veor	q11, q11, q5
+	vand	q10, q10, q8
+	vand	q11, q11, q8
+	veor	q7, q7, q10
+	vshl.u64	q10, q10, #1
+	veor	q5, q5, q11
+	vshl.u64	q11, q11, #1
+	veor	q6, q6, q10
+	veor	q4, q4, q11
+	vshr.u64	q10, q2, #1
+	vshr.u64	q11, q0, #1
+	veor	q10, q10, q3
+	veor	q11, q11, q1
+	vand	q10, q10, q8
+	vand	q11, q11, q8
+	veor	q3, q3, q10
+	vshl.u64	q10, q10, #1
+	veor	q1, q1, q11
+	vshl.u64	q11, q11, #1
+	veor	q2, q2, q10
+	veor	q0, q0, q11
+	vmov.i8	q8,#0x0f			@ compose LBS2
+	vshr.u64	q10, q5, #2
+	vshr.u64	q11, q4, #2
+	veor	q10, q10, q7
+	veor	q11, q11, q6
+	vand	q10, q10, q9
+	vand	q11, q11, q9
+	veor	q7, q7, q10
+	vshl.u64	q10, q10, #2
+	veor	q6, q6, q11
+	vshl.u64	q11, q11, #2
+	veor	q5, q5, q10
+	veor	q4, q4, q11
+	vshr.u64	q10, q1, #2
+	vshr.u64	q11, q0, #2
+	veor	q10, q10, q3
+	veor	q11, q11, q2
+	vand	q10, q10, q9
+	vand	q11, q11, q9
+	veor	q3, q3, q10
+	vshl.u64	q10, q10, #2
+	veor	q2, q2, q11
+	vshl.u64	q11, q11, #2
+	veor	q1, q1, q10
+	veor	q0, q0, q11
+	vshr.u64	q10, q3, #4
+	vshr.u64	q11, q2, #4
+	veor	q10, q10, q7
+	veor	q11, q11, q6
+	vand	q10, q10, q8
+	vand	q11, q11, q8
+	veor	q7, q7, q10
+	vshl.u64	q10, q10, #4
+	veor	q6, q6, q11
+	vshl.u64	q11, q11, #4
+	veor	q3, q3, q10
+	veor	q2, q2, q11
+	vshr.u64	q10, q1, #4
+	vshr.u64	q11, q0, #4
+	veor	q10, q10, q5
+	veor	q11, q11, q4
+	vand	q10, q10, q8
+	vand	q11, q11, q8
+	veor	q5, q5, q10
+	vshl.u64	q10, q10, #4
+	veor	q4, q4, q11
+	vshl.u64	q11, q11, #4
+	veor	q1, q1, q10
+	veor	q0, q0, q11
+	sub	r5,r5,#1
+	b	Ldec_sbox
+.align	4
+Ldec_loop:
+	vldmia	r4!, {q8,q9,q10,q11}
+	veor	q8, q8, q0
+	veor	q9, q9, q1
+	vtbl.8	d0, {q8}, d24
+	vtbl.8	d1, {q8}, d25
+	vldmia	r4!, {q8}
+	veor	q10, q10, q2
+	vtbl.8	d2, {q9}, d24
+	vtbl.8	d3, {q9}, d25
+	vldmia	r4!, {q9}
+	veor	q11, q11, q3
+	vtbl.8	d4, {q10}, d24
+	vtbl.8	d5, {q10}, d25
+	vldmia	r4!, {q10}
+	vtbl.8	d6, {q11}, d24
+	vtbl.8	d7, {q11}, d25
+	vldmia	r4!, {q11}
+	veor	q8, q8, q4
+	veor	q9, q9, q5
+	vtbl.8	d8, {q8}, d24
+	vtbl.8	d9, {q8}, d25
+	veor	q10, q10, q6
+	vtbl.8	d10, {q9}, d24
+	vtbl.8	d11, {q9}, d25
+	veor	q11, q11, q7
+	vtbl.8	d12, {q10}, d24
+	vtbl.8	d13, {q10}, d25
+	vtbl.8	d14, {q11}, d24
+	vtbl.8	d15, {q11}, d25
+Ldec_sbox:
+	veor	q1, q1, q4
+	veor	q3, q3, q4
+
+	veor	q4, q4, q7
+	veor	q1, q1, q6
+	veor	q2, q2, q7
+	veor	q6, q6, q4
+
+	veor	q0, q0, q1
+	veor	q2, q2, q5
+	veor	q7, q7, q6
+	veor	q3, q3, q0
+	veor	q5, q5, q0
+	veor	q1, q1, q3
+	veor	q11, q3, q0
+	veor	q10, q7, q4
+	veor	q9, q1, q6
+	veor	q13, q4, q0
+	vmov	q8, q10
+	veor	q12, q5, q2
+
+	vorr	q10, q10, q9
+	veor	q15, q11, q8
+	vand	q14, q11, q12
+	vorr	q11, q11, q12
+	veor	q12, q12, q9
+	vand	q8, q8, q9
+	veor	q9, q6, q2
+	vand	q15, q15, q12
+	vand	q13, q13, q9
+	veor	q9, q3, q7
+	veor	q12, q1, q5
+	veor	q11, q11, q13
+	veor	q10, q10, q13
+	vand	q13, q9, q12
+	vorr	q9, q9, q12
+	veor	q11, q11, q15
+	veor	q8, q8, q13
+	veor	q10, q10, q14
+	veor	q9, q9, q15
+	veor	q8, q8, q14
+	vand	q12, q4, q6
+	veor	q9, q9, q14
+	vand	q13, q0, q2
+	vand	q14, q7, q1
+	vorr	q15, q3, q5
+	veor	q11, q11, q12
+	veor	q9, q9, q14
+	veor	q8, q8, q15
+	veor	q10, q10, q13
+
+	@ Inv_GF16 	0, 	1, 	2, 	3, s0, s1, s2, s3
+
+	@ new smaller inversion
+
+	vand	q14, q11, q9
+	vmov	q12, q8
+
+	veor	q13, q10, q14
+	veor	q15, q8, q14
+	veor	q14, q8, q14	@ q14=q15
+
+	vbsl	q13, q9, q8
+	vbsl	q15, q11, q10
+	veor	q11, q11, q10
+
+	vbsl	q12, q13, q14
+	vbsl	q8, q14, q13
+
+	vand	q14, q12, q15
+	veor	q9, q9, q8
+
+	veor	q14, q14, q11
+	veor	q12, q5, q2
+	veor	q8, q1, q6
+	veor	q10, q15, q14
+	vand	q10, q10, q5
+	veor	q5, q5, q1
+	vand	q11, q1, q15
+	vand	q5, q5, q14
+	veor	q1, q11, q10
+	veor	q5, q5, q11
+	veor	q15, q15, q13
+	veor	q14, q14, q9
+	veor	q11, q15, q14
+	veor	q10, q13, q9
+	vand	q11, q11, q12
+	vand	q10, q10, q2
+	veor	q12, q12, q8
+	veor	q2, q2, q6
+	vand	q8, q8, q15
+	vand	q6, q6, q13
+	vand	q12, q12, q14
+	vand	q2, q2, q9
+	veor	q8, q8, q12
+	veor	q2, q2, q6
+	veor	q12, q12, q11
+	veor	q6, q6, q10
+	veor	q5, q5, q12
+	veor	q2, q2, q12
+	veor	q1, q1, q8
+	veor	q6, q6, q8
+
+	veor	q12, q3, q0
+	veor	q8, q7, q4
+	veor	q11, q15, q14
+	veor	q10, q13, q9
+	vand	q11, q11, q12
+	vand	q10, q10, q0
+	veor	q12, q12, q8
+	veor	q0, q0, q4
+	vand	q8, q8, q15
+	vand	q4, q4, q13
+	vand	q12, q12, q14
+	vand	q0, q0, q9
+	veor	q8, q8, q12
+	veor	q0, q0, q4
+	veor	q12, q12, q11
+	veor	q4, q4, q10
+	veor	q15, q15, q13
+	veor	q14, q14, q9
+	veor	q10, q15, q14
+	vand	q10, q10, q3
+	veor	q3, q3, q7
+	vand	q11, q7, q15
+	vand	q3, q3, q14
+	veor	q7, q11, q10
+	veor	q3, q3, q11
+	veor	q3, q3, q12
+	veor	q0, q0, q12
+	veor	q7, q7, q8
+	veor	q4, q4, q8
+	veor	q1, q1, q7
+	veor	q6, q6, q5
+
+	veor	q4, q4, q1
+	veor	q2, q2, q7
+	veor	q5, q5, q7
+	veor	q4, q4, q2
+	veor	q7, q7, q0
+	veor	q4, q4, q5
+	veor	q3, q3, q6
+	veor	q6, q6, q1
+	veor	q3, q3, q4
+
+	veor	q4, q4, q0
+	veor	q7, q7, q3
+	subs	r5,r5,#1
+	bcc	Ldec_done
+	@ multiplication by 0x05-0x00-0x04-0x00
+	vext.8	q8, q0, q0, #8
+	vext.8	q14, q3, q3, #8
+	vext.8	q15, q5, q5, #8
+	veor	q8, q8, q0
+	vext.8	q9, q1, q1, #8
+	veor	q14, q14, q3
+	vext.8	q10, q6, q6, #8
+	veor	q15, q15, q5
+	vext.8	q11, q4, q4, #8
+	veor	q9, q9, q1
+	vext.8	q12, q2, q2, #8
+	veor	q10, q10, q6
+	vext.8	q13, q7, q7, #8
+	veor	q11, q11, q4
+	veor	q12, q12, q2
+	veor	q13, q13, q7
+
+	veor	q0, q0, q14
+	veor	q1, q1, q14
+	veor	q6, q6, q8
+	veor	q2, q2, q10
+	veor	q4, q4, q9
+	veor	q1, q1, q15
+	veor	q6, q6, q15
+	veor	q2, q2, q14
+	veor	q7, q7, q11
+	veor	q4, q4, q14
+	veor	q3, q3, q12
+	veor	q2, q2, q15
+	veor	q7, q7, q15
+	veor	q5, q5, q13
+	vext.8	q8, q0, q0, #12	@ x0 <<< 32
+	vext.8	q9, q1, q1, #12
+	veor	q0, q0, q8		@ x0 ^ (x0 <<< 32)
+	vext.8	q10, q6, q6, #12
+	veor	q1, q1, q9
+	vext.8	q11, q4, q4, #12
+	veor	q6, q6, q10
+	vext.8	q12, q2, q2, #12
+	veor	q4, q4, q11
+	vext.8	q13, q7, q7, #12
+	veor	q2, q2, q12
+	vext.8	q14, q3, q3, #12
+	veor	q7, q7, q13
+	vext.8	q15, q5, q5, #12
+	veor	q3, q3, q14
+
+	veor	q9, q9, q0
+	veor	q5, q5, q15
+	vext.8	q0, q0, q0, #8		@ (x0 ^ (x0 <<< 32)) <<< 64)
+	veor	q10, q10, q1
+	veor	q8, q8, q5
+	veor	q9, q9, q5
+	vext.8	q1, q1, q1, #8
+	veor	q13, q13, q2
+	veor	q0, q0, q8
+	veor	q14, q14, q7
+	veor	q1, q1, q9
+	vext.8	q8, q2, q2, #8
+	veor	q12, q12, q4
+	vext.8	q9, q7, q7, #8
+	veor	q15, q15, q3
+	vext.8	q2, q4, q4, #8
+	veor	q11, q11, q6
+	vext.8	q7, q5, q5, #8
+	veor	q12, q12, q5
+	vext.8	q4, q3, q3, #8
+	veor	q11, q11, q5
+	vext.8	q3, q6, q6, #8
+	veor	q5, q9, q13
+	veor	q11, q11, q2
+	veor	q7, q7, q15
+	veor	q6, q4, q14
+	veor	q4, q8, q12
+	veor	q2, q3, q10
+	vmov	q3, q11
+	 @ vmov	q5, q9
+	vldmia	r6, {q12}		@ LISR
+	ite	eq				@ Thumb2 thing, sanity check in ARM
+	addeq	r6,r6,#0x10
+	bne	Ldec_loop
+	vldmia	r6, {q12}		@ LISRM0
+	b	Ldec_loop
+.align	4
+Ldec_done:
+	vmov.i8	q8,#0x55			@ compose LBS0
+	vmov.i8	q9,#0x33			@ compose LBS1
+	vshr.u64	q10, q3, #1
+	vshr.u64	q11, q2, #1
+	veor	q10, q10, q5
+	veor	q11, q11, q7
+	vand	q10, q10, q8
+	vand	q11, q11, q8
+	veor	q5, q5, q10
+	vshl.u64	q10, q10, #1
+	veor	q7, q7, q11
+	vshl.u64	q11, q11, #1
+	veor	q3, q3, q10
+	veor	q2, q2, q11
+	vshr.u64	q10, q6, #1
+	vshr.u64	q11, q0, #1
+	veor	q10, q10, q4
+	veor	q11, q11, q1
+	vand	q10, q10, q8
+	vand	q11, q11, q8
+	veor	q4, q4, q10
+	vshl.u64	q10, q10, #1
+	veor	q1, q1, q11
+	vshl.u64	q11, q11, #1
+	veor	q6, q6, q10
+	veor	q0, q0, q11
+	vmov.i8	q8,#0x0f			@ compose LBS2
+	vshr.u64	q10, q7, #2
+	vshr.u64	q11, q2, #2
+	veor	q10, q10, q5
+	veor	q11, q11, q3
+	vand	q10, q10, q9
+	vand	q11, q11, q9
+	veor	q5, q5, q10
+	vshl.u64	q10, q10, #2
+	veor	q3, q3, q11
+	vshl.u64	q11, q11, #2
+	veor	q7, q7, q10
+	veor	q2, q2, q11
+	vshr.u64	q10, q1, #2
+	vshr.u64	q11, q0, #2
+	veor	q10, q10, q4
+	veor	q11, q11, q6
+	vand	q10, q10, q9
+	vand	q11, q11, q9
+	veor	q4, q4, q10
+	vshl.u64	q10, q10, #2
+	veor	q6, q6, q11
+	vshl.u64	q11, q11, #2
+	veor	q1, q1, q10
+	veor	q0, q0, q11
+	vshr.u64	q10, q4, #4
+	vshr.u64	q11, q6, #4
+	veor	q10, q10, q5
+	veor	q11, q11, q3
+	vand	q10, q10, q8
+	vand	q11, q11, q8
+	veor	q5, q5, q10
+	vshl.u64	q10, q10, #4
+	veor	q3, q3, q11
+	vshl.u64	q11, q11, #4
+	veor	q4, q4, q10
+	veor	q6, q6, q11
+	vshr.u64	q10, q1, #4
+	vshr.u64	q11, q0, #4
+	veor	q10, q10, q7
+	veor	q11, q11, q2
+	vand	q10, q10, q8
+	vand	q11, q11, q8
+	veor	q7, q7, q10
+	vshl.u64	q10, q10, #4
+	veor	q2, q2, q11
+	vshl.u64	q11, q11, #4
+	veor	q1, q1, q10
+	veor	q0, q0, q11
+	vldmia	r4, {q8}			@ last round key
+	veor	q6, q6, q8
+	veor	q4, q4, q8
+	veor	q2, q2, q8
+	veor	q7, q7, q8
+	veor	q3, q3, q8
+	veor	q5, q5, q8
+	veor	q0, q0, q8
+	veor	q1, q1, q8
+	bx	lr
+
+
+
+.align	6
+_bsaes_const:
+LM0ISR:@ InvShiftRows constants
+.quad	0x0a0e0206070b0f03, 0x0004080c0d010509
+LISR:
+.quad	0x0504070602010003, 0x0f0e0d0c080b0a09
+LISRM0:
+.quad	0x01040b0e0205080f, 0x0306090c00070a0d
+LM0SR:@ ShiftRows constants
+.quad	0x0a0e02060f03070b, 0x0004080c05090d01
+LSR:
+.quad	0x0504070600030201, 0x0f0e0d0c0a09080b
+LSRM0:
+.quad	0x0304090e00050a0f, 0x01060b0c0207080d
+LM0:
+.quad	0x02060a0e03070b0f, 0x0004080c0105090d
+LREVM0SR:
+.quad	0x090d01050c000408, 0x03070b0f060a0e02
+.byte	66,105,116,45,115,108,105,99,101,100,32,65,69,83,32,102,111,114,32,78,69,79,78,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+.align	6
+
+
+
+.align	4
+_bsaes_encrypt8:
+	adr	r6,_bsaes_encrypt8
+	vldmia	r4!, {q9}		@ round 0 key
+#ifdef	__APPLE__
+	adr	r6,LM0SR
+#else
+	sub	r6,r6,#_bsaes_encrypt8-LM0SR
+#endif
+
+	vldmia	r6!, {q8}		@ LM0SR
+_bsaes_encrypt8_alt:
+	veor	q10, q0, q9	@ xor with round0 key
+	veor	q11, q1, q9
+	vtbl.8	d0, {q10}, d16
+	vtbl.8	d1, {q10}, d17
+	veor	q12, q2, q9
+	vtbl.8	d2, {q11}, d16
+	vtbl.8	d3, {q11}, d17
+	veor	q13, q3, q9
+	vtbl.8	d4, {q12}, d16
+	vtbl.8	d5, {q12}, d17
+	veor	q14, q4, q9
+	vtbl.8	d6, {q13}, d16
+	vtbl.8	d7, {q13}, d17
+	veor	q15, q5, q9
+	vtbl.8	d8, {q14}, d16
+	vtbl.8	d9, {q14}, d17
+	veor	q10, q6, q9
+	vtbl.8	d10, {q15}, d16
+	vtbl.8	d11, {q15}, d17
+	veor	q11, q7, q9
+	vtbl.8	d12, {q10}, d16
+	vtbl.8	d13, {q10}, d17
+	vtbl.8	d14, {q11}, d16
+	vtbl.8	d15, {q11}, d17
+_bsaes_encrypt8_bitslice:
+	vmov.i8	q8,#0x55			@ compose LBS0
+	vmov.i8	q9,#0x33			@ compose LBS1
+	vshr.u64	q10, q6, #1
+	vshr.u64	q11, q4, #1
+	veor	q10, q10, q7
+	veor	q11, q11, q5
+	vand	q10, q10, q8
+	vand	q11, q11, q8
+	veor	q7, q7, q10
+	vshl.u64	q10, q10, #1
+	veor	q5, q5, q11
+	vshl.u64	q11, q11, #1
+	veor	q6, q6, q10
+	veor	q4, q4, q11
+	vshr.u64	q10, q2, #1
+	vshr.u64	q11, q0, #1
+	veor	q10, q10, q3
+	veor	q11, q11, q1
+	vand	q10, q10, q8
+	vand	q11, q11, q8
+	veor	q3, q3, q10
+	vshl.u64	q10, q10, #1
+	veor	q1, q1, q11
+	vshl.u64	q11, q11, #1
+	veor	q2, q2, q10
+	veor	q0, q0, q11
+	vmov.i8	q8,#0x0f			@ compose LBS2
+	vshr.u64	q10, q5, #2
+	vshr.u64	q11, q4, #2
+	veor	q10, q10, q7
+	veor	q11, q11, q6
+	vand	q10, q10, q9
+	vand	q11, q11, q9
+	veor	q7, q7, q10
+	vshl.u64	q10, q10, #2
+	veor	q6, q6, q11
+	vshl.u64	q11, q11, #2
+	veor	q5, q5, q10
+	veor	q4, q4, q11
+	vshr.u64	q10, q1, #2
+	vshr.u64	q11, q0, #2
+	veor	q10, q10, q3
+	veor	q11, q11, q2
+	vand	q10, q10, q9
+	vand	q11, q11, q9
+	veor	q3, q3, q10
+	vshl.u64	q10, q10, #2
+	veor	q2, q2, q11
+	vshl.u64	q11, q11, #2
+	veor	q1, q1, q10
+	veor	q0, q0, q11
+	vshr.u64	q10, q3, #4
+	vshr.u64	q11, q2, #4
+	veor	q10, q10, q7
+	veor	q11, q11, q6
+	vand	q10, q10, q8
+	vand	q11, q11, q8
+	veor	q7, q7, q10
+	vshl.u64	q10, q10, #4
+	veor	q6, q6, q11
+	vshl.u64	q11, q11, #4
+	veor	q3, q3, q10
+	veor	q2, q2, q11
+	vshr.u64	q10, q1, #4
+	vshr.u64	q11, q0, #4
+	veor	q10, q10, q5
+	veor	q11, q11, q4
+	vand	q10, q10, q8
+	vand	q11, q11, q8
+	veor	q5, q5, q10
+	vshl.u64	q10, q10, #4
+	veor	q4, q4, q11
+	vshl.u64	q11, q11, #4
+	veor	q1, q1, q10
+	veor	q0, q0, q11
+	sub	r5,r5,#1
+	b	Lenc_sbox
+.align	4
+Lenc_loop:
+	vldmia	r4!, {q8,q9,q10,q11}
+	veor	q8, q8, q0
+	veor	q9, q9, q1
+	vtbl.8	d0, {q8}, d24
+	vtbl.8	d1, {q8}, d25
+	vldmia	r4!, {q8}
+	veor	q10, q10, q2
+	vtbl.8	d2, {q9}, d24
+	vtbl.8	d3, {q9}, d25
+	vldmia	r4!, {q9}
+	veor	q11, q11, q3
+	vtbl.8	d4, {q10}, d24
+	vtbl.8	d5, {q10}, d25
+	vldmia	r4!, {q10}
+	vtbl.8	d6, {q11}, d24
+	vtbl.8	d7, {q11}, d25
+	vldmia	r4!, {q11}
+	veor	q8, q8, q4
+	veor	q9, q9, q5
+	vtbl.8	d8, {q8}, d24
+	vtbl.8	d9, {q8}, d25
+	veor	q10, q10, q6
+	vtbl.8	d10, {q9}, d24
+	vtbl.8	d11, {q9}, d25
+	veor	q11, q11, q7
+	vtbl.8	d12, {q10}, d24
+	vtbl.8	d13, {q10}, d25
+	vtbl.8	d14, {q11}, d24
+	vtbl.8	d15, {q11}, d25
+Lenc_sbox:
+	veor	q2, q2, q1
+	veor	q5, q5, q6
+	veor	q3, q3, q0
+	veor	q6, q6, q2
+	veor	q5, q5, q0
+
+	veor	q6, q6, q3
+	veor	q3, q3, q7
+	veor	q7, q7, q5
+	veor	q3, q3, q4
+	veor	q4, q4, q5
+
+	veor	q2, q2, q7
+	veor	q3, q3, q1
+	veor	q1, q1, q5
+	veor	q11, q7, q4
+	veor	q10, q1, q2
+	veor	q9, q5, q3
+	veor	q13, q2, q4
+	vmov	q8, q10
+	veor	q12, q6, q0
+
+	vorr	q10, q10, q9
+	veor	q15, q11, q8
+	vand	q14, q11, q12
+	vorr	q11, q11, q12
+	veor	q12, q12, q9
+	vand	q8, q8, q9
+	veor	q9, q3, q0
+	vand	q15, q15, q12
+	vand	q13, q13, q9
+	veor	q9, q7, q1
+	veor	q12, q5, q6
+	veor	q11, q11, q13
+	veor	q10, q10, q13
+	vand	q13, q9, q12
+	vorr	q9, q9, q12
+	veor	q11, q11, q15
+	veor	q8, q8, q13
+	veor	q10, q10, q14
+	veor	q9, q9, q15
+	veor	q8, q8, q14
+	vand	q12, q2, q3
+	veor	q9, q9, q14
+	vand	q13, q4, q0
+	vand	q14, q1, q5
+	vorr	q15, q7, q6
+	veor	q11, q11, q12
+	veor	q9, q9, q14
+	veor	q8, q8, q15
+	veor	q10, q10, q13
+
+	@ Inv_GF16 	0, 	1, 	2, 	3, s0, s1, s2, s3
+
+	@ new smaller inversion
+
+	vand	q14, q11, q9
+	vmov	q12, q8
+
+	veor	q13, q10, q14
+	veor	q15, q8, q14
+	veor	q14, q8, q14	@ q14=q15
+
+	vbsl	q13, q9, q8
+	vbsl	q15, q11, q10
+	veor	q11, q11, q10
+
+	vbsl	q12, q13, q14
+	vbsl	q8, q14, q13
+
+	vand	q14, q12, q15
+	veor	q9, q9, q8
+
+	veor	q14, q14, q11
+	veor	q12, q6, q0
+	veor	q8, q5, q3
+	veor	q10, q15, q14
+	vand	q10, q10, q6
+	veor	q6, q6, q5
+	vand	q11, q5, q15
+	vand	q6, q6, q14
+	veor	q5, q11, q10
+	veor	q6, q6, q11
+	veor	q15, q15, q13
+	veor	q14, q14, q9
+	veor	q11, q15, q14
+	veor	q10, q13, q9
+	vand	q11, q11, q12
+	vand	q10, q10, q0
+	veor	q12, q12, q8
+	veor	q0, q0, q3
+	vand	q8, q8, q15
+	vand	q3, q3, q13
+	vand	q12, q12, q14
+	vand	q0, q0, q9
+	veor	q8, q8, q12
+	veor	q0, q0, q3
+	veor	q12, q12, q11
+	veor	q3, q3, q10
+	veor	q6, q6, q12
+	veor	q0, q0, q12
+	veor	q5, q5, q8
+	veor	q3, q3, q8
+
+	veor	q12, q7, q4
+	veor	q8, q1, q2
+	veor	q11, q15, q14
+	veor	q10, q13, q9
+	vand	q11, q11, q12
+	vand	q10, q10, q4
+	veor	q12, q12, q8
+	veor	q4, q4, q2
+	vand	q8, q8, q15
+	vand	q2, q2, q13
+	vand	q12, q12, q14
+	vand	q4, q4, q9
+	veor	q8, q8, q12
+	veor	q4, q4, q2
+	veor	q12, q12, q11
+	veor	q2, q2, q10
+	veor	q15, q15, q13
+	veor	q14, q14, q9
+	veor	q10, q15, q14
+	vand	q10, q10, q7
+	veor	q7, q7, q1
+	vand	q11, q1, q15
+	vand	q7, q7, q14
+	veor	q1, q11, q10
+	veor	q7, q7, q11
+	veor	q7, q7, q12
+	veor	q4, q4, q12
+	veor	q1, q1, q8
+	veor	q2, q2, q8
+	veor	q7, q7, q0
+	veor	q1, q1, q6
+	veor	q6, q6, q0
+	veor	q4, q4, q7
+	veor	q0, q0, q1
+
+	veor	q1, q1, q5
+	veor	q5, q5, q2
+	veor	q2, q2, q3
+	veor	q3, q3, q5
+	veor	q4, q4, q5
+
+	veor	q6, q6, q3
+	subs	r5,r5,#1
+	bcc	Lenc_done
+	vext.8	q8, q0, q0, #12	@ x0 <<< 32
+	vext.8	q9, q1, q1, #12
+	veor	q0, q0, q8		@ x0 ^ (x0 <<< 32)
+	vext.8	q10, q4, q4, #12
+	veor	q1, q1, q9
+	vext.8	q11, q6, q6, #12
+	veor	q4, q4, q10
+	vext.8	q12, q3, q3, #12
+	veor	q6, q6, q11
+	vext.8	q13, q7, q7, #12
+	veor	q3, q3, q12
+	vext.8	q14, q2, q2, #12
+	veor	q7, q7, q13
+	vext.8	q15, q5, q5, #12
+	veor	q2, q2, q14
+
+	veor	q9, q9, q0
+	veor	q5, q5, q15
+	vext.8	q0, q0, q0, #8		@ (x0 ^ (x0 <<< 32)) <<< 64)
+	veor	q10, q10, q1
+	veor	q8, q8, q5
+	veor	q9, q9, q5
+	vext.8	q1, q1, q1, #8
+	veor	q13, q13, q3
+	veor	q0, q0, q8
+	veor	q14, q14, q7
+	veor	q1, q1, q9
+	vext.8	q8, q3, q3, #8
+	veor	q12, q12, q6
+	vext.8	q9, q7, q7, #8
+	veor	q15, q15, q2
+	vext.8	q3, q6, q6, #8
+	veor	q11, q11, q4
+	vext.8	q7, q5, q5, #8
+	veor	q12, q12, q5
+	vext.8	q6, q2, q2, #8
+	veor	q11, q11, q5
+	vext.8	q2, q4, q4, #8
+	veor	q5, q9, q13
+	veor	q4, q8, q12
+	veor	q3, q3, q11
+	veor	q7, q7, q15
+	veor	q6, q6, q14
+	 @ vmov	q4, q8
+	veor	q2, q2, q10
+	 @ vmov	q5, q9
+	vldmia	r6, {q12}		@ LSR
+	ite	eq				@ Thumb2 thing, samity check in ARM
+	addeq	r6,r6,#0x10
+	bne	Lenc_loop
+	vldmia	r6, {q12}		@ LSRM0
+	b	Lenc_loop
+.align	4
+Lenc_done:
+	vmov.i8	q8,#0x55			@ compose LBS0
+	vmov.i8	q9,#0x33			@ compose LBS1
+	vshr.u64	q10, q2, #1
+	vshr.u64	q11, q3, #1
+	veor	q10, q10, q5
+	veor	q11, q11, q7
+	vand	q10, q10, q8
+	vand	q11, q11, q8
+	veor	q5, q5, q10
+	vshl.u64	q10, q10, #1
+	veor	q7, q7, q11
+	vshl.u64	q11, q11, #1
+	veor	q2, q2, q10
+	veor	q3, q3, q11
+	vshr.u64	q10, q4, #1
+	vshr.u64	q11, q0, #1
+	veor	q10, q10, q6
+	veor	q11, q11, q1
+	vand	q10, q10, q8
+	vand	q11, q11, q8
+	veor	q6, q6, q10
+	vshl.u64	q10, q10, #1
+	veor	q1, q1, q11
+	vshl.u64	q11, q11, #1
+	veor	q4, q4, q10
+	veor	q0, q0, q11
+	vmov.i8	q8,#0x0f			@ compose LBS2
+	vshr.u64	q10, q7, #2
+	vshr.u64	q11, q3, #2
+	veor	q10, q10, q5
+	veor	q11, q11, q2
+	vand	q10, q10, q9
+	vand	q11, q11, q9
+	veor	q5, q5, q10
+	vshl.u64	q10, q10, #2
+	veor	q2, q2, q11
+	vshl.u64	q11, q11, #2
+	veor	q7, q7, q10
+	veor	q3, q3, q11
+	vshr.u64	q10, q1, #2
+	vshr.u64	q11, q0, #2
+	veor	q10, q10, q6
+	veor	q11, q11, q4
+	vand	q10, q10, q9
+	vand	q11, q11, q9
+	veor	q6, q6, q10
+	vshl.u64	q10, q10, #2
+	veor	q4, q4, q11
+	vshl.u64	q11, q11, #2
+	veor	q1, q1, q10
+	veor	q0, q0, q11
+	vshr.u64	q10, q6, #4
+	vshr.u64	q11, q4, #4
+	veor	q10, q10, q5
+	veor	q11, q11, q2
+	vand	q10, q10, q8
+	vand	q11, q11, q8
+	veor	q5, q5, q10
+	vshl.u64	q10, q10, #4
+	veor	q2, q2, q11
+	vshl.u64	q11, q11, #4
+	veor	q6, q6, q10
+	veor	q4, q4, q11
+	vshr.u64	q10, q1, #4
+	vshr.u64	q11, q0, #4
+	veor	q10, q10, q7
+	veor	q11, q11, q3
+	vand	q10, q10, q8
+	vand	q11, q11, q8
+	veor	q7, q7, q10
+	vshl.u64	q10, q10, #4
+	veor	q3, q3, q11
+	vshl.u64	q11, q11, #4
+	veor	q1, q1, q10
+	veor	q0, q0, q11
+	vldmia	r4, {q8}			@ last round key
+	veor	q4, q4, q8
+	veor	q6, q6, q8
+	veor	q3, q3, q8
+	veor	q7, q7, q8
+	veor	q2, q2, q8
+	veor	q5, q5, q8
+	veor	q0, q0, q8
+	veor	q1, q1, q8
+	bx	lr
+
+
+.align	4
+_bsaes_key_convert:
+	adr	r6,_bsaes_key_convert
+	vld1.8	{q7},  [r4]!		@ load round 0 key
+#ifdef	__APPLE__
+	adr	r6,LM0
+#else
+	sub	r6,r6,#_bsaes_key_convert-LM0
+#endif
+	vld1.8	{q15}, [r4]!		@ load round 1 key
+
+	vmov.i8	q8,  #0x01			@ bit masks
+	vmov.i8	q9,  #0x02
+	vmov.i8	q10, #0x04
+	vmov.i8	q11, #0x08
+	vmov.i8	q12, #0x10
+	vmov.i8	q13, #0x20
+	vldmia	r6, {q14}		@ LM0
+
+#ifdef __ARMEL__
+	vrev32.8	q7,  q7
+	vrev32.8	q15, q15
+#endif
+	sub	r5,r5,#1
+	vstmia	r12!, {q7}		@ save round 0 key
+	b	Lkey_loop
+
+.align	4
+Lkey_loop:
+	vtbl.8	d14,{q15},d28
+	vtbl.8	d15,{q15},d29
+	vmov.i8	q6,  #0x40
+	vmov.i8	q15, #0x80
+
+	vtst.8	q0, q7, q8
+	vtst.8	q1, q7, q9
+	vtst.8	q2, q7, q10
+	vtst.8	q3, q7, q11
+	vtst.8	q4, q7, q12
+	vtst.8	q5, q7, q13
+	vtst.8	q6, q7, q6
+	vtst.8	q7, q7, q15
+	vld1.8	{q15}, [r4]!		@ load next round key
+	vmvn	q0, q0		@ "pnot"
+	vmvn	q1, q1
+	vmvn	q5, q5
+	vmvn	q6, q6
+#ifdef __ARMEL__
+	vrev32.8	q15, q15
+#endif
+	subs	r5,r5,#1
+	vstmia	r12!,{q0,q1,q2,q3,q4,q5,q6,q7}		@ write bit-sliced round key
+	bne	Lkey_loop
+
+	vmov.i8	q7,#0x63			@ compose L63
+	@ don't save last round key
+	bx	lr
+
+
+
+
+.globl	_bsaes_cbc_encrypt
+.private_extern	_bsaes_cbc_encrypt
+
+.align	5
+_bsaes_cbc_encrypt:
+#ifndef	__KERNEL__
+	cmp	r2, #128
+#ifndef	__thumb__
+	blo	_AES_cbc_encrypt
+#else
+	bhs	1f
+	b	_AES_cbc_encrypt
+1:
+#endif
+#endif
+
+	@ it is up to the caller to make sure we are called with enc == 0
+
+	mov	ip, sp
+	stmdb	sp!, {r4,r5,r6,r7,r8,r9,r10, lr}
+	VFP_ABI_PUSH
+	ldr	r8, [ip]			@ IV is 1st arg on the stack
+	mov	r2, r2, lsr#4		@ len in 16 byte blocks
+	sub	sp, #0x10			@ scratch space to carry over the IV
+	mov	r9, sp				@ save sp
+
+	ldr	r10, [r3, #240]		@ get # of rounds
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	@ allocate the key schedule on the stack
+	sub	r12, sp, r10, lsl#7		@ 128 bytes per inner round key
+	add	r12, #96			@ sifze of bit-slices key schedule
+
+	@ populate the key schedule
+	mov	r4, r3			@ pass key
+	mov	r5, r10			@ pass # of rounds
+	mov	sp, r12				@ sp is sp
+	bl	_bsaes_key_convert
+	vldmia	sp, {q6}
+	vstmia	r12,  {q15}		@ save last round key
+	veor	q7, q7, q6	@ fix up round 0 key
+	vstmia	sp, {q7}
+#else
+	ldr	r12, [r3, #244]
+	eors	r12, #1
+	beq	0f
+
+	@ populate the key schedule
+	str	r12, [r3, #244]
+	mov	r4, r3			@ pass key
+	mov	r5, r10			@ pass # of rounds
+	add	r12, r3, #248			@ pass key schedule
+	bl	_bsaes_key_convert
+	add	r4, r3, #248
+	vldmia	r4, {q6}
+	vstmia	r12, {q15}			@ save last round key
+	veor	q7, q7, q6	@ fix up round 0 key
+	vstmia	r4, {q7}
+
+.align	2
+
+#endif
+
+	vld1.8	{q15}, [r8]		@ load IV
+	b	Lcbc_dec_loop
+
+.align	4
+Lcbc_dec_loop:
+	subs	r2, r2, #0x8
+	bmi	Lcbc_dec_loop_finish
+
+	vld1.8	{q0,q1}, [r0]!	@ load input
+	vld1.8	{q2,q3}, [r0]!
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	mov	r4, sp			@ pass the key
+#else
+	add	r4, r3, #248
+#endif
+	vld1.8	{q4,q5}, [r0]!
+	mov	r5, r10
+	vld1.8	{q6,q7}, [r0]
+	sub	r0, r0, #0x60
+	vstmia	r9, {q15}			@ put aside IV
+
+	bl	_bsaes_decrypt8
+
+	vldmia	r9, {q14}			@ reload IV
+	vld1.8	{q8,q9}, [r0]!	@ reload input
+	veor	q0, q0, q14	@ ^= IV
+	vld1.8	{q10,q11}, [r0]!
+	veor	q1, q1, q8
+	veor	q6, q6, q9
+	vld1.8	{q12,q13}, [r0]!
+	veor	q4, q4, q10
+	veor	q2, q2, q11
+	vld1.8	{q14,q15}, [r0]!
+	veor	q7, q7, q12
+	vst1.8	{q0,q1}, [r1]!	@ write output
+	veor	q3, q3, q13
+	vst1.8	{q6}, [r1]!
+	veor	q5, q5, q14
+	vst1.8	{q4}, [r1]!
+	vst1.8	{q2}, [r1]!
+	vst1.8	{q7}, [r1]!
+	vst1.8	{q3}, [r1]!
+	vst1.8	{q5}, [r1]!
+
+	b	Lcbc_dec_loop
+
+Lcbc_dec_loop_finish:
+	adds	r2, r2, #8
+	beq	Lcbc_dec_done
+
+	vld1.8	{q0}, [r0]!		@ load input
+	cmp	r2, #2
+	blo	Lcbc_dec_one
+	vld1.8	{q1}, [r0]!
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	mov	r4, sp			@ pass the key
+#else
+	add	r4, r3, #248
+#endif
+	mov	r5, r10
+	vstmia	r9, {q15}			@ put aside IV
+	beq	Lcbc_dec_two
+	vld1.8	{q2}, [r0]!
+	cmp	r2, #4
+	blo	Lcbc_dec_three
+	vld1.8	{q3}, [r0]!
+	beq	Lcbc_dec_four
+	vld1.8	{q4}, [r0]!
+	cmp	r2, #6
+	blo	Lcbc_dec_five
+	vld1.8	{q5}, [r0]!
+	beq	Lcbc_dec_six
+	vld1.8	{q6}, [r0]!
+	sub	r0, r0, #0x70
+
+	bl	_bsaes_decrypt8
+
+	vldmia	r9, {q14}			@ reload IV
+	vld1.8	{q8,q9}, [r0]!	@ reload input
+	veor	q0, q0, q14	@ ^= IV
+	vld1.8	{q10,q11}, [r0]!
+	veor	q1, q1, q8
+	veor	q6, q6, q9
+	vld1.8	{q12,q13}, [r0]!
+	veor	q4, q4, q10
+	veor	q2, q2, q11
+	vld1.8	{q15}, [r0]!
+	veor	q7, q7, q12
+	vst1.8	{q0,q1}, [r1]!	@ write output
+	veor	q3, q3, q13
+	vst1.8	{q6}, [r1]!
+	vst1.8	{q4}, [r1]!
+	vst1.8	{q2}, [r1]!
+	vst1.8	{q7}, [r1]!
+	vst1.8	{q3}, [r1]!
+	b	Lcbc_dec_done
+.align	4
+Lcbc_dec_six:
+	sub	r0, r0, #0x60
+	bl	_bsaes_decrypt8
+	vldmia	r9,{q14}			@ reload IV
+	vld1.8	{q8,q9}, [r0]!	@ reload input
+	veor	q0, q0, q14	@ ^= IV
+	vld1.8	{q10,q11}, [r0]!
+	veor	q1, q1, q8
+	veor	q6, q6, q9
+	vld1.8	{q12}, [r0]!
+	veor	q4, q4, q10
+	veor	q2, q2, q11
+	vld1.8	{q15}, [r0]!
+	veor	q7, q7, q12
+	vst1.8	{q0,q1}, [r1]!	@ write output
+	vst1.8	{q6}, [r1]!
+	vst1.8	{q4}, [r1]!
+	vst1.8	{q2}, [r1]!
+	vst1.8	{q7}, [r1]!
+	b	Lcbc_dec_done
+.align	4
+Lcbc_dec_five:
+	sub	r0, r0, #0x50
+	bl	_bsaes_decrypt8
+	vldmia	r9, {q14}			@ reload IV
+	vld1.8	{q8,q9}, [r0]!	@ reload input
+	veor	q0, q0, q14	@ ^= IV
+	vld1.8	{q10,q11}, [r0]!
+	veor	q1, q1, q8
+	veor	q6, q6, q9
+	vld1.8	{q15}, [r0]!
+	veor	q4, q4, q10
+	vst1.8	{q0,q1}, [r1]!	@ write output
+	veor	q2, q2, q11
+	vst1.8	{q6}, [r1]!
+	vst1.8	{q4}, [r1]!
+	vst1.8	{q2}, [r1]!
+	b	Lcbc_dec_done
+.align	4
+Lcbc_dec_four:
+	sub	r0, r0, #0x40
+	bl	_bsaes_decrypt8
+	vldmia	r9, {q14}			@ reload IV
+	vld1.8	{q8,q9}, [r0]!	@ reload input
+	veor	q0, q0, q14	@ ^= IV
+	vld1.8	{q10}, [r0]!
+	veor	q1, q1, q8
+	veor	q6, q6, q9
+	vld1.8	{q15}, [r0]!
+	veor	q4, q4, q10
+	vst1.8	{q0,q1}, [r1]!	@ write output
+	vst1.8	{q6}, [r1]!
+	vst1.8	{q4}, [r1]!
+	b	Lcbc_dec_done
+.align	4
+Lcbc_dec_three:
+	sub	r0, r0, #0x30
+	bl	_bsaes_decrypt8
+	vldmia	r9, {q14}			@ reload IV
+	vld1.8	{q8,q9}, [r0]!	@ reload input
+	veor	q0, q0, q14	@ ^= IV
+	vld1.8	{q15}, [r0]!
+	veor	q1, q1, q8
+	veor	q6, q6, q9
+	vst1.8	{q0,q1}, [r1]!	@ write output
+	vst1.8	{q6}, [r1]!
+	b	Lcbc_dec_done
+.align	4
+Lcbc_dec_two:
+	sub	r0, r0, #0x20
+	bl	_bsaes_decrypt8
+	vldmia	r9, {q14}			@ reload IV
+	vld1.8	{q8}, [r0]!		@ reload input
+	veor	q0, q0, q14	@ ^= IV
+	vld1.8	{q15}, [r0]!		@ reload input
+	veor	q1, q1, q8
+	vst1.8	{q0,q1}, [r1]!	@ write output
+	b	Lcbc_dec_done
+.align	4
+Lcbc_dec_one:
+	sub	r0, r0, #0x10
+	mov	r10, r1			@ save original out pointer
+	mov	r1, r9			@ use the iv scratch space as out buffer
+	mov	r2, r3
+	vmov	q4,q15		@ just in case ensure that IV
+	vmov	q5,q0			@ and input are preserved
+	bl	_AES_decrypt
+	vld1.8	{q0}, [r9]		@ load result
+	veor	q0, q0, q4	@ ^= IV
+	vmov	q15, q5		@ q5 holds input
+	vst1.8	{q0}, [r10]		@ write output
+
+Lcbc_dec_done:
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	vmov.i32	q0, #0
+	vmov.i32	q1, #0
+Lcbc_dec_bzero:@ wipe key schedule [if any]
+	vstmia	sp!, {q0,q1}
+	cmp	sp, r9
+	bne	Lcbc_dec_bzero
+#endif
+
+	mov	sp, r9
+	add	sp, #0x10			@ add sp,r9,#0x10 is no good for thumb
+	vst1.8	{q15}, [r8]		@ return IV
+	VFP_ABI_POP
+	ldmia	sp!, {r4,r5,r6,r7,r8,r9,r10, pc}
+
+
+.globl	_bsaes_ctr32_encrypt_blocks
+.private_extern	_bsaes_ctr32_encrypt_blocks
+
+.align	5
+_bsaes_ctr32_encrypt_blocks:
+	cmp	r2, #8			@ use plain AES for
+	blo	Lctr_enc_short			@ small sizes
+
+	mov	ip, sp
+	stmdb	sp!, {r4,r5,r6,r7,r8,r9,r10, lr}
+	VFP_ABI_PUSH
+	ldr	r8, [ip]			@ ctr is 1st arg on the stack
+	sub	sp, sp, #0x10			@ scratch space to carry over the ctr
+	mov	r9, sp				@ save sp
+
+	ldr	r10, [r3, #240]		@ get # of rounds
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	@ allocate the key schedule on the stack
+	sub	r12, sp, r10, lsl#7		@ 128 bytes per inner round key
+	add	r12, #96			@ size of bit-sliced key schedule
+
+	@ populate the key schedule
+	mov	r4, r3			@ pass key
+	mov	r5, r10			@ pass # of rounds
+	mov	sp, r12				@ sp is sp
+	bl	_bsaes_key_convert
+	veor	q7,q7,q15	@ fix up last round key
+	vstmia	r12, {q7}			@ save last round key
+
+	vld1.8	{q0}, [r8]		@ load counter
+#ifdef	__APPLE__
+	mov	r8, #:lower16:(LREVM0SR-LM0)
+	add	r8, r6, r8
+#else
+	add	r8, r6, #LREVM0SR-LM0	@ borrow r8
+#endif
+	vldmia	sp, {q4}		@ load round0 key
+#else
+	ldr	r12, [r3, #244]
+	eors	r12, #1
+	beq	0f
+
+	@ populate the key schedule
+	str	r12, [r3, #244]
+	mov	r4, r3			@ pass key
+	mov	r5, r10			@ pass # of rounds
+	add	r12, r3, #248			@ pass key schedule
+	bl	_bsaes_key_convert
+	veor	q7,q7,q15	@ fix up last round key
+	vstmia	r12, {q7}			@ save last round key
+
+.align	2
+	add	r12, r3, #248
+	vld1.8	{q0}, [r8]		@ load counter
+	adrl	r8, LREVM0SR			@ borrow r8
+	vldmia	r12, {q4}			@ load round0 key
+	sub	sp, #0x10			@ place for adjusted round0 key
+#endif
+
+	vmov.i32	q8,#1		@ compose 1<<96
+	veor	q9,q9,q9
+	vrev32.8	q0,q0
+	vext.8	q8,q9,q8,#4
+	vrev32.8	q4,q4
+	vadd.u32	q9,q8,q8	@ compose 2<<96
+	vstmia	sp, {q4}		@ save adjusted round0 key
+	b	Lctr_enc_loop
+
+.align	4
+Lctr_enc_loop:
+	vadd.u32	q10, q8, q9	@ compose 3<<96
+	vadd.u32	q1, q0, q8	@ +1
+	vadd.u32	q2, q0, q9	@ +2
+	vadd.u32	q3, q0, q10	@ +3
+	vadd.u32	q4, q1, q10
+	vadd.u32	q5, q2, q10
+	vadd.u32	q6, q3, q10
+	vadd.u32	q7, q4, q10
+	vadd.u32	q10, q5, q10	@ next counter
+
+	@ Borrow prologue from _bsaes_encrypt8 to use the opportunity
+	@ to flip byte order in 32-bit counter
+
+	vldmia	sp, {q9}		@ load round0 key
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	add	r4, sp, #0x10		@ pass next round key
+#else
+	add	r4, r3, #264
+#endif
+	vldmia	r8, {q8}			@ LREVM0SR
+	mov	r5, r10			@ pass rounds
+	vstmia	r9, {q10}			@ save next counter
+#ifdef	__APPLE__
+	mov	r6, #:lower16:(LREVM0SR-LSR)
+	sub	r6, r8, r6
+#else
+	sub	r6, r8, #LREVM0SR-LSR	@ pass constants
+#endif
+
+	bl	_bsaes_encrypt8_alt
+
+	subs	r2, r2, #8
+	blo	Lctr_enc_loop_done
+
+	vld1.8	{q8,q9}, [r0]!	@ load input
+	vld1.8	{q10,q11}, [r0]!
+	veor	q0, q8
+	veor	q1, q9
+	vld1.8	{q12,q13}, [r0]!
+	veor	q4, q10
+	veor	q6, q11
+	vld1.8	{q14,q15}, [r0]!
+	veor	q3, q12
+	vst1.8	{q0,q1}, [r1]!	@ write output
+	veor	q7, q13
+	veor	q2, q14
+	vst1.8	{q4}, [r1]!
+	veor	q5, q15
+	vst1.8	{q6}, [r1]!
+	vmov.i32	q8, #1			@ compose 1<<96
+	vst1.8	{q3}, [r1]!
+	veor	q9, q9, q9
+	vst1.8	{q7}, [r1]!
+	vext.8	q8, q9, q8, #4
+	vst1.8	{q2}, [r1]!
+	vadd.u32	q9,q8,q8		@ compose 2<<96
+	vst1.8	{q5}, [r1]!
+	vldmia	r9, {q0}			@ load counter
+
+	bne	Lctr_enc_loop
+	b	Lctr_enc_done
+
+.align	4
+Lctr_enc_loop_done:
+	add	r2, r2, #8
+	vld1.8	{q8}, [r0]!	@ load input
+	veor	q0, q8
+	vst1.8	{q0}, [r1]!	@ write output
+	cmp	r2, #2
+	blo	Lctr_enc_done
+	vld1.8	{q9}, [r0]!
+	veor	q1, q9
+	vst1.8	{q1}, [r1]!
+	beq	Lctr_enc_done
+	vld1.8	{q10}, [r0]!
+	veor	q4, q10
+	vst1.8	{q4}, [r1]!
+	cmp	r2, #4
+	blo	Lctr_enc_done
+	vld1.8	{q11}, [r0]!
+	veor	q6, q11
+	vst1.8	{q6}, [r1]!
+	beq	Lctr_enc_done
+	vld1.8	{q12}, [r0]!
+	veor	q3, q12
+	vst1.8	{q3}, [r1]!
+	cmp	r2, #6
+	blo	Lctr_enc_done
+	vld1.8	{q13}, [r0]!
+	veor	q7, q13
+	vst1.8	{q7}, [r1]!
+	beq	Lctr_enc_done
+	vld1.8	{q14}, [r0]
+	veor	q2, q14
+	vst1.8	{q2}, [r1]!
+
+Lctr_enc_done:
+	vmov.i32	q0, #0
+	vmov.i32	q1, #0
+#ifndef	BSAES_ASM_EXTENDED_KEY
+Lctr_enc_bzero:@ wipe key schedule [if any]
+	vstmia	sp!, {q0,q1}
+	cmp	sp, r9
+	bne	Lctr_enc_bzero
+#else
+	vstmia	sp, {q0,q1}
+#endif
+
+	mov	sp, r9
+	add	sp, #0x10		@ add sp,r9,#0x10 is no good for thumb
+	VFP_ABI_POP
+	ldmia	sp!, {r4,r5,r6,r7,r8,r9,r10, pc}	@ return
+
+.align	4
+Lctr_enc_short:
+	ldr	ip, [sp]		@ ctr pointer is passed on stack
+	stmdb	sp!, {r4,r5,r6,r7,r8, lr}
+
+	mov	r4, r0		@ copy arguments
+	mov	r5, r1
+	mov	r6, r2
+	mov	r7, r3
+	ldr	r8, [ip, #12]		@ load counter LSW
+	vld1.8	{q1}, [ip]		@ load whole counter value
+#ifdef __ARMEL__
+	rev	r8, r8
+#endif
+	sub	sp, sp, #0x10
+	vst1.8	{q1}, [sp]		@ copy counter value
+	sub	sp, sp, #0x10
+
+Lctr_enc_short_loop:
+	add	r0, sp, #0x10		@ input counter value
+	mov	r1, sp			@ output on the stack
+	mov	r2, r7			@ key
+
+	bl	_AES_encrypt
+
+	vld1.8	{q0}, [r4]!	@ load input
+	vld1.8	{q1}, [sp]		@ load encrypted counter
+	add	r8, r8, #1
+#ifdef __ARMEL__
+	rev	r0, r8
+	str	r0, [sp, #0x1c]		@ next counter value
+#else
+	str	r8, [sp, #0x1c]		@ next counter value
+#endif
+	veor	q0,q0,q1
+	vst1.8	{q0}, [r5]!	@ store output
+	subs	r6, r6, #1
+	bne	Lctr_enc_short_loop
+
+	vmov.i32	q0, #0
+	vmov.i32	q1, #0
+	vstmia	sp!, {q0,q1}
+
+	ldmia	sp!, {r4,r5,r6,r7,r8, pc}
+
+.globl	_bsaes_xts_encrypt
+.private_extern	_bsaes_xts_encrypt
+
+.align	4
+_bsaes_xts_encrypt:
+	mov	ip, sp
+	stmdb	sp!, {r4,r5,r6,r7,r8,r9,r10, lr}		@ 0x20
+	VFP_ABI_PUSH
+	mov	r6, sp				@ future r3
+
+	mov	r7, r0
+	mov	r8, r1
+	mov	r9, r2
+	mov	r10, r3
+
+	sub	r0, sp, #0x10			@ 0x10
+	bic	r0, #0xf			@ align at 16 bytes
+	mov	sp, r0
+
+#ifdef	XTS_CHAIN_TWEAK
+	ldr	r0, [ip]			@ pointer to input tweak
+#else
+	@ generate initial tweak
+	ldr	r0, [ip, #4]			@ iv[]
+	mov	r1, sp
+	ldr	r2, [ip, #0]			@ key2
+	bl	_AES_encrypt
+	mov	r0,sp				@ pointer to initial tweak
+#endif
+
+	ldr	r1, [r10, #240]		@ get # of rounds
+	mov	r3, r6
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	@ allocate the key schedule on the stack
+	sub	r12, sp, r1, lsl#7		@ 128 bytes per inner round key
+	@ add	r12, #96			@ size of bit-sliced key schedule
+	sub	r12, #48			@ place for tweak[9]
+
+	@ populate the key schedule
+	mov	r4, r10			@ pass key
+	mov	r5, r1			@ pass # of rounds
+	mov	sp, r12
+	add	r12, #0x90			@ pass key schedule
+	bl	_bsaes_key_convert
+	veor	q7, q7, q15	@ fix up last round key
+	vstmia	r12, {q7}			@ save last round key
+#else
+	ldr	r12, [r10, #244]
+	eors	r12, #1
+	beq	0f
+
+	str	r12, [r10, #244]
+	mov	r4, r10			@ pass key
+	mov	r5, r1			@ pass # of rounds
+	add	r12, r10, #248			@ pass key schedule
+	bl	_bsaes_key_convert
+	veor	q7, q7, q15	@ fix up last round key
+	vstmia	r12, {q7}
+
+.align	2
+	sub	sp, #0x90			@ place for tweak[9]
+#endif
+
+	vld1.8	{q8}, [r0]			@ initial tweak
+	adr	r2, Lxts_magic
+
+	subs	r9, #0x80
+	blo	Lxts_enc_short
+	b	Lxts_enc_loop
+
+.align	4
+Lxts_enc_loop:
+	vldmia	r2, {q5}	@ load XTS magic
+	vshr.s64	q6, q8, #63
+	mov	r0, sp
+	vand	q6, q6, q5
+	vadd.u64	q9, q8, q8
+	vst1.64	{q8}, [r0,:128]!
+	vswp	d13,d12
+	vshr.s64	q7, q9, #63
+	veor	q9, q9, q6
+	vand	q7, q7, q5
+	vadd.u64	q10, q9, q9
+	vst1.64	{q9}, [r0,:128]!
+	vswp	d15,d14
+	vshr.s64	q6, q10, #63
+	veor	q10, q10, q7
+	vand	q6, q6, q5
+	vld1.8	{q0}, [r7]!
+	vadd.u64	q11, q10, q10
+	vst1.64	{q10}, [r0,:128]!
+	vswp	d13,d12
+	vshr.s64	q7, q11, #63
+	veor	q11, q11, q6
+	vand	q7, q7, q5
+	vld1.8	{q1}, [r7]!
+	veor	q0, q0, q8
+	vadd.u64	q12, q11, q11
+	vst1.64	{q11}, [r0,:128]!
+	vswp	d15,d14
+	vshr.s64	q6, q12, #63
+	veor	q12, q12, q7
+	vand	q6, q6, q5
+	vld1.8	{q2}, [r7]!
+	veor	q1, q1, q9
+	vadd.u64	q13, q12, q12
+	vst1.64	{q12}, [r0,:128]!
+	vswp	d13,d12
+	vshr.s64	q7, q13, #63
+	veor	q13, q13, q6
+	vand	q7, q7, q5
+	vld1.8	{q3}, [r7]!
+	veor	q2, q2, q10
+	vadd.u64	q14, q13, q13
+	vst1.64	{q13}, [r0,:128]!
+	vswp	d15,d14
+	vshr.s64	q6, q14, #63
+	veor	q14, q14, q7
+	vand	q6, q6, q5
+	vld1.8	{q4}, [r7]!
+	veor	q3, q3, q11
+	vadd.u64	q15, q14, q14
+	vst1.64	{q14}, [r0,:128]!
+	vswp	d13,d12
+	vshr.s64	q7, q15, #63
+	veor	q15, q15, q6
+	vand	q7, q7, q5
+	vld1.8	{q5}, [r7]!
+	veor	q4, q4, q12
+	vadd.u64	q8, q15, q15
+	vst1.64	{q15}, [r0,:128]!
+	vswp	d15,d14
+	veor	q8, q8, q7
+	vst1.64	{q8}, [r0,:128]		@ next round tweak
+
+	vld1.8	{q6,q7}, [r7]!
+	veor	q5, q5, q13
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	add	r4, sp, #0x90			@ pass key schedule
+#else
+	add	r4, r10, #248			@ pass key schedule
+#endif
+	veor	q6, q6, q14
+	mov	r5, r1			@ pass rounds
+	veor	q7, q7, q15
+	mov	r0, sp
+
+	bl	_bsaes_encrypt8
+
+	vld1.64	{q8,q9}, [r0,:128]!
+	vld1.64	{q10,q11}, [r0,:128]!
+	veor	q0, q0, q8
+	vld1.64	{q12,q13}, [r0,:128]!
+	veor	q1, q1, q9
+	veor	q8, q4, q10
+	vst1.8	{q0,q1}, [r8]!
+	veor	q9, q6, q11
+	vld1.64	{q14,q15}, [r0,:128]!
+	veor	q10, q3, q12
+	vst1.8	{q8,q9}, [r8]!
+	veor	q11, q7, q13
+	veor	q12, q2, q14
+	vst1.8	{q10,q11}, [r8]!
+	veor	q13, q5, q15
+	vst1.8	{q12,q13}, [r8]!
+
+	vld1.64	{q8}, [r0,:128]		@ next round tweak
+
+	subs	r9, #0x80
+	bpl	Lxts_enc_loop
+
+Lxts_enc_short:
+	adds	r9, #0x70
+	bmi	Lxts_enc_done
+
+	vldmia	r2, {q5}	@ load XTS magic
+	vshr.s64	q7, q8, #63
+	mov	r0, sp
+	vand	q7, q7, q5
+	vadd.u64	q9, q8, q8
+	vst1.64	{q8}, [r0,:128]!
+	vswp	d15,d14
+	vshr.s64	q6, q9, #63
+	veor	q9, q9, q7
+	vand	q6, q6, q5
+	vadd.u64	q10, q9, q9
+	vst1.64	{q9}, [r0,:128]!
+	vswp	d13,d12
+	vshr.s64	q7, q10, #63
+	veor	q10, q10, q6
+	vand	q7, q7, q5
+	vld1.8	{q0}, [r7]!
+	subs	r9, #0x10
+	bmi	Lxts_enc_1
+	vadd.u64	q11, q10, q10
+	vst1.64	{q10}, [r0,:128]!
+	vswp	d15,d14
+	vshr.s64	q6, q11, #63
+	veor	q11, q11, q7
+	vand	q6, q6, q5
+	vld1.8	{q1}, [r7]!
+	subs	r9, #0x10
+	bmi	Lxts_enc_2
+	veor	q0, q0, q8
+	vadd.u64	q12, q11, q11
+	vst1.64	{q11}, [r0,:128]!
+	vswp	d13,d12
+	vshr.s64	q7, q12, #63
+	veor	q12, q12, q6
+	vand	q7, q7, q5
+	vld1.8	{q2}, [r7]!
+	subs	r9, #0x10
+	bmi	Lxts_enc_3
+	veor	q1, q1, q9
+	vadd.u64	q13, q12, q12
+	vst1.64	{q12}, [r0,:128]!
+	vswp	d15,d14
+	vshr.s64	q6, q13, #63
+	veor	q13, q13, q7
+	vand	q6, q6, q5
+	vld1.8	{q3}, [r7]!
+	subs	r9, #0x10
+	bmi	Lxts_enc_4
+	veor	q2, q2, q10
+	vadd.u64	q14, q13, q13
+	vst1.64	{q13}, [r0,:128]!
+	vswp	d13,d12
+	vshr.s64	q7, q14, #63
+	veor	q14, q14, q6
+	vand	q7, q7, q5
+	vld1.8	{q4}, [r7]!
+	subs	r9, #0x10
+	bmi	Lxts_enc_5
+	veor	q3, q3, q11
+	vadd.u64	q15, q14, q14
+	vst1.64	{q14}, [r0,:128]!
+	vswp	d15,d14
+	vshr.s64	q6, q15, #63
+	veor	q15, q15, q7
+	vand	q6, q6, q5
+	vld1.8	{q5}, [r7]!
+	subs	r9, #0x10
+	bmi	Lxts_enc_6
+	veor	q4, q4, q12
+	sub	r9, #0x10
+	vst1.64	{q15}, [r0,:128]		@ next round tweak
+
+	vld1.8	{q6}, [r7]!
+	veor	q5, q5, q13
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	add	r4, sp, #0x90			@ pass key schedule
+#else
+	add	r4, r10, #248			@ pass key schedule
+#endif
+	veor	q6, q6, q14
+	mov	r5, r1			@ pass rounds
+	mov	r0, sp
+
+	bl	_bsaes_encrypt8
+
+	vld1.64	{q8,q9}, [r0,:128]!
+	vld1.64	{q10,q11}, [r0,:128]!
+	veor	q0, q0, q8
+	vld1.64	{q12,q13}, [r0,:128]!
+	veor	q1, q1, q9
+	veor	q8, q4, q10
+	vst1.8	{q0,q1}, [r8]!
+	veor	q9, q6, q11
+	vld1.64	{q14}, [r0,:128]!
+	veor	q10, q3, q12
+	vst1.8	{q8,q9}, [r8]!
+	veor	q11, q7, q13
+	veor	q12, q2, q14
+	vst1.8	{q10,q11}, [r8]!
+	vst1.8	{q12}, [r8]!
+
+	vld1.64	{q8}, [r0,:128]		@ next round tweak
+	b	Lxts_enc_done
+.align	4
+Lxts_enc_6:
+	veor	q4, q4, q12
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	add	r4, sp, #0x90			@ pass key schedule
+#else
+	add	r4, r10, #248			@ pass key schedule
+#endif
+	veor	q5, q5, q13
+	mov	r5, r1			@ pass rounds
+	mov	r0, sp
+
+	bl	_bsaes_encrypt8
+
+	vld1.64	{q8,q9}, [r0,:128]!
+	vld1.64	{q10,q11}, [r0,:128]!
+	veor	q0, q0, q8
+	vld1.64	{q12,q13}, [r0,:128]!
+	veor	q1, q1, q9
+	veor	q8, q4, q10
+	vst1.8	{q0,q1}, [r8]!
+	veor	q9, q6, q11
+	veor	q10, q3, q12
+	vst1.8	{q8,q9}, [r8]!
+	veor	q11, q7, q13
+	vst1.8	{q10,q11}, [r8]!
+
+	vld1.64	{q8}, [r0,:128]		@ next round tweak
+	b	Lxts_enc_done
+
+@ put this in range for both ARM and Thumb mode adr instructions
+.align	5
+Lxts_magic:
+.quad	1, 0x87
+
+.align	5
+Lxts_enc_5:
+	veor	q3, q3, q11
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	add	r4, sp, #0x90			@ pass key schedule
+#else
+	add	r4, r10, #248			@ pass key schedule
+#endif
+	veor	q4, q4, q12
+	mov	r5, r1			@ pass rounds
+	mov	r0, sp
+
+	bl	_bsaes_encrypt8
+
+	vld1.64	{q8,q9}, [r0,:128]!
+	vld1.64	{q10,q11}, [r0,:128]!
+	veor	q0, q0, q8
+	vld1.64	{q12}, [r0,:128]!
+	veor	q1, q1, q9
+	veor	q8, q4, q10
+	vst1.8	{q0,q1}, [r8]!
+	veor	q9, q6, q11
+	veor	q10, q3, q12
+	vst1.8	{q8,q9}, [r8]!
+	vst1.8	{q10}, [r8]!
+
+	vld1.64	{q8}, [r0,:128]		@ next round tweak
+	b	Lxts_enc_done
+.align	4
+Lxts_enc_4:
+	veor	q2, q2, q10
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	add	r4, sp, #0x90			@ pass key schedule
+#else
+	add	r4, r10, #248			@ pass key schedule
+#endif
+	veor	q3, q3, q11
+	mov	r5, r1			@ pass rounds
+	mov	r0, sp
+
+	bl	_bsaes_encrypt8
+
+	vld1.64	{q8,q9}, [r0,:128]!
+	vld1.64	{q10,q11}, [r0,:128]!
+	veor	q0, q0, q8
+	veor	q1, q1, q9
+	veor	q8, q4, q10
+	vst1.8	{q0,q1}, [r8]!
+	veor	q9, q6, q11
+	vst1.8	{q8,q9}, [r8]!
+
+	vld1.64	{q8}, [r0,:128]		@ next round tweak
+	b	Lxts_enc_done
+.align	4
+Lxts_enc_3:
+	veor	q1, q1, q9
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	add	r4, sp, #0x90			@ pass key schedule
+#else
+	add	r4, r10, #248			@ pass key schedule
+#endif
+	veor	q2, q2, q10
+	mov	r5, r1			@ pass rounds
+	mov	r0, sp
+
+	bl	_bsaes_encrypt8
+
+	vld1.64	{q8,q9}, [r0,:128]!
+	vld1.64	{q10}, [r0,:128]!
+	veor	q0, q0, q8
+	veor	q1, q1, q9
+	veor	q8, q4, q10
+	vst1.8	{q0,q1}, [r8]!
+	vst1.8	{q8}, [r8]!
+
+	vld1.64	{q8}, [r0,:128]		@ next round tweak
+	b	Lxts_enc_done
+.align	4
+Lxts_enc_2:
+	veor	q0, q0, q8
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	add	r4, sp, #0x90			@ pass key schedule
+#else
+	add	r4, r10, #248			@ pass key schedule
+#endif
+	veor	q1, q1, q9
+	mov	r5, r1			@ pass rounds
+	mov	r0, sp
+
+	bl	_bsaes_encrypt8
+
+	vld1.64	{q8,q9}, [r0,:128]!
+	veor	q0, q0, q8
+	veor	q1, q1, q9
+	vst1.8	{q0,q1}, [r8]!
+
+	vld1.64	{q8}, [r0,:128]		@ next round tweak
+	b	Lxts_enc_done
+.align	4
+Lxts_enc_1:
+	mov	r0, sp
+	veor	q0, q0, q8
+	mov	r1, sp
+	vst1.8	{q0}, [sp,:128]
+	mov	r2, r10
+	mov	r4, r3				@ preserve fp
+
+	bl	_AES_encrypt
+
+	vld1.8	{q0}, [sp,:128]
+	veor	q0, q0, q8
+	vst1.8	{q0}, [r8]!
+	mov	r3, r4
+
+	vmov	q8, q9		@ next round tweak
+
+Lxts_enc_done:
+#ifndef	XTS_CHAIN_TWEAK
+	adds	r9, #0x10
+	beq	Lxts_enc_ret
+	sub	r6, r8, #0x10
+
+Lxts_enc_steal:
+	ldrb	r0, [r7], #1
+	ldrb	r1, [r8, #-0x10]
+	strb	r0, [r8, #-0x10]
+	strb	r1, [r8], #1
+
+	subs	r9, #1
+	bhi	Lxts_enc_steal
+
+	vld1.8	{q0}, [r6]
+	mov	r0, sp
+	veor	q0, q0, q8
+	mov	r1, sp
+	vst1.8	{q0}, [sp,:128]
+	mov	r2, r10
+	mov	r4, r3			@ preserve fp
+
+	bl	_AES_encrypt
+
+	vld1.8	{q0}, [sp,:128]
+	veor	q0, q0, q8
+	vst1.8	{q0}, [r6]
+	mov	r3, r4
+#endif
+
+Lxts_enc_ret:
+	bic	r0, r3, #0xf
+	vmov.i32	q0, #0
+	vmov.i32	q1, #0
+#ifdef	XTS_CHAIN_TWEAK
+	ldr	r1, [r3, #0x20+VFP_ABI_FRAME]	@ chain tweak
+#endif
+Lxts_enc_bzero:@ wipe key schedule [if any]
+	vstmia	sp!, {q0,q1}
+	cmp	sp, r0
+	bne	Lxts_enc_bzero
+
+	mov	sp, r3
+#ifdef	XTS_CHAIN_TWEAK
+	vst1.8	{q8}, [r1]
+#endif
+	VFP_ABI_POP
+	ldmia	sp!, {r4,r5,r6,r7,r8,r9,r10, pc}	@ return
+
+
+
+.globl	_bsaes_xts_decrypt
+.private_extern	_bsaes_xts_decrypt
+
+.align	4
+_bsaes_xts_decrypt:
+	mov	ip, sp
+	stmdb	sp!, {r4,r5,r6,r7,r8,r9,r10, lr}		@ 0x20
+	VFP_ABI_PUSH
+	mov	r6, sp				@ future r3
+
+	mov	r7, r0
+	mov	r8, r1
+	mov	r9, r2
+	mov	r10, r3
+
+	sub	r0, sp, #0x10			@ 0x10
+	bic	r0, #0xf			@ align at 16 bytes
+	mov	sp, r0
+
+#ifdef	XTS_CHAIN_TWEAK
+	ldr	r0, [ip]			@ pointer to input tweak
+#else
+	@ generate initial tweak
+	ldr	r0, [ip, #4]			@ iv[]
+	mov	r1, sp
+	ldr	r2, [ip, #0]			@ key2
+	bl	_AES_encrypt
+	mov	r0, sp				@ pointer to initial tweak
+#endif
+
+	ldr	r1, [r10, #240]		@ get # of rounds
+	mov	r3, r6
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	@ allocate the key schedule on the stack
+	sub	r12, sp, r1, lsl#7		@ 128 bytes per inner round key
+	@ add	r12, #96			@ size of bit-sliced key schedule
+	sub	r12, #48			@ place for tweak[9]
+
+	@ populate the key schedule
+	mov	r4, r10			@ pass key
+	mov	r5, r1			@ pass # of rounds
+	mov	sp, r12
+	add	r12, #0x90			@ pass key schedule
+	bl	_bsaes_key_convert
+	add	r4, sp, #0x90
+	vldmia	r4, {q6}
+	vstmia	r12,  {q15}		@ save last round key
+	veor	q7, q7, q6	@ fix up round 0 key
+	vstmia	r4, {q7}
+#else
+	ldr	r12, [r10, #244]
+	eors	r12, #1
+	beq	0f
+
+	str	r12, [r10, #244]
+	mov	r4, r10			@ pass key
+	mov	r5, r1			@ pass # of rounds
+	add	r12, r10, #248			@ pass key schedule
+	bl	_bsaes_key_convert
+	add	r4, r10, #248
+	vldmia	r4, {q6}
+	vstmia	r12,  {q15}		@ save last round key
+	veor	q7, q7, q6	@ fix up round 0 key
+	vstmia	r4, {q7}
+
+.align	2
+	sub	sp, #0x90			@ place for tweak[9]
+#endif
+	vld1.8	{q8}, [r0]			@ initial tweak
+	adr	r2, Lxts_magic
+
+#ifndef	XTS_CHAIN_TWEAK
+	tst	r9, #0xf			@ if not multiple of 16
+	it	ne				@ Thumb2 thing, sanity check in ARM
+	subne	r9, #0x10			@ subtract another 16 bytes
+#endif
+	subs	r9, #0x80
+
+	blo	Lxts_dec_short
+	b	Lxts_dec_loop
+
+.align	4
+Lxts_dec_loop:
+	vldmia	r2, {q5}	@ load XTS magic
+	vshr.s64	q6, q8, #63
+	mov	r0, sp
+	vand	q6, q6, q5
+	vadd.u64	q9, q8, q8
+	vst1.64	{q8}, [r0,:128]!
+	vswp	d13,d12
+	vshr.s64	q7, q9, #63
+	veor	q9, q9, q6
+	vand	q7, q7, q5
+	vadd.u64	q10, q9, q9
+	vst1.64	{q9}, [r0,:128]!
+	vswp	d15,d14
+	vshr.s64	q6, q10, #63
+	veor	q10, q10, q7
+	vand	q6, q6, q5
+	vld1.8	{q0}, [r7]!
+	vadd.u64	q11, q10, q10
+	vst1.64	{q10}, [r0,:128]!
+	vswp	d13,d12
+	vshr.s64	q7, q11, #63
+	veor	q11, q11, q6
+	vand	q7, q7, q5
+	vld1.8	{q1}, [r7]!
+	veor	q0, q0, q8
+	vadd.u64	q12, q11, q11
+	vst1.64	{q11}, [r0,:128]!
+	vswp	d15,d14
+	vshr.s64	q6, q12, #63
+	veor	q12, q12, q7
+	vand	q6, q6, q5
+	vld1.8	{q2}, [r7]!
+	veor	q1, q1, q9
+	vadd.u64	q13, q12, q12
+	vst1.64	{q12}, [r0,:128]!
+	vswp	d13,d12
+	vshr.s64	q7, q13, #63
+	veor	q13, q13, q6
+	vand	q7, q7, q5
+	vld1.8	{q3}, [r7]!
+	veor	q2, q2, q10
+	vadd.u64	q14, q13, q13
+	vst1.64	{q13}, [r0,:128]!
+	vswp	d15,d14
+	vshr.s64	q6, q14, #63
+	veor	q14, q14, q7
+	vand	q6, q6, q5
+	vld1.8	{q4}, [r7]!
+	veor	q3, q3, q11
+	vadd.u64	q15, q14, q14
+	vst1.64	{q14}, [r0,:128]!
+	vswp	d13,d12
+	vshr.s64	q7, q15, #63
+	veor	q15, q15, q6
+	vand	q7, q7, q5
+	vld1.8	{q5}, [r7]!
+	veor	q4, q4, q12
+	vadd.u64	q8, q15, q15
+	vst1.64	{q15}, [r0,:128]!
+	vswp	d15,d14
+	veor	q8, q8, q7
+	vst1.64	{q8}, [r0,:128]		@ next round tweak
+
+	vld1.8	{q6,q7}, [r7]!
+	veor	q5, q5, q13
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	add	r4, sp, #0x90			@ pass key schedule
+#else
+	add	r4, r10, #248			@ pass key schedule
+#endif
+	veor	q6, q6, q14
+	mov	r5, r1			@ pass rounds
+	veor	q7, q7, q15
+	mov	r0, sp
+
+	bl	_bsaes_decrypt8
+
+	vld1.64	{q8,q9}, [r0,:128]!
+	vld1.64	{q10,q11}, [r0,:128]!
+	veor	q0, q0, q8
+	vld1.64	{q12,q13}, [r0,:128]!
+	veor	q1, q1, q9
+	veor	q8, q6, q10
+	vst1.8	{q0,q1}, [r8]!
+	veor	q9, q4, q11
+	vld1.64	{q14,q15}, [r0,:128]!
+	veor	q10, q2, q12
+	vst1.8	{q8,q9}, [r8]!
+	veor	q11, q7, q13
+	veor	q12, q3, q14
+	vst1.8	{q10,q11}, [r8]!
+	veor	q13, q5, q15
+	vst1.8	{q12,q13}, [r8]!
+
+	vld1.64	{q8}, [r0,:128]		@ next round tweak
+
+	subs	r9, #0x80
+	bpl	Lxts_dec_loop
+
+Lxts_dec_short:
+	adds	r9, #0x70
+	bmi	Lxts_dec_done
+
+	vldmia	r2, {q5}	@ load XTS magic
+	vshr.s64	q7, q8, #63
+	mov	r0, sp
+	vand	q7, q7, q5
+	vadd.u64	q9, q8, q8
+	vst1.64	{q8}, [r0,:128]!
+	vswp	d15,d14
+	vshr.s64	q6, q9, #63
+	veor	q9, q9, q7
+	vand	q6, q6, q5
+	vadd.u64	q10, q9, q9
+	vst1.64	{q9}, [r0,:128]!
+	vswp	d13,d12
+	vshr.s64	q7, q10, #63
+	veor	q10, q10, q6
+	vand	q7, q7, q5
+	vld1.8	{q0}, [r7]!
+	subs	r9, #0x10
+	bmi	Lxts_dec_1
+	vadd.u64	q11, q10, q10
+	vst1.64	{q10}, [r0,:128]!
+	vswp	d15,d14
+	vshr.s64	q6, q11, #63
+	veor	q11, q11, q7
+	vand	q6, q6, q5
+	vld1.8	{q1}, [r7]!
+	subs	r9, #0x10
+	bmi	Lxts_dec_2
+	veor	q0, q0, q8
+	vadd.u64	q12, q11, q11
+	vst1.64	{q11}, [r0,:128]!
+	vswp	d13,d12
+	vshr.s64	q7, q12, #63
+	veor	q12, q12, q6
+	vand	q7, q7, q5
+	vld1.8	{q2}, [r7]!
+	subs	r9, #0x10
+	bmi	Lxts_dec_3
+	veor	q1, q1, q9
+	vadd.u64	q13, q12, q12
+	vst1.64	{q12}, [r0,:128]!
+	vswp	d15,d14
+	vshr.s64	q6, q13, #63
+	veor	q13, q13, q7
+	vand	q6, q6, q5
+	vld1.8	{q3}, [r7]!
+	subs	r9, #0x10
+	bmi	Lxts_dec_4
+	veor	q2, q2, q10
+	vadd.u64	q14, q13, q13
+	vst1.64	{q13}, [r0,:128]!
+	vswp	d13,d12
+	vshr.s64	q7, q14, #63
+	veor	q14, q14, q6
+	vand	q7, q7, q5
+	vld1.8	{q4}, [r7]!
+	subs	r9, #0x10
+	bmi	Lxts_dec_5
+	veor	q3, q3, q11
+	vadd.u64	q15, q14, q14
+	vst1.64	{q14}, [r0,:128]!
+	vswp	d15,d14
+	vshr.s64	q6, q15, #63
+	veor	q15, q15, q7
+	vand	q6, q6, q5
+	vld1.8	{q5}, [r7]!
+	subs	r9, #0x10
+	bmi	Lxts_dec_6
+	veor	q4, q4, q12
+	sub	r9, #0x10
+	vst1.64	{q15}, [r0,:128]		@ next round tweak
+
+	vld1.8	{q6}, [r7]!
+	veor	q5, q5, q13
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	add	r4, sp, #0x90			@ pass key schedule
+#else
+	add	r4, r10, #248			@ pass key schedule
+#endif
+	veor	q6, q6, q14
+	mov	r5, r1			@ pass rounds
+	mov	r0, sp
+
+	bl	_bsaes_decrypt8
+
+	vld1.64	{q8,q9}, [r0,:128]!
+	vld1.64	{q10,q11}, [r0,:128]!
+	veor	q0, q0, q8
+	vld1.64	{q12,q13}, [r0,:128]!
+	veor	q1, q1, q9
+	veor	q8, q6, q10
+	vst1.8	{q0,q1}, [r8]!
+	veor	q9, q4, q11
+	vld1.64	{q14}, [r0,:128]!
+	veor	q10, q2, q12
+	vst1.8	{q8,q9}, [r8]!
+	veor	q11, q7, q13
+	veor	q12, q3, q14
+	vst1.8	{q10,q11}, [r8]!
+	vst1.8	{q12}, [r8]!
+
+	vld1.64	{q8}, [r0,:128]		@ next round tweak
+	b	Lxts_dec_done
+.align	4
+Lxts_dec_6:
+	vst1.64	{q14}, [r0,:128]		@ next round tweak
+
+	veor	q4, q4, q12
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	add	r4, sp, #0x90			@ pass key schedule
+#else
+	add	r4, r10, #248			@ pass key schedule
+#endif
+	veor	q5, q5, q13
+	mov	r5, r1			@ pass rounds
+	mov	r0, sp
+
+	bl	_bsaes_decrypt8
+
+	vld1.64	{q8,q9}, [r0,:128]!
+	vld1.64	{q10,q11}, [r0,:128]!
+	veor	q0, q0, q8
+	vld1.64	{q12,q13}, [r0,:128]!
+	veor	q1, q1, q9
+	veor	q8, q6, q10
+	vst1.8	{q0,q1}, [r8]!
+	veor	q9, q4, q11
+	veor	q10, q2, q12
+	vst1.8	{q8,q9}, [r8]!
+	veor	q11, q7, q13
+	vst1.8	{q10,q11}, [r8]!
+
+	vld1.64	{q8}, [r0,:128]		@ next round tweak
+	b	Lxts_dec_done
+.align	4
+Lxts_dec_5:
+	veor	q3, q3, q11
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	add	r4, sp, #0x90			@ pass key schedule
+#else
+	add	r4, r10, #248			@ pass key schedule
+#endif
+	veor	q4, q4, q12
+	mov	r5, r1			@ pass rounds
+	mov	r0, sp
+
+	bl	_bsaes_decrypt8
+
+	vld1.64	{q8,q9}, [r0,:128]!
+	vld1.64	{q10,q11}, [r0,:128]!
+	veor	q0, q0, q8
+	vld1.64	{q12}, [r0,:128]!
+	veor	q1, q1, q9
+	veor	q8, q6, q10
+	vst1.8	{q0,q1}, [r8]!
+	veor	q9, q4, q11
+	veor	q10, q2, q12
+	vst1.8	{q8,q9}, [r8]!
+	vst1.8	{q10}, [r8]!
+
+	vld1.64	{q8}, [r0,:128]		@ next round tweak
+	b	Lxts_dec_done
+.align	4
+Lxts_dec_4:
+	veor	q2, q2, q10
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	add	r4, sp, #0x90			@ pass key schedule
+#else
+	add	r4, r10, #248			@ pass key schedule
+#endif
+	veor	q3, q3, q11
+	mov	r5, r1			@ pass rounds
+	mov	r0, sp
+
+	bl	_bsaes_decrypt8
+
+	vld1.64	{q8,q9}, [r0,:128]!
+	vld1.64	{q10,q11}, [r0,:128]!
+	veor	q0, q0, q8
+	veor	q1, q1, q9
+	veor	q8, q6, q10
+	vst1.8	{q0,q1}, [r8]!
+	veor	q9, q4, q11
+	vst1.8	{q8,q9}, [r8]!
+
+	vld1.64	{q8}, [r0,:128]		@ next round tweak
+	b	Lxts_dec_done
+.align	4
+Lxts_dec_3:
+	veor	q1, q1, q9
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	add	r4, sp, #0x90			@ pass key schedule
+#else
+	add	r4, r10, #248			@ pass key schedule
+#endif
+	veor	q2, q2, q10
+	mov	r5, r1			@ pass rounds
+	mov	r0, sp
+
+	bl	_bsaes_decrypt8
+
+	vld1.64	{q8,q9}, [r0,:128]!
+	vld1.64	{q10}, [r0,:128]!
+	veor	q0, q0, q8
+	veor	q1, q1, q9
+	veor	q8, q6, q10
+	vst1.8	{q0,q1}, [r8]!
+	vst1.8	{q8}, [r8]!
+
+	vld1.64	{q8}, [r0,:128]		@ next round tweak
+	b	Lxts_dec_done
+.align	4
+Lxts_dec_2:
+	veor	q0, q0, q8
+#ifndef	BSAES_ASM_EXTENDED_KEY
+	add	r4, sp, #0x90			@ pass key schedule
+#else
+	add	r4, r10, #248			@ pass key schedule
+#endif
+	veor	q1, q1, q9
+	mov	r5, r1			@ pass rounds
+	mov	r0, sp
+
+	bl	_bsaes_decrypt8
+
+	vld1.64	{q8,q9}, [r0,:128]!
+	veor	q0, q0, q8
+	veor	q1, q1, q9
+	vst1.8	{q0,q1}, [r8]!
+
+	vld1.64	{q8}, [r0,:128]		@ next round tweak
+	b	Lxts_dec_done
+.align	4
+Lxts_dec_1:
+	mov	r0, sp
+	veor	q0, q0, q8
+	mov	r1, sp
+	vst1.8	{q0}, [sp,:128]
+	mov	r5, r2			@ preserve magic
+	mov	r2, r10
+	mov	r4, r3				@ preserve fp
+
+	bl	_AES_decrypt
+
+	vld1.8	{q0}, [sp,:128]
+	veor	q0, q0, q8
+	vst1.8	{q0}, [r8]!
+	mov	r3, r4
+	mov	r2, r5
+
+	vmov	q8, q9		@ next round tweak
+
+Lxts_dec_done:
+#ifndef	XTS_CHAIN_TWEAK
+	adds	r9, #0x10
+	beq	Lxts_dec_ret
+
+	@ calculate one round of extra tweak for the stolen ciphertext
+	vldmia	r2, {q5}
+	vshr.s64	q6, q8, #63
+	vand	q6, q6, q5
+	vadd.u64	q9, q8, q8
+	vswp	d13,d12
+	veor	q9, q9, q6
+
+	@ perform the final decryption with the last tweak value
+	vld1.8	{q0}, [r7]!
+	mov	r0, sp
+	veor	q0, q0, q9
+	mov	r1, sp
+	vst1.8	{q0}, [sp,:128]
+	mov	r2, r10
+	mov	r4, r3			@ preserve fp
+
+	bl	_AES_decrypt
+
+	vld1.8	{q0}, [sp,:128]
+	veor	q0, q0, q9
+	vst1.8	{q0}, [r8]
+
+	mov	r6, r8
+Lxts_dec_steal:
+	ldrb	r1, [r8]
+	ldrb	r0, [r7], #1
+	strb	r1, [r8, #0x10]
+	strb	r0, [r8], #1
+
+	subs	r9, #1
+	bhi	Lxts_dec_steal
+
+	vld1.8	{q0}, [r6]
+	mov	r0, sp
+	veor	q0, q8
+	mov	r1, sp
+	vst1.8	{q0}, [sp,:128]
+	mov	r2, r10
+
+	bl	_AES_decrypt
+
+	vld1.8	{q0}, [sp,:128]
+	veor	q0, q0, q8
+	vst1.8	{q0}, [r6]
+	mov	r3, r4
+#endif
+
+Lxts_dec_ret:
+	bic	r0, r3, #0xf
+	vmov.i32	q0, #0
+	vmov.i32	q1, #0
+#ifdef	XTS_CHAIN_TWEAK
+	ldr	r1, [r3, #0x20+VFP_ABI_FRAME]	@ chain tweak
+#endif
+Lxts_dec_bzero:@ wipe key schedule [if any]
+	vstmia	sp!, {q0,q1}
+	cmp	sp, r0
+	bne	Lxts_dec_bzero
+
+	mov	sp, r3
+#ifdef	XTS_CHAIN_TWEAK
+	vst1.8	{q8}, [r1]
+#endif
+	VFP_ABI_POP
+	ldmia	sp!, {r4,r5,r6,r7,r8,r9,r10, pc}	@ return
+
+
+#endif
diff --git a/third_party/boringssl/ios-arm/crypto/fipsmodule/ghash-armv4.S b/third_party/boringssl/ios-arm/crypto/fipsmodule/ghash-armv4.S
new file mode 100644
index 0000000..39abb3f
--- /dev/null
+++ b/third_party/boringssl/ios-arm/crypto/fipsmodule/ghash-armv4.S
@@ -0,0 +1,536 @@
+#include <openssl/arm_arch.h>
+
+.syntax	unified
+
+.text
+.code	32
+
+#ifdef  __clang__
+#define ldrplb  ldrbpl
+#define ldrneb  ldrbne
+#endif
+
+
+.align	5
+rem_4bit:
+.short	0x0000,0x1C20,0x3840,0x2460
+.short	0x7080,0x6CA0,0x48C0,0x54E0
+.short	0xE100,0xFD20,0xD940,0xC560
+.short	0x9180,0x8DA0,0xA9C0,0xB5E0
+
+
+
+rem_4bit_get:
+	sub	r2,pc,#8
+	sub	r2,r2,#32	@ &rem_4bit
+	b	Lrem_4bit_got
+	nop
+
+
+.globl	_gcm_ghash_4bit
+.private_extern	_gcm_ghash_4bit
+
+_gcm_ghash_4bit:
+	sub	r12,pc,#8
+	add	r3,r2,r3		@ r3 to point at the end
+	stmdb	sp!,{r3,r4,r5,r6,r7,r8,r9,r10,r11,lr}		@ save r3/end too
+	sub	r12,r12,#48		@ &rem_4bit
+
+	ldmia	r12,{r4,r5,r6,r7,r8,r9,r10,r11}		@ copy rem_4bit ...
+	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11}		@ ... to stack
+
+	ldrb	r12,[r2,#15]
+	ldrb	r14,[r0,#15]
+Louter:
+	eor	r12,r12,r14
+	and	r14,r12,#0xf0
+	and	r12,r12,#0x0f
+	mov	r3,#14
+
+	add	r7,r1,r12,lsl#4
+	ldmia	r7,{r4,r5,r6,r7}	@ load Htbl[nlo]
+	add	r11,r1,r14
+	ldrb	r12,[r2,#14]
+
+	and	r14,r4,#0xf		@ rem
+	ldmia	r11,{r8,r9,r10,r11}	@ load Htbl[nhi]
+	add	r14,r14,r14
+	eor	r4,r8,r4,lsr#4
+	ldrh	r8,[sp,r14]		@ rem_4bit[rem]
+	eor	r4,r4,r5,lsl#28
+	ldrb	r14,[r0,#14]
+	eor	r5,r9,r5,lsr#4
+	eor	r5,r5,r6,lsl#28
+	eor	r6,r10,r6,lsr#4
+	eor	r6,r6,r7,lsl#28
+	eor	r7,r11,r7,lsr#4
+	eor	r12,r12,r14
+	and	r14,r12,#0xf0
+	and	r12,r12,#0x0f
+	eor	r7,r7,r8,lsl#16
+
+Linner:
+	add	r11,r1,r12,lsl#4
+	and	r12,r4,#0xf		@ rem
+	subs	r3,r3,#1
+	add	r12,r12,r12
+	ldmia	r11,{r8,r9,r10,r11}	@ load Htbl[nlo]
+	eor	r4,r8,r4,lsr#4
+	eor	r4,r4,r5,lsl#28
+	eor	r5,r9,r5,lsr#4
+	eor	r5,r5,r6,lsl#28
+	ldrh	r8,[sp,r12]		@ rem_4bit[rem]
+	eor	r6,r10,r6,lsr#4
+	ldrbpl	r12,[r2,r3]
+	eor	r6,r6,r7,lsl#28
+	eor	r7,r11,r7,lsr#4
+
+	add	r11,r1,r14
+	and	r14,r4,#0xf		@ rem
+	eor	r7,r7,r8,lsl#16	@ ^= rem_4bit[rem]
+	add	r14,r14,r14
+	ldmia	r11,{r8,r9,r10,r11}	@ load Htbl[nhi]
+	eor	r4,r8,r4,lsr#4
+	ldrbpl	r8,[r0,r3]
+	eor	r4,r4,r5,lsl#28
+	eor	r5,r9,r5,lsr#4
+	ldrh	r9,[sp,r14]
+	eor	r5,r5,r6,lsl#28
+	eor	r6,r10,r6,lsr#4
+	eor	r6,r6,r7,lsl#28
+	eorpl	r12,r12,r8
+	eor	r7,r11,r7,lsr#4
+	andpl	r14,r12,#0xf0
+	andpl	r12,r12,#0x0f
+	eor	r7,r7,r9,lsl#16	@ ^= rem_4bit[rem]
+	bpl	Linner
+
+	ldr	r3,[sp,#32]		@ re-load r3/end
+	add	r2,r2,#16
+	mov	r14,r4
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+	rev	r4,r4
+	str	r4,[r0,#12]
+#elif defined(__ARMEB__)
+	str	r4,[r0,#12]
+#else
+	mov	r9,r4,lsr#8
+	strb	r4,[r0,#12+3]
+	mov	r10,r4,lsr#16
+	strb	r9,[r0,#12+2]
+	mov	r11,r4,lsr#24
+	strb	r10,[r0,#12+1]
+	strb	r11,[r0,#12]
+#endif
+	cmp	r2,r3
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+	rev	r5,r5
+	str	r5,[r0,#8]
+#elif defined(__ARMEB__)
+	str	r5,[r0,#8]
+#else
+	mov	r9,r5,lsr#8
+	strb	r5,[r0,#8+3]
+	mov	r10,r5,lsr#16
+	strb	r9,[r0,#8+2]
+	mov	r11,r5,lsr#24
+	strb	r10,[r0,#8+1]
+	strb	r11,[r0,#8]
+#endif
+	ldrbne	r12,[r2,#15]
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+	rev	r6,r6
+	str	r6,[r0,#4]
+#elif defined(__ARMEB__)
+	str	r6,[r0,#4]
+#else
+	mov	r9,r6,lsr#8
+	strb	r6,[r0,#4+3]
+	mov	r10,r6,lsr#16
+	strb	r9,[r0,#4+2]
+	mov	r11,r6,lsr#24
+	strb	r10,[r0,#4+1]
+	strb	r11,[r0,#4]
+#endif
+
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+	rev	r7,r7
+	str	r7,[r0,#0]
+#elif defined(__ARMEB__)
+	str	r7,[r0,#0]
+#else
+	mov	r9,r7,lsr#8
+	strb	r7,[r0,#0+3]
+	mov	r10,r7,lsr#16
+	strb	r9,[r0,#0+2]
+	mov	r11,r7,lsr#24
+	strb	r10,[r0,#0+1]
+	strb	r11,[r0,#0]
+#endif
+
+	bne	Louter
+
+	add	sp,sp,#36
+#if __ARM_ARCH__>=5
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,pc}
+#else
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,lr}
+	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+
+
+.globl	_gcm_gmult_4bit
+.private_extern	_gcm_gmult_4bit
+
+_gcm_gmult_4bit:
+	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,lr}
+	ldrb	r12,[r0,#15]
+	b	rem_4bit_get
+Lrem_4bit_got:
+	and	r14,r12,#0xf0
+	and	r12,r12,#0x0f
+	mov	r3,#14
+
+	add	r7,r1,r12,lsl#4
+	ldmia	r7,{r4,r5,r6,r7}	@ load Htbl[nlo]
+	ldrb	r12,[r0,#14]
+
+	add	r11,r1,r14
+	and	r14,r4,#0xf		@ rem
+	ldmia	r11,{r8,r9,r10,r11}	@ load Htbl[nhi]
+	add	r14,r14,r14
+	eor	r4,r8,r4,lsr#4
+	ldrh	r8,[r2,r14]	@ rem_4bit[rem]
+	eor	r4,r4,r5,lsl#28
+	eor	r5,r9,r5,lsr#4
+	eor	r5,r5,r6,lsl#28
+	eor	r6,r10,r6,lsr#4
+	eor	r6,r6,r7,lsl#28
+	eor	r7,r11,r7,lsr#4
+	and	r14,r12,#0xf0
+	eor	r7,r7,r8,lsl#16
+	and	r12,r12,#0x0f
+
+Loop:
+	add	r11,r1,r12,lsl#4
+	and	r12,r4,#0xf		@ rem
+	subs	r3,r3,#1
+	add	r12,r12,r12
+	ldmia	r11,{r8,r9,r10,r11}	@ load Htbl[nlo]
+	eor	r4,r8,r4,lsr#4
+	eor	r4,r4,r5,lsl#28
+	eor	r5,r9,r5,lsr#4
+	eor	r5,r5,r6,lsl#28
+	ldrh	r8,[r2,r12]	@ rem_4bit[rem]
+	eor	r6,r10,r6,lsr#4
+	ldrbpl	r12,[r0,r3]
+	eor	r6,r6,r7,lsl#28
+	eor	r7,r11,r7,lsr#4
+
+	add	r11,r1,r14
+	and	r14,r4,#0xf		@ rem
+	eor	r7,r7,r8,lsl#16	@ ^= rem_4bit[rem]
+	add	r14,r14,r14
+	ldmia	r11,{r8,r9,r10,r11}	@ load Htbl[nhi]
+	eor	r4,r8,r4,lsr#4
+	eor	r4,r4,r5,lsl#28
+	eor	r5,r9,r5,lsr#4
+	ldrh	r8,[r2,r14]	@ rem_4bit[rem]
+	eor	r5,r5,r6,lsl#28
+	eor	r6,r10,r6,lsr#4
+	eor	r6,r6,r7,lsl#28
+	eor	r7,r11,r7,lsr#4
+	andpl	r14,r12,#0xf0
+	andpl	r12,r12,#0x0f
+	eor	r7,r7,r8,lsl#16	@ ^= rem_4bit[rem]
+	bpl	Loop
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+	rev	r4,r4
+	str	r4,[r0,#12]
+#elif defined(__ARMEB__)
+	str	r4,[r0,#12]
+#else
+	mov	r9,r4,lsr#8
+	strb	r4,[r0,#12+3]
+	mov	r10,r4,lsr#16
+	strb	r9,[r0,#12+2]
+	mov	r11,r4,lsr#24
+	strb	r10,[r0,#12+1]
+	strb	r11,[r0,#12]
+#endif
+
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+	rev	r5,r5
+	str	r5,[r0,#8]
+#elif defined(__ARMEB__)
+	str	r5,[r0,#8]
+#else
+	mov	r9,r5,lsr#8
+	strb	r5,[r0,#8+3]
+	mov	r10,r5,lsr#16
+	strb	r9,[r0,#8+2]
+	mov	r11,r5,lsr#24
+	strb	r10,[r0,#8+1]
+	strb	r11,[r0,#8]
+#endif
+
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+	rev	r6,r6
+	str	r6,[r0,#4]
+#elif defined(__ARMEB__)
+	str	r6,[r0,#4]
+#else
+	mov	r9,r6,lsr#8
+	strb	r6,[r0,#4+3]
+	mov	r10,r6,lsr#16
+	strb	r9,[r0,#4+2]
+	mov	r11,r6,lsr#24
+	strb	r10,[r0,#4+1]
+	strb	r11,[r0,#4]
+#endif
+
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+	rev	r7,r7
+	str	r7,[r0,#0]
+#elif defined(__ARMEB__)
+	str	r7,[r0,#0]
+#else
+	mov	r9,r7,lsr#8
+	strb	r7,[r0,#0+3]
+	mov	r10,r7,lsr#16
+	strb	r9,[r0,#0+2]
+	mov	r11,r7,lsr#24
+	strb	r10,[r0,#0+1]
+	strb	r11,[r0,#0]
+#endif
+
+#if __ARM_ARCH__>=5
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,pc}
+#else
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,lr}
+	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+
+#if __ARM_MAX_ARCH__>=7
+
+
+
+.globl	_gcm_init_neon
+.private_extern	_gcm_init_neon
+
+.align	4
+_gcm_init_neon:
+	vld1.64	d7,[r1]!		@ load H
+	vmov.i8	q8,#0xe1
+	vld1.64	d6,[r1]
+	vshl.i64	d17,#57
+	vshr.u64	d16,#63		@ t0=0xc2....01
+	vdup.8	q9,d7[7]
+	vshr.u64	d26,d6,#63
+	vshr.s8	q9,#7			@ broadcast carry bit
+	vshl.i64	q3,q3,#1
+	vand	q8,q8,q9
+	vorr	d7,d26		@ H<<<=1
+	veor	q3,q3,q8		@ twisted H
+	vstmia	r0,{q3}
+
+	bx	lr					@ bx lr
+
+
+.globl	_gcm_gmult_neon
+.private_extern	_gcm_gmult_neon
+
+.align	4
+_gcm_gmult_neon:
+	vld1.64	d7,[r0]!		@ load Xi
+	vld1.64	d6,[r0]!
+	vmov.i64	d29,#0x0000ffffffffffff
+	vldmia	r1,{d26,d27}	@ load twisted H
+	vmov.i64	d30,#0x00000000ffffffff
+#ifdef __ARMEL__
+	vrev64.8	q3,q3
+#endif
+	vmov.i64	d31,#0x000000000000ffff
+	veor	d28,d26,d27		@ Karatsuba pre-processing
+	mov	r3,#16
+	b	Lgmult_neon
+
+
+.globl	_gcm_ghash_neon
+.private_extern	_gcm_ghash_neon
+
+.align	4
+_gcm_ghash_neon:
+	vld1.64	d1,[r0]!		@ load Xi
+	vld1.64	d0,[r0]!
+	vmov.i64	d29,#0x0000ffffffffffff
+	vldmia	r1,{d26,d27}	@ load twisted H
+	vmov.i64	d30,#0x00000000ffffffff
+#ifdef __ARMEL__
+	vrev64.8	q0,q0
+#endif
+	vmov.i64	d31,#0x000000000000ffff
+	veor	d28,d26,d27		@ Karatsuba pre-processing
+
+Loop_neon:
+	vld1.64	d7,[r2]!		@ load inp
+	vld1.64	d6,[r2]!
+#ifdef __ARMEL__
+	vrev64.8	q3,q3
+#endif
+	veor	q3,q0			@ inp^=Xi
+Lgmult_neon:
+	vext.8	d16, d26, d26, #1	@ A1
+	vmull.p8	q8, d16, d6		@ F = A1*B
+	vext.8	d0, d6, d6, #1	@ B1
+	vmull.p8	q0, d26, d0		@ E = A*B1
+	vext.8	d18, d26, d26, #2	@ A2
+	vmull.p8	q9, d18, d6		@ H = A2*B
+	vext.8	d22, d6, d6, #2	@ B2
+	vmull.p8	q11, d26, d22		@ G = A*B2
+	vext.8	d20, d26, d26, #3	@ A3
+	veor	q8, q8, q0		@ L = E + F
+	vmull.p8	q10, d20, d6		@ J = A3*B
+	vext.8	d0, d6, d6, #3	@ B3
+	veor	q9, q9, q11		@ M = G + H
+	vmull.p8	q0, d26, d0		@ I = A*B3
+	veor	d16, d16, d17	@ t0 = (L) (P0 + P1) << 8
+	vand	d17, d17, d29
+	vext.8	d22, d6, d6, #4	@ B4
+	veor	d18, d18, d19	@ t1 = (M) (P2 + P3) << 16
+	vand	d19, d19, d30
+	vmull.p8	q11, d26, d22		@ K = A*B4
+	veor	q10, q10, q0		@ N = I + J
+	veor	d16, d16, d17
+	veor	d18, d18, d19
+	veor	d20, d20, d21	@ t2 = (N) (P4 + P5) << 24
+	vand	d21, d21, d31
+	vext.8	q8, q8, q8, #15
+	veor	d22, d22, d23	@ t3 = (K) (P6 + P7) << 32
+	vmov.i64	d23, #0
+	vext.8	q9, q9, q9, #14
+	veor	d20, d20, d21
+	vmull.p8	q0, d26, d6		@ D = A*B
+	vext.8	q11, q11, q11, #12
+	vext.8	q10, q10, q10, #13
+	veor	q8, q8, q9
+	veor	q10, q10, q11
+	veor	q0, q0, q8
+	veor	q0, q0, q10
+	veor	d6,d6,d7	@ Karatsuba pre-processing
+	vext.8	d16, d28, d28, #1	@ A1
+	vmull.p8	q8, d16, d6		@ F = A1*B
+	vext.8	d2, d6, d6, #1	@ B1
+	vmull.p8	q1, d28, d2		@ E = A*B1
+	vext.8	d18, d28, d28, #2	@ A2
+	vmull.p8	q9, d18, d6		@ H = A2*B
+	vext.8	d22, d6, d6, #2	@ B2
+	vmull.p8	q11, d28, d22		@ G = A*B2
+	vext.8	d20, d28, d28, #3	@ A3
+	veor	q8, q8, q1		@ L = E + F
+	vmull.p8	q10, d20, d6		@ J = A3*B
+	vext.8	d2, d6, d6, #3	@ B3
+	veor	q9, q9, q11		@ M = G + H
+	vmull.p8	q1, d28, d2		@ I = A*B3
+	veor	d16, d16, d17	@ t0 = (L) (P0 + P1) << 8
+	vand	d17, d17, d29
+	vext.8	d22, d6, d6, #4	@ B4
+	veor	d18, d18, d19	@ t1 = (M) (P2 + P3) << 16
+	vand	d19, d19, d30
+	vmull.p8	q11, d28, d22		@ K = A*B4
+	veor	q10, q10, q1		@ N = I + J
+	veor	d16, d16, d17
+	veor	d18, d18, d19
+	veor	d20, d20, d21	@ t2 = (N) (P4 + P5) << 24
+	vand	d21, d21, d31
+	vext.8	q8, q8, q8, #15
+	veor	d22, d22, d23	@ t3 = (K) (P6 + P7) << 32
+	vmov.i64	d23, #0
+	vext.8	q9, q9, q9, #14
+	veor	d20, d20, d21
+	vmull.p8	q1, d28, d6		@ D = A*B
+	vext.8	q11, q11, q11, #12
+	vext.8	q10, q10, q10, #13
+	veor	q8, q8, q9
+	veor	q10, q10, q11
+	veor	q1, q1, q8
+	veor	q1, q1, q10
+	vext.8	d16, d27, d27, #1	@ A1
+	vmull.p8	q8, d16, d7		@ F = A1*B
+	vext.8	d4, d7, d7, #1	@ B1
+	vmull.p8	q2, d27, d4		@ E = A*B1
+	vext.8	d18, d27, d27, #2	@ A2
+	vmull.p8	q9, d18, d7		@ H = A2*B
+	vext.8	d22, d7, d7, #2	@ B2
+	vmull.p8	q11, d27, d22		@ G = A*B2
+	vext.8	d20, d27, d27, #3	@ A3
+	veor	q8, q8, q2		@ L = E + F
+	vmull.p8	q10, d20, d7		@ J = A3*B
+	vext.8	d4, d7, d7, #3	@ B3
+	veor	q9, q9, q11		@ M = G + H
+	vmull.p8	q2, d27, d4		@ I = A*B3
+	veor	d16, d16, d17	@ t0 = (L) (P0 + P1) << 8
+	vand	d17, d17, d29
+	vext.8	d22, d7, d7, #4	@ B4
+	veor	d18, d18, d19	@ t1 = (M) (P2 + P3) << 16
+	vand	d19, d19, d30
+	vmull.p8	q11, d27, d22		@ K = A*B4
+	veor	q10, q10, q2		@ N = I + J
+	veor	d16, d16, d17
+	veor	d18, d18, d19
+	veor	d20, d20, d21	@ t2 = (N) (P4 + P5) << 24
+	vand	d21, d21, d31
+	vext.8	q8, q8, q8, #15
+	veor	d22, d22, d23	@ t3 = (K) (P6 + P7) << 32
+	vmov.i64	d23, #0
+	vext.8	q9, q9, q9, #14
+	veor	d20, d20, d21
+	vmull.p8	q2, d27, d7		@ D = A*B
+	vext.8	q11, q11, q11, #12
+	vext.8	q10, q10, q10, #13
+	veor	q8, q8, q9
+	veor	q10, q10, q11
+	veor	q2, q2, q8
+	veor	q2, q2, q10
+	veor	q1,q1,q0		@ Karatsuba post-processing
+	veor	q1,q1,q2
+	veor	d1,d1,d2
+	veor	d4,d4,d3	@ Xh|Xl - 256-bit result
+
+	@ equivalent of reduction_avx from ghash-x86_64.pl
+	vshl.i64	q9,q0,#57		@ 1st phase
+	vshl.i64	q10,q0,#62
+	veor	q10,q10,q9		@
+	vshl.i64	q9,q0,#63
+	veor	q10, q10, q9		@
+	veor	d1,d1,d20	@
+	veor	d4,d4,d21
+
+	vshr.u64	q10,q0,#1		@ 2nd phase
+	veor	q2,q2,q0
+	veor	q0,q0,q10		@
+	vshr.u64	q10,q10,#6
+	vshr.u64	q0,q0,#1		@
+	veor	q0,q0,q2		@
+	veor	q0,q0,q10		@
+
+	subs	r3,#16
+	bne	Loop_neon
+
+#ifdef __ARMEL__
+	vrev64.8	q0,q0
+#endif
+	sub	r0,#16
+	vst1.64	d1,[r0]!		@ write out Xi
+	vst1.64	d0,[r0]
+
+	bx	lr					@ bx lr
+
+#endif
+.byte	71,72,65,83,72,32,102,111,114,32,65,82,77,118,52,47,78,69,79,78,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+.align	2
diff --git a/third_party/boringssl/ios-arm/crypto/fipsmodule/ghashv8-armx32.S b/third_party/boringssl/ios-arm/crypto/fipsmodule/ghashv8-armx32.S
new file mode 100644
index 0000000..10a0ab0
--- /dev/null
+++ b/third_party/boringssl/ios-arm/crypto/fipsmodule/ghashv8-armx32.S
@@ -0,0 +1,234 @@
+#include <openssl/arm_arch.h>
+
+.text
+
+.code	32
+.globl	_gcm_init_v8
+.private_extern	_gcm_init_v8
+
+.align	4
+_gcm_init_v8:
+	vld1.64	{q9},[r1]		@ load input H
+	vmov.i8	q11,#0xe1
+	vshl.i64	q11,q11,#57		@ 0xc2.0
+	vext.8	q3,q9,q9,#8
+	vshr.u64	q10,q11,#63
+	vdup.32	q9,d18[1]
+	vext.8	q8,q10,q11,#8		@ t0=0xc2....01
+	vshr.u64	q10,q3,#63
+	vshr.s32	q9,q9,#31		@ broadcast carry bit
+	vand	q10,q10,q8
+	vshl.i64	q3,q3,#1
+	vext.8	q10,q10,q10,#8
+	vand	q8,q8,q9
+	vorr	q3,q3,q10		@ H<<<=1
+	veor	q12,q3,q8		@ twisted H
+	vst1.64	{q12},[r0]!		@ store Htable[0]
+
+	@ calculate H^2
+	vext.8	q8,q12,q12,#8		@ Karatsuba pre-processing
+.byte	0xa8,0x0e,0xa8,0xf2	@ pmull q0,q12,q12
+	veor	q8,q8,q12
+.byte	0xa9,0x4e,0xa9,0xf2	@ pmull2 q2,q12,q12
+.byte	0xa0,0x2e,0xa0,0xf2	@ pmull q1,q8,q8
+
+	vext.8	q9,q0,q2,#8		@ Karatsuba post-processing
+	veor	q10,q0,q2
+	veor	q1,q1,q9
+	veor	q1,q1,q10
+.byte	0x26,0x4e,0xe0,0xf2	@ pmull q10,q0,q11		@ 1st phase
+
+	vmov	d4,d3		@ Xh|Xm - 256-bit result
+	vmov	d3,d0		@ Xm is rotated Xl
+	veor	q0,q1,q10
+
+	vext.8	q10,q0,q0,#8		@ 2nd phase
+.byte	0x26,0x0e,0xa0,0xf2	@ pmull q0,q0,q11
+	veor	q10,q10,q2
+	veor	q14,q0,q10
+
+	vext.8	q9,q14,q14,#8		@ Karatsuba pre-processing
+	veor	q9,q9,q14
+	vext.8	q13,q8,q9,#8		@ pack Karatsuba pre-processed
+	vst1.64	{q13,q14},[r0]		@ store Htable[1..2]
+
+	bx	lr
+
+.globl	_gcm_gmult_v8
+.private_extern	_gcm_gmult_v8
+
+.align	4
+_gcm_gmult_v8:
+	vld1.64	{q9},[r0]		@ load Xi
+	vmov.i8	q11,#0xe1
+	vld1.64	{q12,q13},[r1]	@ load twisted H, ...
+	vshl.u64	q11,q11,#57
+#ifndef __ARMEB__
+	vrev64.8	q9,q9
+#endif
+	vext.8	q3,q9,q9,#8
+
+.byte	0x86,0x0e,0xa8,0xf2	@ pmull q0,q12,q3		@ H.lo·Xi.lo
+	veor	q9,q9,q3		@ Karatsuba pre-processing
+.byte	0x87,0x4e,0xa9,0xf2	@ pmull2 q2,q12,q3		@ H.hi·Xi.hi
+.byte	0xa2,0x2e,0xaa,0xf2	@ pmull q1,q13,q9		@ (H.lo+H.hi)·(Xi.lo+Xi.hi)
+
+	vext.8	q9,q0,q2,#8		@ Karatsuba post-processing
+	veor	q10,q0,q2
+	veor	q1,q1,q9
+	veor	q1,q1,q10
+.byte	0x26,0x4e,0xe0,0xf2	@ pmull q10,q0,q11		@ 1st phase of reduction
+
+	vmov	d4,d3		@ Xh|Xm - 256-bit result
+	vmov	d3,d0		@ Xm is rotated Xl
+	veor	q0,q1,q10
+
+	vext.8	q10,q0,q0,#8		@ 2nd phase of reduction
+.byte	0x26,0x0e,0xa0,0xf2	@ pmull q0,q0,q11
+	veor	q10,q10,q2
+	veor	q0,q0,q10
+
+#ifndef __ARMEB__
+	vrev64.8	q0,q0
+#endif
+	vext.8	q0,q0,q0,#8
+	vst1.64	{q0},[r0]		@ write out Xi
+
+	bx	lr
+
+.globl	_gcm_ghash_v8
+.private_extern	_gcm_ghash_v8
+
+.align	4
+_gcm_ghash_v8:
+	vstmdb	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}		@ 32-bit ABI says so
+	vld1.64	{q0},[r0]		@ load [rotated] Xi
+						@ "[rotated]" means that
+						@ loaded value would have
+						@ to be rotated in order to
+						@ make it appear as in
+						@ alorithm specification
+	subs	r3,r3,#32		@ see if r3 is 32 or larger
+	mov	r12,#16		@ r12 is used as post-
+						@ increment for input pointer;
+						@ as loop is modulo-scheduled
+						@ r12 is zeroed just in time
+						@ to preclude oversteping
+						@ inp[len], which means that
+						@ last block[s] are actually
+						@ loaded twice, but last
+						@ copy is not processed
+	vld1.64	{q12,q13},[r1]!	@ load twisted H, ..., H^2
+	vmov.i8	q11,#0xe1
+	vld1.64	{q14},[r1]
+	moveq	r12,#0			@ is it time to zero r12?
+	vext.8	q0,q0,q0,#8		@ rotate Xi
+	vld1.64	{q8},[r2]!	@ load [rotated] I[0]
+	vshl.u64	q11,q11,#57		@ compose 0xc2.0 constant
+#ifndef __ARMEB__
+	vrev64.8	q8,q8
+	vrev64.8	q0,q0
+#endif
+	vext.8	q3,q8,q8,#8		@ rotate I[0]
+	blo	Lodd_tail_v8		@ r3 was less than 32
+	vld1.64	{q9},[r2],r12	@ load [rotated] I[1]
+#ifndef __ARMEB__
+	vrev64.8	q9,q9
+#endif
+	vext.8	q7,q9,q9,#8
+	veor	q3,q3,q0		@ I[i]^=Xi
+.byte	0x8e,0x8e,0xa8,0xf2	@ pmull q4,q12,q7		@ H·Ii+1
+	veor	q9,q9,q7		@ Karatsuba pre-processing
+.byte	0x8f,0xce,0xa9,0xf2	@ pmull2 q6,q12,q7
+	b	Loop_mod2x_v8
+
+.align	4
+Loop_mod2x_v8:
+	vext.8	q10,q3,q3,#8
+	subs	r3,r3,#32		@ is there more data?
+.byte	0x86,0x0e,0xac,0xf2	@ pmull q0,q14,q3		@ H^2.lo·Xi.lo
+	movlo	r12,#0			@ is it time to zero r12?
+
+.byte	0xa2,0xae,0xaa,0xf2	@ pmull q5,q13,q9
+	veor	q10,q10,q3		@ Karatsuba pre-processing
+.byte	0x87,0x4e,0xad,0xf2	@ pmull2 q2,q14,q3		@ H^2.hi·Xi.hi
+	veor	q0,q0,q4		@ accumulate
+.byte	0xa5,0x2e,0xab,0xf2	@ pmull2 q1,q13,q10		@ (H^2.lo+H^2.hi)·(Xi.lo+Xi.hi)
+	vld1.64	{q8},[r2],r12	@ load [rotated] I[i+2]
+
+	veor	q2,q2,q6
+	moveq	r12,#0			@ is it time to zero r12?
+	veor	q1,q1,q5
+
+	vext.8	q9,q0,q2,#8		@ Karatsuba post-processing
+	veor	q10,q0,q2
+	veor	q1,q1,q9
+	vld1.64	{q9},[r2],r12	@ load [rotated] I[i+3]
+#ifndef __ARMEB__
+	vrev64.8	q8,q8
+#endif
+	veor	q1,q1,q10
+.byte	0x26,0x4e,0xe0,0xf2	@ pmull q10,q0,q11		@ 1st phase of reduction
+
+#ifndef __ARMEB__
+	vrev64.8	q9,q9
+#endif
+	vmov	d4,d3		@ Xh|Xm - 256-bit result
+	vmov	d3,d0		@ Xm is rotated Xl
+	vext.8	q7,q9,q9,#8
+	vext.8	q3,q8,q8,#8
+	veor	q0,q1,q10
+.byte	0x8e,0x8e,0xa8,0xf2	@ pmull q4,q12,q7		@ H·Ii+1
+	veor	q3,q3,q2		@ accumulate q3 early
+
+	vext.8	q10,q0,q0,#8		@ 2nd phase of reduction
+.byte	0x26,0x0e,0xa0,0xf2	@ pmull q0,q0,q11
+	veor	q3,q3,q10
+	veor	q9,q9,q7		@ Karatsuba pre-processing
+	veor	q3,q3,q0
+.byte	0x8f,0xce,0xa9,0xf2	@ pmull2 q6,q12,q7
+	bhs	Loop_mod2x_v8		@ there was at least 32 more bytes
+
+	veor	q2,q2,q10
+	vext.8	q3,q8,q8,#8		@ re-construct q3
+	adds	r3,r3,#32		@ re-construct r3
+	veor	q0,q0,q2		@ re-construct q0
+	beq	Ldone_v8		@ is r3 zero?
+Lodd_tail_v8:
+	vext.8	q10,q0,q0,#8
+	veor	q3,q3,q0		@ inp^=Xi
+	veor	q9,q8,q10		@ q9 is rotated inp^Xi
+
+.byte	0x86,0x0e,0xa8,0xf2	@ pmull q0,q12,q3		@ H.lo·Xi.lo
+	veor	q9,q9,q3		@ Karatsuba pre-processing
+.byte	0x87,0x4e,0xa9,0xf2	@ pmull2 q2,q12,q3		@ H.hi·Xi.hi
+.byte	0xa2,0x2e,0xaa,0xf2	@ pmull q1,q13,q9		@ (H.lo+H.hi)·(Xi.lo+Xi.hi)
+
+	vext.8	q9,q0,q2,#8		@ Karatsuba post-processing
+	veor	q10,q0,q2
+	veor	q1,q1,q9
+	veor	q1,q1,q10
+.byte	0x26,0x4e,0xe0,0xf2	@ pmull q10,q0,q11		@ 1st phase of reduction
+
+	vmov	d4,d3		@ Xh|Xm - 256-bit result
+	vmov	d3,d0		@ Xm is rotated Xl
+	veor	q0,q1,q10
+
+	vext.8	q10,q0,q0,#8		@ 2nd phase of reduction
+.byte	0x26,0x0e,0xa0,0xf2	@ pmull q0,q0,q11
+	veor	q10,q10,q2
+	veor	q0,q0,q10
+
+Ldone_v8:
+#ifndef __ARMEB__
+	vrev64.8	q0,q0
+#endif
+	vext.8	q0,q0,q0,#8
+	vst1.64	{q0},[r0]		@ write out Xi
+
+	vldmia	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}		@ 32-bit ABI says so
+	bx	lr
+
+.byte	71,72,65,83,72,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+.align	2
diff --git a/third_party/boringssl/ios-arm/crypto/fipsmodule/sha1-armv4-large.S b/third_party/boringssl/ios-arm/crypto/fipsmodule/sha1-armv4-large.S
new file mode 100644
index 0000000..652ccbc9
--- /dev/null
+++ b/third_party/boringssl/ios-arm/crypto/fipsmodule/sha1-armv4-large.S
@@ -0,0 +1,1465 @@
+#include <openssl/arm_arch.h>
+
+.text
+.code	32
+
+.globl	_sha1_block_data_order
+.private_extern	_sha1_block_data_order
+
+
+.align	5
+_sha1_block_data_order:
+#if __ARM_MAX_ARCH__>=7
+	sub	r3,pc,#8		@ _sha1_block_data_order
+	ldr	r12,LOPENSSL_armcap
+	ldr	r12,[r3,r12]		@ OPENSSL_armcap_P
+#ifdef	__APPLE__
+	ldr	r12,[r12]
+#endif
+	tst	r12,#ARMV8_SHA1
+	bne	LARMv8
+	tst	r12,#ARMV7_NEON
+	bne	LNEON
+#endif
+	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
+	add	r2,r1,r2,lsl#6	@ r2 to point at the end of r1
+	ldmia	r0,{r3,r4,r5,r6,r7}
+Lloop:
+	ldr	r8,LK_00_19
+	mov	r14,sp
+	sub	sp,sp,#15*4
+	mov	r5,r5,ror#30
+	mov	r6,r6,ror#30
+	mov	r7,r7,ror#30		@ [6]
+L_00_15:
+#if __ARM_ARCH__<7
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r7,r8,r7,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r5,r6			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r7,r8,r7,ror#2			@ E+=K_00_19
+	eor	r10,r5,r6			@ F_xx_xx
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r4,r10,ror#2
+	add	r7,r7,r9			@ E+=X[i]
+	eor	r10,r10,r6,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r7,r7,r10			@ E+=F_00_19(B,C,D)
+#if __ARM_ARCH__<7
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r6,r8,r6,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r4,r5			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r6,r6,r7,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r6,r8,r6,ror#2			@ E+=K_00_19
+	eor	r10,r4,r5			@ F_xx_xx
+	add	r6,r6,r7,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r3,r10,ror#2
+	add	r6,r6,r9			@ E+=X[i]
+	eor	r10,r10,r5,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r6,r6,r10			@ E+=F_00_19(B,C,D)
+#if __ARM_ARCH__<7
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r5,r8,r5,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r3,r4			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r5,r5,r6,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r5,r8,r5,ror#2			@ E+=K_00_19
+	eor	r10,r3,r4			@ F_xx_xx
+	add	r5,r5,r6,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r7,r10,ror#2
+	add	r5,r5,r9			@ E+=X[i]
+	eor	r10,r10,r4,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r5,r5,r10			@ E+=F_00_19(B,C,D)
+#if __ARM_ARCH__<7
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r4,r8,r4,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r7,r3			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r4,r4,r5,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r4,r8,r4,ror#2			@ E+=K_00_19
+	eor	r10,r7,r3			@ F_xx_xx
+	add	r4,r4,r5,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r6,r10,ror#2
+	add	r4,r4,r9			@ E+=X[i]
+	eor	r10,r10,r3,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r4,r4,r10			@ E+=F_00_19(B,C,D)
+#if __ARM_ARCH__<7
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r3,r8,r3,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r6,r7			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r3,r3,r4,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r3,r8,r3,ror#2			@ E+=K_00_19
+	eor	r10,r6,r7			@ F_xx_xx
+	add	r3,r3,r4,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r5,r10,ror#2
+	add	r3,r3,r9			@ E+=X[i]
+	eor	r10,r10,r7,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r3,r3,r10			@ E+=F_00_19(B,C,D)
+	teq	r14,sp
+	bne	L_00_15		@ [((11+4)*5+2)*3]
+	sub	sp,sp,#25*4
+#if __ARM_ARCH__<7
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r7,r8,r7,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r5,r6			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r7,r8,r7,ror#2			@ E+=K_00_19
+	eor	r10,r5,r6			@ F_xx_xx
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r4,r10,ror#2
+	add	r7,r7,r9			@ E+=X[i]
+	eor	r10,r10,r6,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r7,r7,r10			@ E+=F_00_19(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r6,r8,r6,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r4,r5			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r6,r6,r7,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and	r10,r3,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r6,r6,r9			@ E+=X[i]
+	eor	r10,r10,r5,ror#2		@ F_00_19(B,C,D)
+	add	r6,r6,r10			@ E+=F_00_19(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r5,r8,r5,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r3,r4			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r5,r5,r6,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and	r10,r7,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r5,r5,r9			@ E+=X[i]
+	eor	r10,r10,r4,ror#2		@ F_00_19(B,C,D)
+	add	r5,r5,r10			@ E+=F_00_19(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r4,r8,r4,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r7,r3			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r4,r4,r5,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and	r10,r6,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r4,r4,r9			@ E+=X[i]
+	eor	r10,r10,r3,ror#2		@ F_00_19(B,C,D)
+	add	r4,r4,r10			@ E+=F_00_19(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r3,r8,r3,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r6,r7			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r3,r3,r4,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and	r10,r5,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r3,r3,r9			@ E+=X[i]
+	eor	r10,r10,r7,ror#2		@ F_00_19(B,C,D)
+	add	r3,r3,r10			@ E+=F_00_19(B,C,D)
+
+	ldr	r8,LK_20_39		@ [+15+16*4]
+	cmn	sp,#0			@ [+3], clear carry to denote 20_39
+L_20_39_or_60_79:
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r7,r8,r7,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r5,r6			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	eor	r10,r4,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r7,r7,r9			@ E+=X[i]
+	add	r7,r7,r10			@ E+=F_20_39(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r6,r8,r6,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r4,r5			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r6,r6,r7,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	eor	r10,r3,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r6,r6,r9			@ E+=X[i]
+	add	r6,r6,r10			@ E+=F_20_39(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r5,r8,r5,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r3,r4			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r5,r5,r6,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	eor	r10,r7,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r5,r5,r9			@ E+=X[i]
+	add	r5,r5,r10			@ E+=F_20_39(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r4,r8,r4,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r7,r3			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r4,r4,r5,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	eor	r10,r6,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r4,r4,r9			@ E+=X[i]
+	add	r4,r4,r10			@ E+=F_20_39(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r3,r8,r3,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r6,r7			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r3,r3,r4,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	eor	r10,r5,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r3,r3,r9			@ E+=X[i]
+	add	r3,r3,r10			@ E+=F_20_39(B,C,D)
+	teq	r14,sp			@ preserve carry
+	bne	L_20_39_or_60_79	@ [+((12+3)*5+2)*4]
+	bcs	L_done			@ [+((12+3)*5+2)*4], spare 300 bytes
+
+	ldr	r8,LK_40_59
+	sub	sp,sp,#20*4		@ [+2]
+L_40_59:
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r7,r8,r7,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r5,r6			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and	r10,r4,r10,ror#2					@ F_xx_xx
+	and	r11,r5,r6					@ F_xx_xx
+	add	r7,r7,r9			@ E+=X[i]
+	add	r7,r7,r10			@ E+=F_40_59(B,C,D)
+	add	r7,r7,r11,ror#2
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r6,r8,r6,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r4,r5			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r6,r6,r7,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and	r10,r3,r10,ror#2					@ F_xx_xx
+	and	r11,r4,r5					@ F_xx_xx
+	add	r6,r6,r9			@ E+=X[i]
+	add	r6,r6,r10			@ E+=F_40_59(B,C,D)
+	add	r6,r6,r11,ror#2
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r5,r8,r5,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r3,r4			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r5,r5,r6,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and	r10,r7,r10,ror#2					@ F_xx_xx
+	and	r11,r3,r4					@ F_xx_xx
+	add	r5,r5,r9			@ E+=X[i]
+	add	r5,r5,r10			@ E+=F_40_59(B,C,D)
+	add	r5,r5,r11,ror#2
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r4,r8,r4,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r7,r3			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r4,r4,r5,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and	r10,r6,r10,ror#2					@ F_xx_xx
+	and	r11,r7,r3					@ F_xx_xx
+	add	r4,r4,r9			@ E+=X[i]
+	add	r4,r4,r10			@ E+=F_40_59(B,C,D)
+	add	r4,r4,r11,ror#2
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r3,r8,r3,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r6,r7			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r3,r3,r4,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and	r10,r5,r10,ror#2					@ F_xx_xx
+	and	r11,r6,r7					@ F_xx_xx
+	add	r3,r3,r9			@ E+=X[i]
+	add	r3,r3,r10			@ E+=F_40_59(B,C,D)
+	add	r3,r3,r11,ror#2
+	teq	r14,sp
+	bne	L_40_59		@ [+((12+5)*5+2)*4]
+
+	ldr	r8,LK_60_79
+	sub	sp,sp,#20*4
+	cmp	sp,#0			@ set carry to denote 60_79
+	b	L_20_39_or_60_79	@ [+4], spare 300 bytes
+L_done:
+	add	sp,sp,#80*4		@ "deallocate" stack frame
+	ldmia	r0,{r8,r9,r10,r11,r12}
+	add	r3,r8,r3
+	add	r4,r9,r4
+	add	r5,r10,r5,ror#2
+	add	r6,r11,r6,ror#2
+	add	r7,r12,r7,ror#2
+	stmia	r0,{r3,r4,r5,r6,r7}
+	teq	r1,r2
+	bne	Lloop			@ [+18], total 1307
+
+#if __ARM_ARCH__>=5
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
+#else
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
+	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+
+
+.align	5
+LK_00_19:.word	0x5a827999
+LK_20_39:.word	0x6ed9eba1
+LK_40_59:.word	0x8f1bbcdc
+LK_60_79:.word	0xca62c1d6
+#if __ARM_MAX_ARCH__>=7
+LOPENSSL_armcap:
+.word	OPENSSL_armcap_P-_sha1_block_data_order
+#endif
+.byte	83,72,65,49,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,65,82,77,118,52,47,78,69,79,78,47,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+.align	5
+#if __ARM_MAX_ARCH__>=7
+
+
+
+
+.align	4
+sha1_block_data_order_neon:
+LNEON:
+	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
+	add	r2,r1,r2,lsl#6	@ r2 to point at the end of r1
+	@ dmb				@ errata #451034 on early Cortex A8
+	@ vstmdb	sp!,{d8-d15}	@ ABI specification says so
+	mov	r14,sp
+	sub	sp,sp,#64		@ alloca
+	adr	r8,LK_00_19
+	bic	sp,sp,#15		@ align for 128-bit stores
+
+	ldmia	r0,{r3,r4,r5,r6,r7}	@ load context
+	mov	r12,sp
+
+	vld1.8	{q0,q1},[r1]!	@ handles unaligned
+	veor	q15,q15,q15
+	vld1.8	{q2,q3},[r1]!
+	vld1.32	{d28[],d29[]},[r8,:32]!	@ load K_00_19
+	vrev32.8	q0,q0		@ yes, even on
+	vrev32.8	q1,q1		@ big-endian...
+	vrev32.8	q2,q2
+	vadd.i32	q8,q0,q14
+	vrev32.8	q3,q3
+	vadd.i32	q9,q1,q14
+	vst1.32	{q8},[r12,:128]!
+	vadd.i32	q10,q2,q14
+	vst1.32	{q9},[r12,:128]!
+	vst1.32	{q10},[r12,:128]!
+	ldr	r9,[sp]			@ big RAW stall
+
+Loop_neon:
+	vext.8	q8,q0,q1,#8
+	bic	r10,r6,r4
+	add	r7,r7,r9
+	and	r11,r5,r4
+	vadd.i32	q13,q3,q14
+	ldr	r9,[sp,#4]
+	add	r7,r7,r3,ror#27
+	vext.8	q12,q3,q15,#4
+	eor	r11,r11,r10
+	mov	r4,r4,ror#2
+	add	r7,r7,r11
+	veor	q8,q8,q0
+	bic	r10,r5,r3
+	add	r6,r6,r9
+	veor	q12,q12,q2
+	and	r11,r4,r3
+	ldr	r9,[sp,#8]
+	veor	q12,q12,q8
+	add	r6,r6,r7,ror#27
+	eor	r11,r11,r10
+	vst1.32	{q13},[r12,:128]!
+	sub	r12,r12,#64
+	mov	r3,r3,ror#2
+	add	r6,r6,r11
+	vext.8	q13,q15,q12,#4
+	bic	r10,r4,r7
+	add	r5,r5,r9
+	vadd.i32	q8,q12,q12
+	and	r11,r3,r7
+	ldr	r9,[sp,#12]
+	vsri.32	q8,q12,#31
+	add	r5,r5,r6,ror#27
+	eor	r11,r11,r10
+	mov	r7,r7,ror#2
+	vshr.u32	q12,q13,#30
+	add	r5,r5,r11
+	bic	r10,r3,r6
+	vshl.u32	q13,q13,#2
+	add	r4,r4,r9
+	and	r11,r7,r6
+	veor	q8,q8,q12
+	ldr	r9,[sp,#16]
+	add	r4,r4,r5,ror#27
+	veor	q8,q8,q13
+	eor	r11,r11,r10
+	mov	r6,r6,ror#2
+	add	r4,r4,r11
+	vext.8	q9,q1,q2,#8
+	bic	r10,r7,r5
+	add	r3,r3,r9
+	and	r11,r6,r5
+	vadd.i32	q13,q8,q14
+	ldr	r9,[sp,#20]
+	vld1.32	{d28[],d29[]},[r8,:32]!
+	add	r3,r3,r4,ror#27
+	vext.8	q12,q8,q15,#4
+	eor	r11,r11,r10
+	mov	r5,r5,ror#2
+	add	r3,r3,r11
+	veor	q9,q9,q1
+	bic	r10,r6,r4
+	add	r7,r7,r9
+	veor	q12,q12,q3
+	and	r11,r5,r4
+	ldr	r9,[sp,#24]
+	veor	q12,q12,q9
+	add	r7,r7,r3,ror#27
+	eor	r11,r11,r10
+	vst1.32	{q13},[r12,:128]!
+	mov	r4,r4,ror#2
+	add	r7,r7,r11
+	vext.8	q13,q15,q12,#4
+	bic	r10,r5,r3
+	add	r6,r6,r9
+	vadd.i32	q9,q12,q12
+	and	r11,r4,r3
+	ldr	r9,[sp,#28]
+	vsri.32	q9,q12,#31
+	add	r6,r6,r7,ror#27
+	eor	r11,r11,r10
+	mov	r3,r3,ror#2
+	vshr.u32	q12,q13,#30
+	add	r6,r6,r11
+	bic	r10,r4,r7
+	vshl.u32	q13,q13,#2
+	add	r5,r5,r9
+	and	r11,r3,r7
+	veor	q9,q9,q12
+	ldr	r9,[sp,#32]
+	add	r5,r5,r6,ror#27
+	veor	q9,q9,q13
+	eor	r11,r11,r10
+	mov	r7,r7,ror#2
+	add	r5,r5,r11
+	vext.8	q10,q2,q3,#8
+	bic	r10,r3,r6
+	add	r4,r4,r9
+	and	r11,r7,r6
+	vadd.i32	q13,q9,q14
+	ldr	r9,[sp,#36]
+	add	r4,r4,r5,ror#27
+	vext.8	q12,q9,q15,#4
+	eor	r11,r11,r10
+	mov	r6,r6,ror#2
+	add	r4,r4,r11
+	veor	q10,q10,q2
+	bic	r10,r7,r5
+	add	r3,r3,r9
+	veor	q12,q12,q8
+	and	r11,r6,r5
+	ldr	r9,[sp,#40]
+	veor	q12,q12,q10
+	add	r3,r3,r4,ror#27
+	eor	r11,r11,r10
+	vst1.32	{q13},[r12,:128]!
+	mov	r5,r5,ror#2
+	add	r3,r3,r11
+	vext.8	q13,q15,q12,#4
+	bic	r10,r6,r4
+	add	r7,r7,r9
+	vadd.i32	q10,q12,q12
+	and	r11,r5,r4
+	ldr	r9,[sp,#44]
+	vsri.32	q10,q12,#31
+	add	r7,r7,r3,ror#27
+	eor	r11,r11,r10
+	mov	r4,r4,ror#2
+	vshr.u32	q12,q13,#30
+	add	r7,r7,r11
+	bic	r10,r5,r3
+	vshl.u32	q13,q13,#2
+	add	r6,r6,r9
+	and	r11,r4,r3
+	veor	q10,q10,q12
+	ldr	r9,[sp,#48]
+	add	r6,r6,r7,ror#27
+	veor	q10,q10,q13
+	eor	r11,r11,r10
+	mov	r3,r3,ror#2
+	add	r6,r6,r11
+	vext.8	q11,q3,q8,#8
+	bic	r10,r4,r7
+	add	r5,r5,r9
+	and	r11,r3,r7
+	vadd.i32	q13,q10,q14
+	ldr	r9,[sp,#52]
+	add	r5,r5,r6,ror#27
+	vext.8	q12,q10,q15,#4
+	eor	r11,r11,r10
+	mov	r7,r7,ror#2
+	add	r5,r5,r11
+	veor	q11,q11,q3
+	bic	r10,r3,r6
+	add	r4,r4,r9
+	veor	q12,q12,q9
+	and	r11,r7,r6
+	ldr	r9,[sp,#56]
+	veor	q12,q12,q11
+	add	r4,r4,r5,ror#27
+	eor	r11,r11,r10
+	vst1.32	{q13},[r12,:128]!
+	mov	r6,r6,ror#2
+	add	r4,r4,r11
+	vext.8	q13,q15,q12,#4
+	bic	r10,r7,r5
+	add	r3,r3,r9
+	vadd.i32	q11,q12,q12
+	and	r11,r6,r5
+	ldr	r9,[sp,#60]
+	vsri.32	q11,q12,#31
+	add	r3,r3,r4,ror#27
+	eor	r11,r11,r10
+	mov	r5,r5,ror#2
+	vshr.u32	q12,q13,#30
+	add	r3,r3,r11
+	bic	r10,r6,r4
+	vshl.u32	q13,q13,#2
+	add	r7,r7,r9
+	and	r11,r5,r4
+	veor	q11,q11,q12
+	ldr	r9,[sp,#0]
+	add	r7,r7,r3,ror#27
+	veor	q11,q11,q13
+	eor	r11,r11,r10
+	mov	r4,r4,ror#2
+	add	r7,r7,r11
+	vext.8	q12,q10,q11,#8
+	bic	r10,r5,r3
+	add	r6,r6,r9
+	and	r11,r4,r3
+	veor	q0,q0,q8
+	ldr	r9,[sp,#4]
+	add	r6,r6,r7,ror#27
+	veor	q0,q0,q1
+	eor	r11,r11,r10
+	mov	r3,r3,ror#2
+	vadd.i32	q13,q11,q14
+	add	r6,r6,r11
+	bic	r10,r4,r7
+	veor	q12,q12,q0
+	add	r5,r5,r9
+	and	r11,r3,r7
+	vshr.u32	q0,q12,#30
+	ldr	r9,[sp,#8]
+	add	r5,r5,r6,ror#27
+	vst1.32	{q13},[r12,:128]!
+	sub	r12,r12,#64
+	eor	r11,r11,r10
+	mov	r7,r7,ror#2
+	vsli.32	q0,q12,#2
+	add	r5,r5,r11
+	bic	r10,r3,r6
+	add	r4,r4,r9
+	and	r11,r7,r6
+	ldr	r9,[sp,#12]
+	add	r4,r4,r5,ror#27
+	eor	r11,r11,r10
+	mov	r6,r6,ror#2
+	add	r4,r4,r11
+	bic	r10,r7,r5
+	add	r3,r3,r9
+	and	r11,r6,r5
+	ldr	r9,[sp,#16]
+	add	r3,r3,r4,ror#27
+	eor	r11,r11,r10
+	mov	r5,r5,ror#2
+	add	r3,r3,r11
+	vext.8	q12,q11,q0,#8
+	eor	r10,r4,r6
+	add	r7,r7,r9
+	ldr	r9,[sp,#20]
+	veor	q1,q1,q9
+	eor	r11,r10,r5
+	add	r7,r7,r3,ror#27
+	veor	q1,q1,q2
+	mov	r4,r4,ror#2
+	add	r7,r7,r11
+	vadd.i32	q13,q0,q14
+	eor	r10,r3,r5
+	add	r6,r6,r9
+	veor	q12,q12,q1
+	ldr	r9,[sp,#24]
+	eor	r11,r10,r4
+	vshr.u32	q1,q12,#30
+	add	r6,r6,r7,ror#27
+	mov	r3,r3,ror#2
+	vst1.32	{q13},[r12,:128]!
+	add	r6,r6,r11
+	eor	r10,r7,r4
+	vsli.32	q1,q12,#2
+	add	r5,r5,r9
+	ldr	r9,[sp,#28]
+	eor	r11,r10,r3
+	add	r5,r5,r6,ror#27
+	mov	r7,r7,ror#2
+	add	r5,r5,r11
+	eor	r10,r6,r3
+	add	r4,r4,r9
+	ldr	r9,[sp,#32]
+	eor	r11,r10,r7
+	add	r4,r4,r5,ror#27
+	mov	r6,r6,ror#2
+	add	r4,r4,r11
+	vext.8	q12,q0,q1,#8
+	eor	r10,r5,r7
+	add	r3,r3,r9
+	ldr	r9,[sp,#36]
+	veor	q2,q2,q10
+	eor	r11,r10,r6
+	add	r3,r3,r4,ror#27
+	veor	q2,q2,q3
+	mov	r5,r5,ror#2
+	add	r3,r3,r11
+	vadd.i32	q13,q1,q14
+	eor	r10,r4,r6
+	vld1.32	{d28[],d29[]},[r8,:32]!
+	add	r7,r7,r9
+	veor	q12,q12,q2
+	ldr	r9,[sp,#40]
+	eor	r11,r10,r5
+	vshr.u32	q2,q12,#30
+	add	r7,r7,r3,ror#27
+	mov	r4,r4,ror#2
+	vst1.32	{q13},[r12,:128]!
+	add	r7,r7,r11
+	eor	r10,r3,r5
+	vsli.32	q2,q12,#2
+	add	r6,r6,r9
+	ldr	r9,[sp,#44]
+	eor	r11,r10,r4
+	add	r6,r6,r7,ror#27
+	mov	r3,r3,ror#2
+	add	r6,r6,r11
+	eor	r10,r7,r4
+	add	r5,r5,r9
+	ldr	r9,[sp,#48]
+	eor	r11,r10,r3
+	add	r5,r5,r6,ror#27
+	mov	r7,r7,ror#2
+	add	r5,r5,r11
+	vext.8	q12,q1,q2,#8
+	eor	r10,r6,r3
+	add	r4,r4,r9
+	ldr	r9,[sp,#52]
+	veor	q3,q3,q11
+	eor	r11,r10,r7
+	add	r4,r4,r5,ror#27
+	veor	q3,q3,q8
+	mov	r6,r6,ror#2
+	add	r4,r4,r11
+	vadd.i32	q13,q2,q14
+	eor	r10,r5,r7
+	add	r3,r3,r9
+	veor	q12,q12,q3
+	ldr	r9,[sp,#56]
+	eor	r11,r10,r6
+	vshr.u32	q3,q12,#30
+	add	r3,r3,r4,ror#27
+	mov	r5,r5,ror#2
+	vst1.32	{q13},[r12,:128]!
+	add	r3,r3,r11
+	eor	r10,r4,r6
+	vsli.32	q3,q12,#2
+	add	r7,r7,r9
+	ldr	r9,[sp,#60]
+	eor	r11,r10,r5
+	add	r7,r7,r3,ror#27
+	mov	r4,r4,ror#2
+	add	r7,r7,r11
+	eor	r10,r3,r5
+	add	r6,r6,r9
+	ldr	r9,[sp,#0]
+	eor	r11,r10,r4
+	add	r6,r6,r7,ror#27
+	mov	r3,r3,ror#2
+	add	r6,r6,r11
+	vext.8	q12,q2,q3,#8
+	eor	r10,r7,r4
+	add	r5,r5,r9
+	ldr	r9,[sp,#4]
+	veor	q8,q8,q0
+	eor	r11,r10,r3
+	add	r5,r5,r6,ror#27
+	veor	q8,q8,q9
+	mov	r7,r7,ror#2
+	add	r5,r5,r11
+	vadd.i32	q13,q3,q14
+	eor	r10,r6,r3
+	add	r4,r4,r9
+	veor	q12,q12,q8
+	ldr	r9,[sp,#8]
+	eor	r11,r10,r7
+	vshr.u32	q8,q12,#30
+	add	r4,r4,r5,ror#27
+	mov	r6,r6,ror#2
+	vst1.32	{q13},[r12,:128]!
+	sub	r12,r12,#64
+	add	r4,r4,r11
+	eor	r10,r5,r7
+	vsli.32	q8,q12,#2
+	add	r3,r3,r9
+	ldr	r9,[sp,#12]
+	eor	r11,r10,r6
+	add	r3,r3,r4,ror#27
+	mov	r5,r5,ror#2
+	add	r3,r3,r11
+	eor	r10,r4,r6
+	add	r7,r7,r9
+	ldr	r9,[sp,#16]
+	eor	r11,r10,r5
+	add	r7,r7,r3,ror#27
+	mov	r4,r4,ror#2
+	add	r7,r7,r11
+	vext.8	q12,q3,q8,#8
+	eor	r10,r3,r5
+	add	r6,r6,r9
+	ldr	r9,[sp,#20]
+	veor	q9,q9,q1
+	eor	r11,r10,r4
+	add	r6,r6,r7,ror#27
+	veor	q9,q9,q10
+	mov	r3,r3,ror#2
+	add	r6,r6,r11
+	vadd.i32	q13,q8,q14
+	eor	r10,r7,r4
+	add	r5,r5,r9
+	veor	q12,q12,q9
+	ldr	r9,[sp,#24]
+	eor	r11,r10,r3
+	vshr.u32	q9,q12,#30
+	add	r5,r5,r6,ror#27
+	mov	r7,r7,ror#2
+	vst1.32	{q13},[r12,:128]!
+	add	r5,r5,r11
+	eor	r10,r6,r3
+	vsli.32	q9,q12,#2
+	add	r4,r4,r9
+	ldr	r9,[sp,#28]
+	eor	r11,r10,r7
+	add	r4,r4,r5,ror#27
+	mov	r6,r6,ror#2
+	add	r4,r4,r11
+	eor	r10,r5,r7
+	add	r3,r3,r9
+	ldr	r9,[sp,#32]
+	eor	r11,r10,r6
+	add	r3,r3,r4,ror#27
+	mov	r5,r5,ror#2
+	add	r3,r3,r11
+	vext.8	q12,q8,q9,#8
+	add	r7,r7,r9
+	and	r10,r5,r6
+	ldr	r9,[sp,#36]
+	veor	q10,q10,q2
+	add	r7,r7,r3,ror#27
+	eor	r11,r5,r6
+	veor	q10,q10,q11
+	add	r7,r7,r10
+	and	r11,r11,r4
+	vadd.i32	q13,q9,q14
+	mov	r4,r4,ror#2
+	add	r7,r7,r11
+	veor	q12,q12,q10
+	add	r6,r6,r9
+	and	r10,r4,r5
+	vshr.u32	q10,q12,#30
+	ldr	r9,[sp,#40]
+	add	r6,r6,r7,ror#27
+	vst1.32	{q13},[r12,:128]!
+	eor	r11,r4,r5
+	add	r6,r6,r10
+	vsli.32	q10,q12,#2
+	and	r11,r11,r3
+	mov	r3,r3,ror#2
+	add	r6,r6,r11
+	add	r5,r5,r9
+	and	r10,r3,r4
+	ldr	r9,[sp,#44]
+	add	r5,r5,r6,ror#27
+	eor	r11,r3,r4
+	add	r5,r5,r10
+	and	r11,r11,r7
+	mov	r7,r7,ror#2
+	add	r5,r5,r11
+	add	r4,r4,r9
+	and	r10,r7,r3
+	ldr	r9,[sp,#48]
+	add	r4,r4,r5,ror#27
+	eor	r11,r7,r3
+	add	r4,r4,r10
+	and	r11,r11,r6
+	mov	r6,r6,ror#2
+	add	r4,r4,r11
+	vext.8	q12,q9,q10,#8
+	add	r3,r3,r9
+	and	r10,r6,r7
+	ldr	r9,[sp,#52]
+	veor	q11,q11,q3
+	add	r3,r3,r4,ror#27
+	eor	r11,r6,r7
+	veor	q11,q11,q0
+	add	r3,r3,r10
+	and	r11,r11,r5
+	vadd.i32	q13,q10,q14
+	mov	r5,r5,ror#2
+	vld1.32	{d28[],d29[]},[r8,:32]!
+	add	r3,r3,r11
+	veor	q12,q12,q11
+	add	r7,r7,r9
+	and	r10,r5,r6
+	vshr.u32	q11,q12,#30
+	ldr	r9,[sp,#56]
+	add	r7,r7,r3,ror#27
+	vst1.32	{q13},[r12,:128]!
+	eor	r11,r5,r6
+	add	r7,r7,r10
+	vsli.32	q11,q12,#2
+	and	r11,r11,r4
+	mov	r4,r4,ror#2
+	add	r7,r7,r11
+	add	r6,r6,r9
+	and	r10,r4,r5
+	ldr	r9,[sp,#60]
+	add	r6,r6,r7,ror#27
+	eor	r11,r4,r5
+	add	r6,r6,r10
+	and	r11,r11,r3
+	mov	r3,r3,ror#2
+	add	r6,r6,r11
+	add	r5,r5,r9
+	and	r10,r3,r4
+	ldr	r9,[sp,#0]
+	add	r5,r5,r6,ror#27
+	eor	r11,r3,r4
+	add	r5,r5,r10
+	and	r11,r11,r7
+	mov	r7,r7,ror#2
+	add	r5,r5,r11
+	vext.8	q12,q10,q11,#8
+	add	r4,r4,r9
+	and	r10,r7,r3
+	ldr	r9,[sp,#4]
+	veor	q0,q0,q8
+	add	r4,r4,r5,ror#27
+	eor	r11,r7,r3
+	veor	q0,q0,q1
+	add	r4,r4,r10
+	and	r11,r11,r6
+	vadd.i32	q13,q11,q14
+	mov	r6,r6,ror#2
+	add	r4,r4,r11
+	veor	q12,q12,q0
+	add	r3,r3,r9
+	and	r10,r6,r7
+	vshr.u32	q0,q12,#30
+	ldr	r9,[sp,#8]
+	add	r3,r3,r4,ror#27
+	vst1.32	{q13},[r12,:128]!
+	sub	r12,r12,#64
+	eor	r11,r6,r7
+	add	r3,r3,r10
+	vsli.32	q0,q12,#2
+	and	r11,r11,r5
+	mov	r5,r5,ror#2
+	add	r3,r3,r11
+	add	r7,r7,r9
+	and	r10,r5,r6
+	ldr	r9,[sp,#12]
+	add	r7,r7,r3,ror#27
+	eor	r11,r5,r6
+	add	r7,r7,r10
+	and	r11,r11,r4
+	mov	r4,r4,ror#2
+	add	r7,r7,r11
+	add	r6,r6,r9
+	and	r10,r4,r5
+	ldr	r9,[sp,#16]
+	add	r6,r6,r7,ror#27
+	eor	r11,r4,r5
+	add	r6,r6,r10
+	and	r11,r11,r3
+	mov	r3,r3,ror#2
+	add	r6,r6,r11
+	vext.8	q12,q11,q0,#8
+	add	r5,r5,r9
+	and	r10,r3,r4
+	ldr	r9,[sp,#20]
+	veor	q1,q1,q9
+	add	r5,r5,r6,ror#27
+	eor	r11,r3,r4
+	veor	q1,q1,q2
+	add	r5,r5,r10
+	and	r11,r11,r7
+	vadd.i32	q13,q0,q14
+	mov	r7,r7,ror#2
+	add	r5,r5,r11
+	veor	q12,q12,q1
+	add	r4,r4,r9
+	and	r10,r7,r3
+	vshr.u32	q1,q12,#30
+	ldr	r9,[sp,#24]
+	add	r4,r4,r5,ror#27
+	vst1.32	{q13},[r12,:128]!
+	eor	r11,r7,r3
+	add	r4,r4,r10
+	vsli.32	q1,q12,#2
+	and	r11,r11,r6
+	mov	r6,r6,ror#2
+	add	r4,r4,r11
+	add	r3,r3,r9
+	and	r10,r6,r7
+	ldr	r9,[sp,#28]
+	add	r3,r3,r4,ror#27
+	eor	r11,r6,r7
+	add	r3,r3,r10
+	and	r11,r11,r5
+	mov	r5,r5,ror#2
+	add	r3,r3,r11
+	add	r7,r7,r9
+	and	r10,r5,r6
+	ldr	r9,[sp,#32]
+	add	r7,r7,r3,ror#27
+	eor	r11,r5,r6
+	add	r7,r7,r10
+	and	r11,r11,r4
+	mov	r4,r4,ror#2
+	add	r7,r7,r11
+	vext.8	q12,q0,q1,#8
+	add	r6,r6,r9
+	and	r10,r4,r5
+	ldr	r9,[sp,#36]
+	veor	q2,q2,q10
+	add	r6,r6,r7,ror#27
+	eor	r11,r4,r5
+	veor	q2,q2,q3
+	add	r6,r6,r10
+	and	r11,r11,r3
+	vadd.i32	q13,q1,q14
+	mov	r3,r3,ror#2
+	add	r6,r6,r11
+	veor	q12,q12,q2
+	add	r5,r5,r9
+	and	r10,r3,r4
+	vshr.u32	q2,q12,#30
+	ldr	r9,[sp,#40]
+	add	r5,r5,r6,ror#27
+	vst1.32	{q13},[r12,:128]!
+	eor	r11,r3,r4
+	add	r5,r5,r10
+	vsli.32	q2,q12,#2
+	and	r11,r11,r7
+	mov	r7,r7,ror#2
+	add	r5,r5,r11
+	add	r4,r4,r9
+	and	r10,r7,r3
+	ldr	r9,[sp,#44]
+	add	r4,r4,r5,ror#27
+	eor	r11,r7,r3
+	add	r4,r4,r10
+	and	r11,r11,r6
+	mov	r6,r6,ror#2
+	add	r4,r4,r11
+	add	r3,r3,r9
+	and	r10,r6,r7
+	ldr	r9,[sp,#48]
+	add	r3,r3,r4,ror#27
+	eor	r11,r6,r7
+	add	r3,r3,r10
+	and	r11,r11,r5
+	mov	r5,r5,ror#2
+	add	r3,r3,r11
+	vext.8	q12,q1,q2,#8
+	eor	r10,r4,r6
+	add	r7,r7,r9
+	ldr	r9,[sp,#52]
+	veor	q3,q3,q11
+	eor	r11,r10,r5
+	add	r7,r7,r3,ror#27
+	veor	q3,q3,q8
+	mov	r4,r4,ror#2
+	add	r7,r7,r11
+	vadd.i32	q13,q2,q14
+	eor	r10,r3,r5
+	add	r6,r6,r9
+	veor	q12,q12,q3
+	ldr	r9,[sp,#56]
+	eor	r11,r10,r4
+	vshr.u32	q3,q12,#30
+	add	r6,r6,r7,ror#27
+	mov	r3,r3,ror#2
+	vst1.32	{q13},[r12,:128]!
+	add	r6,r6,r11
+	eor	r10,r7,r4
+	vsli.32	q3,q12,#2
+	add	r5,r5,r9
+	ldr	r9,[sp,#60]
+	eor	r11,r10,r3
+	add	r5,r5,r6,ror#27
+	mov	r7,r7,ror#2
+	add	r5,r5,r11
+	eor	r10,r6,r3
+	add	r4,r4,r9
+	ldr	r9,[sp,#0]
+	eor	r11,r10,r7
+	add	r4,r4,r5,ror#27
+	mov	r6,r6,ror#2
+	add	r4,r4,r11
+	vadd.i32	q13,q3,q14
+	eor	r10,r5,r7
+	add	r3,r3,r9
+	vst1.32	{q13},[r12,:128]!
+	sub	r12,r12,#64
+	teq	r1,r2
+	sub	r8,r8,#16
+	subeq	r1,r1,#64
+	vld1.8	{q0,q1},[r1]!
+	ldr	r9,[sp,#4]
+	eor	r11,r10,r6
+	vld1.8	{q2,q3},[r1]!
+	add	r3,r3,r4,ror#27
+	mov	r5,r5,ror#2
+	vld1.32	{d28[],d29[]},[r8,:32]!
+	add	r3,r3,r11
+	eor	r10,r4,r6
+	vrev32.8	q0,q0
+	add	r7,r7,r9
+	ldr	r9,[sp,#8]
+	eor	r11,r10,r5
+	add	r7,r7,r3,ror#27
+	mov	r4,r4,ror#2
+	add	r7,r7,r11
+	eor	r10,r3,r5
+	add	r6,r6,r9
+	ldr	r9,[sp,#12]
+	eor	r11,r10,r4
+	add	r6,r6,r7,ror#27
+	mov	r3,r3,ror#2
+	add	r6,r6,r11
+	eor	r10,r7,r4
+	add	r5,r5,r9
+	ldr	r9,[sp,#16]
+	eor	r11,r10,r3
+	add	r5,r5,r6,ror#27
+	mov	r7,r7,ror#2
+	add	r5,r5,r11
+	vrev32.8	q1,q1
+	eor	r10,r6,r3
+	add	r4,r4,r9
+	vadd.i32	q8,q0,q14
+	ldr	r9,[sp,#20]
+	eor	r11,r10,r7
+	vst1.32	{q8},[r12,:128]!
+	add	r4,r4,r5,ror#27
+	mov	r6,r6,ror#2
+	add	r4,r4,r11
+	eor	r10,r5,r7
+	add	r3,r3,r9
+	ldr	r9,[sp,#24]
+	eor	r11,r10,r6
+	add	r3,r3,r4,ror#27
+	mov	r5,r5,ror#2
+	add	r3,r3,r11
+	eor	r10,r4,r6
+	add	r7,r7,r9
+	ldr	r9,[sp,#28]
+	eor	r11,r10,r5
+	add	r7,r7,r3,ror#27
+	mov	r4,r4,ror#2
+	add	r7,r7,r11
+	eor	r10,r3,r5
+	add	r6,r6,r9
+	ldr	r9,[sp,#32]
+	eor	r11,r10,r4
+	add	r6,r6,r7,ror#27
+	mov	r3,r3,ror#2
+	add	r6,r6,r11
+	vrev32.8	q2,q2
+	eor	r10,r7,r4
+	add	r5,r5,r9
+	vadd.i32	q9,q1,q14
+	ldr	r9,[sp,#36]
+	eor	r11,r10,r3
+	vst1.32	{q9},[r12,:128]!
+	add	r5,r5,r6,ror#27
+	mov	r7,r7,ror#2
+	add	r5,r5,r11
+	eor	r10,r6,r3
+	add	r4,r4,r9
+	ldr	r9,[sp,#40]
+	eor	r11,r10,r7
+	add	r4,r4,r5,ror#27
+	mov	r6,r6,ror#2
+	add	r4,r4,r11
+	eor	r10,r5,r7
+	add	r3,r3,r9
+	ldr	r9,[sp,#44]
+	eor	r11,r10,r6
+	add	r3,r3,r4,ror#27
+	mov	r5,r5,ror#2
+	add	r3,r3,r11
+	eor	r10,r4,r6
+	add	r7,r7,r9
+	ldr	r9,[sp,#48]
+	eor	r11,r10,r5
+	add	r7,r7,r3,ror#27
+	mov	r4,r4,ror#2
+	add	r7,r7,r11
+	vrev32.8	q3,q3
+	eor	r10,r3,r5
+	add	r6,r6,r9
+	vadd.i32	q10,q2,q14
+	ldr	r9,[sp,#52]
+	eor	r11,r10,r4
+	vst1.32	{q10},[r12,:128]!
+	add	r6,r6,r7,ror#27
+	mov	r3,r3,ror#2
+	add	r6,r6,r11
+	eor	r10,r7,r4
+	add	r5,r5,r9
+	ldr	r9,[sp,#56]
+	eor	r11,r10,r3
+	add	r5,r5,r6,ror#27
+	mov	r7,r7,ror#2
+	add	r5,r5,r11
+	eor	r10,r6,r3
+	add	r4,r4,r9
+	ldr	r9,[sp,#60]
+	eor	r11,r10,r7
+	add	r4,r4,r5,ror#27
+	mov	r6,r6,ror#2
+	add	r4,r4,r11
+	eor	r10,r5,r7
+	add	r3,r3,r9
+	eor	r11,r10,r6
+	add	r3,r3,r4,ror#27
+	mov	r5,r5,ror#2
+	add	r3,r3,r11
+	ldmia	r0,{r9,r10,r11,r12}	@ accumulate context
+	add	r3,r3,r9
+	ldr	r9,[r0,#16]
+	add	r4,r4,r10
+	add	r5,r5,r11
+	add	r6,r6,r12
+	moveq	sp,r14
+	add	r7,r7,r9
+	ldrne	r9,[sp]
+	stmia	r0,{r3,r4,r5,r6,r7}
+	addne	r12,sp,#3*16
+	bne	Loop_neon
+
+	@ vldmia	sp!,{d8-d15}
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
+
+#endif
+#if __ARM_MAX_ARCH__>=7
+
+.align	5
+sha1_block_data_order_armv8:
+LARMv8:
+	vstmdb	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}		@ ABI specification says so
+
+	veor	q1,q1,q1
+	adr	r3,LK_00_19
+	vld1.32	{q0},[r0]!
+	vld1.32	{d2[0]},[r0]
+	sub	r0,r0,#16
+	vld1.32	{d16[],d17[]},[r3,:32]!
+	vld1.32	{d18[],d19[]},[r3,:32]!
+	vld1.32	{d20[],d21[]},[r3,:32]!
+	vld1.32	{d22[],d23[]},[r3,:32]
+
+Loop_v8:
+	vld1.8	{q4,q5},[r1]!
+	vld1.8	{q6,q7},[r1]!
+	vrev32.8	q4,q4
+	vrev32.8	q5,q5
+
+	vadd.i32	q12,q8,q4
+	vrev32.8	q6,q6
+	vmov	q14,q0	@ offload
+	subs	r2,r2,#1
+
+	vadd.i32	q13,q8,q5
+	vrev32.8	q7,q7
+.byte	0xc0,0x62,0xb9,0xf3	@ sha1h q3,q0		@ 0
+.byte	0x68,0x0c,0x02,0xf2	@ sha1c q0,q1,q12
+	vadd.i32	q12,q8,q6
+.byte	0x4c,0x8c,0x3a,0xf2	@ sha1su0 q4,q5,q6
+.byte	0xc0,0x42,0xb9,0xf3	@ sha1h q2,q0		@ 1
+.byte	0x6a,0x0c,0x06,0xf2	@ sha1c q0,q3,q13
+	vadd.i32	q13,q8,q7
+.byte	0x8e,0x83,0xba,0xf3	@ sha1su1 q4,q7
+.byte	0x4e,0xac,0x3c,0xf2	@ sha1su0 q5,q6,q7
+.byte	0xc0,0x62,0xb9,0xf3	@ sha1h q3,q0		@ 2
+.byte	0x68,0x0c,0x04,0xf2	@ sha1c q0,q2,q12
+	vadd.i32	q12,q8,q4
+.byte	0x88,0xa3,0xba,0xf3	@ sha1su1 q5,q4
+.byte	0x48,0xcc,0x3e,0xf2	@ sha1su0 q6,q7,q4
+.byte	0xc0,0x42,0xb9,0xf3	@ sha1h q2,q0		@ 3
+.byte	0x6a,0x0c,0x06,0xf2	@ sha1c q0,q3,q13
+	vadd.i32	q13,q9,q5
+.byte	0x8a,0xc3,0xba,0xf3	@ sha1su1 q6,q5
+.byte	0x4a,0xec,0x38,0xf2	@ sha1su0 q7,q4,q5
+.byte	0xc0,0x62,0xb9,0xf3	@ sha1h q3,q0		@ 4
+.byte	0x68,0x0c,0x04,0xf2	@ sha1c q0,q2,q12
+	vadd.i32	q12,q9,q6
+.byte	0x8c,0xe3,0xba,0xf3	@ sha1su1 q7,q6
+.byte	0x4c,0x8c,0x3a,0xf2	@ sha1su0 q4,q5,q6
+.byte	0xc0,0x42,0xb9,0xf3	@ sha1h q2,q0		@ 5
+.byte	0x6a,0x0c,0x16,0xf2	@ sha1p q0,q3,q13
+	vadd.i32	q13,q9,q7
+.byte	0x8e,0x83,0xba,0xf3	@ sha1su1 q4,q7
+.byte	0x4e,0xac,0x3c,0xf2	@ sha1su0 q5,q6,q7
+.byte	0xc0,0x62,0xb9,0xf3	@ sha1h q3,q0		@ 6
+.byte	0x68,0x0c,0x14,0xf2	@ sha1p q0,q2,q12
+	vadd.i32	q12,q9,q4
+.byte	0x88,0xa3,0xba,0xf3	@ sha1su1 q5,q4
+.byte	0x48,0xcc,0x3e,0xf2	@ sha1su0 q6,q7,q4
+.byte	0xc0,0x42,0xb9,0xf3	@ sha1h q2,q0		@ 7
+.byte	0x6a,0x0c,0x16,0xf2	@ sha1p q0,q3,q13
+	vadd.i32	q13,q9,q5
+.byte	0x8a,0xc3,0xba,0xf3	@ sha1su1 q6,q5
+.byte	0x4a,0xec,0x38,0xf2	@ sha1su0 q7,q4,q5
+.byte	0xc0,0x62,0xb9,0xf3	@ sha1h q3,q0		@ 8
+.byte	0x68,0x0c,0x14,0xf2	@ sha1p q0,q2,q12
+	vadd.i32	q12,q10,q6
+.byte	0x8c,0xe3,0xba,0xf3	@ sha1su1 q7,q6
+.byte	0x4c,0x8c,0x3a,0xf2	@ sha1su0 q4,q5,q6
+.byte	0xc0,0x42,0xb9,0xf3	@ sha1h q2,q0		@ 9
+.byte	0x6a,0x0c,0x16,0xf2	@ sha1p q0,q3,q13
+	vadd.i32	q13,q10,q7
+.byte	0x8e,0x83,0xba,0xf3	@ sha1su1 q4,q7
+.byte	0x4e,0xac,0x3c,0xf2	@ sha1su0 q5,q6,q7
+.byte	0xc0,0x62,0xb9,0xf3	@ sha1h q3,q0		@ 10
+.byte	0x68,0x0c,0x24,0xf2	@ sha1m q0,q2,q12
+	vadd.i32	q12,q10,q4
+.byte	0x88,0xa3,0xba,0xf3	@ sha1su1 q5,q4
+.byte	0x48,0xcc,0x3e,0xf2	@ sha1su0 q6,q7,q4
+.byte	0xc0,0x42,0xb9,0xf3	@ sha1h q2,q0		@ 11
+.byte	0x6a,0x0c,0x26,0xf2	@ sha1m q0,q3,q13
+	vadd.i32	q13,q10,q5
+.byte	0x8a,0xc3,0xba,0xf3	@ sha1su1 q6,q5
+.byte	0x4a,0xec,0x38,0xf2	@ sha1su0 q7,q4,q5
+.byte	0xc0,0x62,0xb9,0xf3	@ sha1h q3,q0		@ 12
+.byte	0x68,0x0c,0x24,0xf2	@ sha1m q0,q2,q12
+	vadd.i32	q12,q10,q6
+.byte	0x8c,0xe3,0xba,0xf3	@ sha1su1 q7,q6
+.byte	0x4c,0x8c,0x3a,0xf2	@ sha1su0 q4,q5,q6
+.byte	0xc0,0x42,0xb9,0xf3	@ sha1h q2,q0		@ 13
+.byte	0x6a,0x0c,0x26,0xf2	@ sha1m q0,q3,q13
+	vadd.i32	q13,q11,q7
+.byte	0x8e,0x83,0xba,0xf3	@ sha1su1 q4,q7
+.byte	0x4e,0xac,0x3c,0xf2	@ sha1su0 q5,q6,q7
+.byte	0xc0,0x62,0xb9,0xf3	@ sha1h q3,q0		@ 14
+.byte	0x68,0x0c,0x24,0xf2	@ sha1m q0,q2,q12
+	vadd.i32	q12,q11,q4
+.byte	0x88,0xa3,0xba,0xf3	@ sha1su1 q5,q4
+.byte	0x48,0xcc,0x3e,0xf2	@ sha1su0 q6,q7,q4
+.byte	0xc0,0x42,0xb9,0xf3	@ sha1h q2,q0		@ 15
+.byte	0x6a,0x0c,0x16,0xf2	@ sha1p q0,q3,q13
+	vadd.i32	q13,q11,q5
+.byte	0x8a,0xc3,0xba,0xf3	@ sha1su1 q6,q5
+.byte	0x4a,0xec,0x38,0xf2	@ sha1su0 q7,q4,q5
+.byte	0xc0,0x62,0xb9,0xf3	@ sha1h q3,q0		@ 16
+.byte	0x68,0x0c,0x14,0xf2	@ sha1p q0,q2,q12
+	vadd.i32	q12,q11,q6
+.byte	0x8c,0xe3,0xba,0xf3	@ sha1su1 q7,q6
+.byte	0xc0,0x42,0xb9,0xf3	@ sha1h q2,q0		@ 17
+.byte	0x6a,0x0c,0x16,0xf2	@ sha1p q0,q3,q13
+	vadd.i32	q13,q11,q7
+
+.byte	0xc0,0x62,0xb9,0xf3	@ sha1h q3,q0		@ 18
+.byte	0x68,0x0c,0x14,0xf2	@ sha1p q0,q2,q12
+
+.byte	0xc0,0x42,0xb9,0xf3	@ sha1h q2,q0		@ 19
+.byte	0x6a,0x0c,0x16,0xf2	@ sha1p q0,q3,q13
+
+	vadd.i32	q1,q1,q2
+	vadd.i32	q0,q0,q14
+	bne	Loop_v8
+
+	vst1.32	{q0},[r0]!
+	vst1.32	{d2[0]},[r0]
+
+	vldmia	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}
+	bx	lr					@ bx lr
+
+#endif
+#if __ARM_MAX_ARCH__>=7
+.comm	_OPENSSL_armcap_P,4
+.non_lazy_symbol_pointer
+OPENSSL_armcap_P:
+.indirect_symbol	_OPENSSL_armcap_P
+.long	0
+.private_extern	_OPENSSL_armcap_P
+#endif
diff --git a/third_party/boringssl/ios-arm/crypto/fipsmodule/sha256-armv4.S b/third_party/boringssl/ios-arm/crypto/fipsmodule/sha256-armv4.S
new file mode 100644
index 0000000..e55248a1
--- /dev/null
+++ b/third_party/boringssl/ios-arm/crypto/fipsmodule/sha256-armv4.S
@@ -0,0 +1,2820 @@
+@ Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
+@
+@ Licensed under the OpenSSL license (the "License").  You may not use
+@ this file except in compliance with the License.  You can obtain a copy
+@ in the file LICENSE in the source distribution or at
+@ https://www.openssl.org/source/license.html
+
+
+@ ====================================================================
+@ Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+@ project. The module is, however, dual licensed under OpenSSL and
+@ CRYPTOGAMS licenses depending on where you obtain it. For further
+@ details see http://www.openssl.org/~appro/cryptogams/.
+@
+@ Permission to use under GPL terms is granted.
+@ ====================================================================
+
+@ SHA256 block procedure for ARMv4. May 2007.
+
+@ Performance is ~2x better than gcc 3.4 generated code and in "abso-
+@ lute" terms is ~2250 cycles per 64-byte block or ~35 cycles per
+@ byte [on single-issue Xscale PXA250 core].
+
+@ July 2010.
+@
+@ Rescheduling for dual-issue pipeline resulted in 22% improvement on
+@ Cortex A8 core and ~20 cycles per processed byte.
+
+@ February 2011.
+@
+@ Profiler-assisted and platform-specific optimization resulted in 16%
+@ improvement on Cortex A8 core and ~15.4 cycles per processed byte.
+
+@ September 2013.
+@
+@ Add NEON implementation. On Cortex A8 it was measured to process one
+@ byte in 12.5 cycles or 23% faster than integer-only code. Snapdragon
+@ S4 does it in 12.5 cycles too, but it's 50% faster than integer-only
+@ code (meaning that latter performs sub-optimally, nothing was done
+@ about it).
+
+@ May 2014.
+@
+@ Add ARMv8 code path performing at 2.0 cpb on Apple A7.
+
+#ifndef __KERNEL__
+# include <openssl/arm_arch.h>
+#else
+# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_MAX_ARCH__ 7
+#endif
+
+.text
+#if defined(__thumb2__)
+.syntax	unified
+.thumb
+#else
+.code	32
+#endif
+
+
+.align	5
+K256:
+.word	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+.word	0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+.word	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+.word	0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+.word	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+.word	0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+.word	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+.word	0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+.word	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+.word	0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+.word	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+.word	0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+.word	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+.word	0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+.word	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+.word	0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+
+.word	0				@ terminator
+#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
+LOPENSSL_armcap:
+.word	OPENSSL_armcap_P-Lsha256_block_data_order
+#endif
+.align	5
+
+.globl	_sha256_block_data_order
+.private_extern	_sha256_block_data_order
+
+_sha256_block_data_order:
+Lsha256_block_data_order:
+#if __ARM_ARCH__<7 && !defined(__thumb2__)
+	sub	r3,pc,#8		@ _sha256_block_data_order
+#else
+	adr	r3,Lsha256_block_data_order
+#endif
+#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
+	ldr	r12,LOPENSSL_armcap
+	ldr	r12,[r3,r12]		@ OPENSSL_armcap_P
+#ifdef	__APPLE__
+	ldr	r12,[r12]
+#endif
+	tst	r12,#ARMV8_SHA256
+	bne	LARMv8
+	tst	r12,#ARMV7_NEON
+	bne	LNEON
+#endif
+	add	r2,r1,r2,lsl#6	@ len to point at the end of inp
+	stmdb	sp!,{r0,r1,r2,r4-r11,lr}
+	ldmia	r0,{r4,r5,r6,r7,r8,r9,r10,r11}
+	sub	r14,r3,#256+32	@ K256
+	sub	sp,sp,#16*4		@ alloca(X[16])
+Loop:
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r5,r6		@ magic
+	eor	r12,r12,r12
+#if __ARM_ARCH__>=7
+	@ ldr	r2,[r1],#4			@ 0
+# if 0==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r8,r8,ror#5
+	add	r4,r4,r12			@ h+=Maj(a,b,c) from the past
+	eor	r0,r0,r8,ror#19	@ Sigma1(e)
+# ifndef __ARMEB__
+	rev	r2,r2
+# endif
+#else
+	@ ldrb	r2,[r1,#3]			@ 0
+	add	r4,r4,r12			@ h+=Maj(a,b,c) from the past
+	ldrb	r12,[r1,#2]
+	ldrb	r0,[r1,#1]
+	orr	r2,r2,r12,lsl#8
+	ldrb	r12,[r1],#4
+	orr	r2,r2,r0,lsl#16
+# if 0==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r8,r8,ror#5
+	orr	r2,r2,r12,lsl#24
+	eor	r0,r0,r8,ror#19	@ Sigma1(e)
+#endif
+	ldr	r12,[r14],#4			@ *K256++
+	add	r11,r11,r2			@ h+=X[i]
+	str	r2,[sp,#0*4]
+	eor	r2,r9,r10
+	add	r11,r11,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r8
+	add	r11,r11,r12			@ h+=K256[i]
+	eor	r2,r2,r10			@ Ch(e,f,g)
+	eor	r0,r4,r4,ror#11
+	add	r11,r11,r2			@ h+=Ch(e,f,g)
+#if 0==31
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2			@ done?
+#endif
+#if 0<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r12,r4,r5			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#2*4]		@ from future BODY_16_xx
+	eor	r12,r4,r5			@ a^b, b^c in next round
+	ldr	r1,[sp,#15*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r4,ror#20	@ Sigma0(a)
+	and	r3,r3,r12			@ (b^c)&=(a^b)
+	add	r7,r7,r11			@ d+=h
+	eor	r3,r3,r5			@ Maj(a,b,c)
+	add	r11,r11,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r11,r11,r3			@ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+	@ ldr	r2,[r1],#4			@ 1
+# if 1==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r7,r7,ror#5
+	add	r11,r11,r3			@ h+=Maj(a,b,c) from the past
+	eor	r0,r0,r7,ror#19	@ Sigma1(e)
+# ifndef __ARMEB__
+	rev	r2,r2
+# endif
+#else
+	@ ldrb	r2,[r1,#3]			@ 1
+	add	r11,r11,r3			@ h+=Maj(a,b,c) from the past
+	ldrb	r3,[r1,#2]
+	ldrb	r0,[r1,#1]
+	orr	r2,r2,r3,lsl#8
+	ldrb	r3,[r1],#4
+	orr	r2,r2,r0,lsl#16
+# if 1==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r7,r7,ror#5
+	orr	r2,r2,r3,lsl#24
+	eor	r0,r0,r7,ror#19	@ Sigma1(e)
+#endif
+	ldr	r3,[r14],#4			@ *K256++
+	add	r10,r10,r2			@ h+=X[i]
+	str	r2,[sp,#1*4]
+	eor	r2,r8,r9
+	add	r10,r10,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r7
+	add	r10,r10,r3			@ h+=K256[i]
+	eor	r2,r2,r9			@ Ch(e,f,g)
+	eor	r0,r11,r11,ror#11
+	add	r10,r10,r2			@ h+=Ch(e,f,g)
+#if 1==31
+	and	r3,r3,#0xff
+	cmp	r3,#0xf2			@ done?
+#endif
+#if 1<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r11,r4			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#3*4]		@ from future BODY_16_xx
+	eor	r3,r11,r4			@ a^b, b^c in next round
+	ldr	r1,[sp,#0*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r11,ror#20	@ Sigma0(a)
+	and	r12,r12,r3			@ (b^c)&=(a^b)
+	add	r6,r6,r10			@ d+=h
+	eor	r12,r12,r4			@ Maj(a,b,c)
+	add	r10,r10,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r10,r10,r12			@ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+	@ ldr	r2,[r1],#4			@ 2
+# if 2==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r6,r6,ror#5
+	add	r10,r10,r12			@ h+=Maj(a,b,c) from the past
+	eor	r0,r0,r6,ror#19	@ Sigma1(e)
+# ifndef __ARMEB__
+	rev	r2,r2
+# endif
+#else
+	@ ldrb	r2,[r1,#3]			@ 2
+	add	r10,r10,r12			@ h+=Maj(a,b,c) from the past
+	ldrb	r12,[r1,#2]
+	ldrb	r0,[r1,#1]
+	orr	r2,r2,r12,lsl#8
+	ldrb	r12,[r1],#4
+	orr	r2,r2,r0,lsl#16
+# if 2==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r6,r6,ror#5
+	orr	r2,r2,r12,lsl#24
+	eor	r0,r0,r6,ror#19	@ Sigma1(e)
+#endif
+	ldr	r12,[r14],#4			@ *K256++
+	add	r9,r9,r2			@ h+=X[i]
+	str	r2,[sp,#2*4]
+	eor	r2,r7,r8
+	add	r9,r9,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r6
+	add	r9,r9,r12			@ h+=K256[i]
+	eor	r2,r2,r8			@ Ch(e,f,g)
+	eor	r0,r10,r10,ror#11
+	add	r9,r9,r2			@ h+=Ch(e,f,g)
+#if 2==31
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2			@ done?
+#endif
+#if 2<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r12,r10,r11			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#4*4]		@ from future BODY_16_xx
+	eor	r12,r10,r11			@ a^b, b^c in next round
+	ldr	r1,[sp,#1*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r10,ror#20	@ Sigma0(a)
+	and	r3,r3,r12			@ (b^c)&=(a^b)
+	add	r5,r5,r9			@ d+=h
+	eor	r3,r3,r11			@ Maj(a,b,c)
+	add	r9,r9,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r9,r9,r3			@ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+	@ ldr	r2,[r1],#4			@ 3
+# if 3==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r5,r5,ror#5
+	add	r9,r9,r3			@ h+=Maj(a,b,c) from the past
+	eor	r0,r0,r5,ror#19	@ Sigma1(e)
+# ifndef __ARMEB__
+	rev	r2,r2
+# endif
+#else
+	@ ldrb	r2,[r1,#3]			@ 3
+	add	r9,r9,r3			@ h+=Maj(a,b,c) from the past
+	ldrb	r3,[r1,#2]
+	ldrb	r0,[r1,#1]
+	orr	r2,r2,r3,lsl#8
+	ldrb	r3,[r1],#4
+	orr	r2,r2,r0,lsl#16
+# if 3==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r5,r5,ror#5
+	orr	r2,r2,r3,lsl#24
+	eor	r0,r0,r5,ror#19	@ Sigma1(e)
+#endif
+	ldr	r3,[r14],#4			@ *K256++
+	add	r8,r8,r2			@ h+=X[i]
+	str	r2,[sp,#3*4]
+	eor	r2,r6,r7
+	add	r8,r8,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r5
+	add	r8,r8,r3			@ h+=K256[i]
+	eor	r2,r2,r7			@ Ch(e,f,g)
+	eor	r0,r9,r9,ror#11
+	add	r8,r8,r2			@ h+=Ch(e,f,g)
+#if 3==31
+	and	r3,r3,#0xff
+	cmp	r3,#0xf2			@ done?
+#endif
+#if 3<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r9,r10			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#5*4]		@ from future BODY_16_xx
+	eor	r3,r9,r10			@ a^b, b^c in next round
+	ldr	r1,[sp,#2*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r9,ror#20	@ Sigma0(a)
+	and	r12,r12,r3			@ (b^c)&=(a^b)
+	add	r4,r4,r8			@ d+=h
+	eor	r12,r12,r10			@ Maj(a,b,c)
+	add	r8,r8,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r8,r8,r12			@ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+	@ ldr	r2,[r1],#4			@ 4
+# if 4==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r4,r4,ror#5
+	add	r8,r8,r12			@ h+=Maj(a,b,c) from the past
+	eor	r0,r0,r4,ror#19	@ Sigma1(e)
+# ifndef __ARMEB__
+	rev	r2,r2
+# endif
+#else
+	@ ldrb	r2,[r1,#3]			@ 4
+	add	r8,r8,r12			@ h+=Maj(a,b,c) from the past
+	ldrb	r12,[r1,#2]
+	ldrb	r0,[r1,#1]
+	orr	r2,r2,r12,lsl#8
+	ldrb	r12,[r1],#4
+	orr	r2,r2,r0,lsl#16
+# if 4==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r4,r4,ror#5
+	orr	r2,r2,r12,lsl#24
+	eor	r0,r0,r4,ror#19	@ Sigma1(e)
+#endif
+	ldr	r12,[r14],#4			@ *K256++
+	add	r7,r7,r2			@ h+=X[i]
+	str	r2,[sp,#4*4]
+	eor	r2,r5,r6
+	add	r7,r7,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r4
+	add	r7,r7,r12			@ h+=K256[i]
+	eor	r2,r2,r6			@ Ch(e,f,g)
+	eor	r0,r8,r8,ror#11
+	add	r7,r7,r2			@ h+=Ch(e,f,g)
+#if 4==31
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2			@ done?
+#endif
+#if 4<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r12,r8,r9			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#6*4]		@ from future BODY_16_xx
+	eor	r12,r8,r9			@ a^b, b^c in next round
+	ldr	r1,[sp,#3*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r8,ror#20	@ Sigma0(a)
+	and	r3,r3,r12			@ (b^c)&=(a^b)
+	add	r11,r11,r7			@ d+=h
+	eor	r3,r3,r9			@ Maj(a,b,c)
+	add	r7,r7,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r7,r7,r3			@ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+	@ ldr	r2,[r1],#4			@ 5
+# if 5==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r11,r11,ror#5
+	add	r7,r7,r3			@ h+=Maj(a,b,c) from the past
+	eor	r0,r0,r11,ror#19	@ Sigma1(e)
+# ifndef __ARMEB__
+	rev	r2,r2
+# endif
+#else
+	@ ldrb	r2,[r1,#3]			@ 5
+	add	r7,r7,r3			@ h+=Maj(a,b,c) from the past
+	ldrb	r3,[r1,#2]
+	ldrb	r0,[r1,#1]
+	orr	r2,r2,r3,lsl#8
+	ldrb	r3,[r1],#4
+	orr	r2,r2,r0,lsl#16
+# if 5==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r11,r11,ror#5
+	orr	r2,r2,r3,lsl#24
+	eor	r0,r0,r11,ror#19	@ Sigma1(e)
+#endif
+	ldr	r3,[r14],#4			@ *K256++
+	add	r6,r6,r2			@ h+=X[i]
+	str	r2,[sp,#5*4]
+	eor	r2,r4,r5
+	add	r6,r6,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r11
+	add	r6,r6,r3			@ h+=K256[i]
+	eor	r2,r2,r5			@ Ch(e,f,g)
+	eor	r0,r7,r7,ror#11
+	add	r6,r6,r2			@ h+=Ch(e,f,g)
+#if 5==31
+	and	r3,r3,#0xff
+	cmp	r3,#0xf2			@ done?
+#endif
+#if 5<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r7,r8			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#7*4]		@ from future BODY_16_xx
+	eor	r3,r7,r8			@ a^b, b^c in next round
+	ldr	r1,[sp,#4*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r7,ror#20	@ Sigma0(a)
+	and	r12,r12,r3			@ (b^c)&=(a^b)
+	add	r10,r10,r6			@ d+=h
+	eor	r12,r12,r8			@ Maj(a,b,c)
+	add	r6,r6,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r6,r6,r12			@ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+	@ ldr	r2,[r1],#4			@ 6
+# if 6==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r10,r10,ror#5
+	add	r6,r6,r12			@ h+=Maj(a,b,c) from the past
+	eor	r0,r0,r10,ror#19	@ Sigma1(e)
+# ifndef __ARMEB__
+	rev	r2,r2
+# endif
+#else
+	@ ldrb	r2,[r1,#3]			@ 6
+	add	r6,r6,r12			@ h+=Maj(a,b,c) from the past
+	ldrb	r12,[r1,#2]
+	ldrb	r0,[r1,#1]
+	orr	r2,r2,r12,lsl#8
+	ldrb	r12,[r1],#4
+	orr	r2,r2,r0,lsl#16
+# if 6==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r10,r10,ror#5
+	orr	r2,r2,r12,lsl#24
+	eor	r0,r0,r10,ror#19	@ Sigma1(e)
+#endif
+	ldr	r12,[r14],#4			@ *K256++
+	add	r5,r5,r2			@ h+=X[i]
+	str	r2,[sp,#6*4]
+	eor	r2,r11,r4
+	add	r5,r5,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r10
+	add	r5,r5,r12			@ h+=K256[i]
+	eor	r2,r2,r4			@ Ch(e,f,g)
+	eor	r0,r6,r6,ror#11
+	add	r5,r5,r2			@ h+=Ch(e,f,g)
+#if 6==31
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2			@ done?
+#endif
+#if 6<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r12,r6,r7			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#8*4]		@ from future BODY_16_xx
+	eor	r12,r6,r7			@ a^b, b^c in next round
+	ldr	r1,[sp,#5*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r6,ror#20	@ Sigma0(a)
+	and	r3,r3,r12			@ (b^c)&=(a^b)
+	add	r9,r9,r5			@ d+=h
+	eor	r3,r3,r7			@ Maj(a,b,c)
+	add	r5,r5,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r5,r5,r3			@ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+	@ ldr	r2,[r1],#4			@ 7
+# if 7==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r9,r9,ror#5
+	add	r5,r5,r3			@ h+=Maj(a,b,c) from the past
+	eor	r0,r0,r9,ror#19	@ Sigma1(e)
+# ifndef __ARMEB__
+	rev	r2,r2
+# endif
+#else
+	@ ldrb	r2,[r1,#3]			@ 7
+	add	r5,r5,r3			@ h+=Maj(a,b,c) from the past
+	ldrb	r3,[r1,#2]
+	ldrb	r0,[r1,#1]
+	orr	r2,r2,r3,lsl#8
+	ldrb	r3,[r1],#4
+	orr	r2,r2,r0,lsl#16
+# if 7==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r9,r9,ror#5
+	orr	r2,r2,r3,lsl#24
+	eor	r0,r0,r9,ror#19	@ Sigma1(e)
+#endif
+	ldr	r3,[r14],#4			@ *K256++
+	add	r4,r4,r2			@ h+=X[i]
+	str	r2,[sp,#7*4]
+	eor	r2,r10,r11
+	add	r4,r4,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r9
+	add	r4,r4,r3			@ h+=K256[i]
+	eor	r2,r2,r11			@ Ch(e,f,g)
+	eor	r0,r5,r5,ror#11
+	add	r4,r4,r2			@ h+=Ch(e,f,g)
+#if 7==31
+	and	r3,r3,#0xff
+	cmp	r3,#0xf2			@ done?
+#endif
+#if 7<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r5,r6			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#9*4]		@ from future BODY_16_xx
+	eor	r3,r5,r6			@ a^b, b^c in next round
+	ldr	r1,[sp,#6*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r5,ror#20	@ Sigma0(a)
+	and	r12,r12,r3			@ (b^c)&=(a^b)
+	add	r8,r8,r4			@ d+=h
+	eor	r12,r12,r6			@ Maj(a,b,c)
+	add	r4,r4,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r4,r4,r12			@ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+	@ ldr	r2,[r1],#4			@ 8
+# if 8==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r8,r8,ror#5
+	add	r4,r4,r12			@ h+=Maj(a,b,c) from the past
+	eor	r0,r0,r8,ror#19	@ Sigma1(e)
+# ifndef __ARMEB__
+	rev	r2,r2
+# endif
+#else
+	@ ldrb	r2,[r1,#3]			@ 8
+	add	r4,r4,r12			@ h+=Maj(a,b,c) from the past
+	ldrb	r12,[r1,#2]
+	ldrb	r0,[r1,#1]
+	orr	r2,r2,r12,lsl#8
+	ldrb	r12,[r1],#4
+	orr	r2,r2,r0,lsl#16
+# if 8==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r8,r8,ror#5
+	orr	r2,r2,r12,lsl#24
+	eor	r0,r0,r8,ror#19	@ Sigma1(e)
+#endif
+	ldr	r12,[r14],#4			@ *K256++
+	add	r11,r11,r2			@ h+=X[i]
+	str	r2,[sp,#8*4]
+	eor	r2,r9,r10
+	add	r11,r11,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r8
+	add	r11,r11,r12			@ h+=K256[i]
+	eor	r2,r2,r10			@ Ch(e,f,g)
+	eor	r0,r4,r4,ror#11
+	add	r11,r11,r2			@ h+=Ch(e,f,g)
+#if 8==31
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2			@ done?
+#endif
+#if 8<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r12,r4,r5			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#10*4]		@ from future BODY_16_xx
+	eor	r12,r4,r5			@ a^b, b^c in next round
+	ldr	r1,[sp,#7*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r4,ror#20	@ Sigma0(a)
+	and	r3,r3,r12			@ (b^c)&=(a^b)
+	add	r7,r7,r11			@ d+=h
+	eor	r3,r3,r5			@ Maj(a,b,c)
+	add	r11,r11,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r11,r11,r3			@ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+	@ ldr	r2,[r1],#4			@ 9
+# if 9==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r7,r7,ror#5
+	add	r11,r11,r3			@ h+=Maj(a,b,c) from the past
+	eor	r0,r0,r7,ror#19	@ Sigma1(e)
+# ifndef __ARMEB__
+	rev	r2,r2
+# endif
+#else
+	@ ldrb	r2,[r1,#3]			@ 9
+	add	r11,r11,r3			@ h+=Maj(a,b,c) from the past
+	ldrb	r3,[r1,#2]
+	ldrb	r0,[r1,#1]
+	orr	r2,r2,r3,lsl#8
+	ldrb	r3,[r1],#4
+	orr	r2,r2,r0,lsl#16
+# if 9==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r7,r7,ror#5
+	orr	r2,r2,r3,lsl#24
+	eor	r0,r0,r7,ror#19	@ Sigma1(e)
+#endif
+	ldr	r3,[r14],#4			@ *K256++
+	add	r10,r10,r2			@ h+=X[i]
+	str	r2,[sp,#9*4]
+	eor	r2,r8,r9
+	add	r10,r10,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r7
+	add	r10,r10,r3			@ h+=K256[i]
+	eor	r2,r2,r9			@ Ch(e,f,g)
+	eor	r0,r11,r11,ror#11
+	add	r10,r10,r2			@ h+=Ch(e,f,g)
+#if 9==31
+	and	r3,r3,#0xff
+	cmp	r3,#0xf2			@ done?
+#endif
+#if 9<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r11,r4			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#11*4]		@ from future BODY_16_xx
+	eor	r3,r11,r4			@ a^b, b^c in next round
+	ldr	r1,[sp,#8*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r11,ror#20	@ Sigma0(a)
+	and	r12,r12,r3			@ (b^c)&=(a^b)
+	add	r6,r6,r10			@ d+=h
+	eor	r12,r12,r4			@ Maj(a,b,c)
+	add	r10,r10,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r10,r10,r12			@ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+	@ ldr	r2,[r1],#4			@ 10
+# if 10==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r6,r6,ror#5
+	add	r10,r10,r12			@ h+=Maj(a,b,c) from the past
+	eor	r0,r0,r6,ror#19	@ Sigma1(e)
+# ifndef __ARMEB__
+	rev	r2,r2
+# endif
+#else
+	@ ldrb	r2,[r1,#3]			@ 10
+	add	r10,r10,r12			@ h+=Maj(a,b,c) from the past
+	ldrb	r12,[r1,#2]
+	ldrb	r0,[r1,#1]
+	orr	r2,r2,r12,lsl#8
+	ldrb	r12,[r1],#4
+	orr	r2,r2,r0,lsl#16
+# if 10==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r6,r6,ror#5
+	orr	r2,r2,r12,lsl#24
+	eor	r0,r0,r6,ror#19	@ Sigma1(e)
+#endif
+	ldr	r12,[r14],#4			@ *K256++
+	add	r9,r9,r2			@ h+=X[i]
+	str	r2,[sp,#10*4]
+	eor	r2,r7,r8
+	add	r9,r9,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r6
+	add	r9,r9,r12			@ h+=K256[i]
+	eor	r2,r2,r8			@ Ch(e,f,g)
+	eor	r0,r10,r10,ror#11
+	add	r9,r9,r2			@ h+=Ch(e,f,g)
+#if 10==31
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2			@ done?
+#endif
+#if 10<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r12,r10,r11			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#12*4]		@ from future BODY_16_xx
+	eor	r12,r10,r11			@ a^b, b^c in next round
+	ldr	r1,[sp,#9*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r10,ror#20	@ Sigma0(a)
+	and	r3,r3,r12			@ (b^c)&=(a^b)
+	add	r5,r5,r9			@ d+=h
+	eor	r3,r3,r11			@ Maj(a,b,c)
+	add	r9,r9,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r9,r9,r3			@ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+	@ ldr	r2,[r1],#4			@ 11
+# if 11==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r5,r5,ror#5
+	add	r9,r9,r3			@ h+=Maj(a,b,c) from the past
+	eor	r0,r0,r5,ror#19	@ Sigma1(e)
+# ifndef __ARMEB__
+	rev	r2,r2
+# endif
+#else
+	@ ldrb	r2,[r1,#3]			@ 11
+	add	r9,r9,r3			@ h+=Maj(a,b,c) from the past
+	ldrb	r3,[r1,#2]
+	ldrb	r0,[r1,#1]
+	orr	r2,r2,r3,lsl#8
+	ldrb	r3,[r1],#4
+	orr	r2,r2,r0,lsl#16
+# if 11==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r5,r5,ror#5
+	orr	r2,r2,r3,lsl#24
+	eor	r0,r0,r5,ror#19	@ Sigma1(e)
+#endif
+	ldr	r3,[r14],#4			@ *K256++
+	add	r8,r8,r2			@ h+=X[i]
+	str	r2,[sp,#11*4]
+	eor	r2,r6,r7
+	add	r8,r8,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r5
+	add	r8,r8,r3			@ h+=K256[i]
+	eor	r2,r2,r7			@ Ch(e,f,g)
+	eor	r0,r9,r9,ror#11
+	add	r8,r8,r2			@ h+=Ch(e,f,g)
+#if 11==31
+	and	r3,r3,#0xff
+	cmp	r3,#0xf2			@ done?
+#endif
+#if 11<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r9,r10			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#13*4]		@ from future BODY_16_xx
+	eor	r3,r9,r10			@ a^b, b^c in next round
+	ldr	r1,[sp,#10*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r9,ror#20	@ Sigma0(a)
+	and	r12,r12,r3			@ (b^c)&=(a^b)
+	add	r4,r4,r8			@ d+=h
+	eor	r12,r12,r10			@ Maj(a,b,c)
+	add	r8,r8,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r8,r8,r12			@ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+	@ ldr	r2,[r1],#4			@ 12
+# if 12==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r4,r4,ror#5
+	add	r8,r8,r12			@ h+=Maj(a,b,c) from the past
+	eor	r0,r0,r4,ror#19	@ Sigma1(e)
+# ifndef __ARMEB__
+	rev	r2,r2
+# endif
+#else
+	@ ldrb	r2,[r1,#3]			@ 12
+	add	r8,r8,r12			@ h+=Maj(a,b,c) from the past
+	ldrb	r12,[r1,#2]
+	ldrb	r0,[r1,#1]
+	orr	r2,r2,r12,lsl#8
+	ldrb	r12,[r1],#4
+	orr	r2,r2,r0,lsl#16
+# if 12==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r4,r4,ror#5
+	orr	r2,r2,r12,lsl#24
+	eor	r0,r0,r4,ror#19	@ Sigma1(e)
+#endif
+	ldr	r12,[r14],#4			@ *K256++
+	add	r7,r7,r2			@ h+=X[i]
+	str	r2,[sp,#12*4]
+	eor	r2,r5,r6
+	add	r7,r7,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r4
+	add	r7,r7,r12			@ h+=K256[i]
+	eor	r2,r2,r6			@ Ch(e,f,g)
+	eor	r0,r8,r8,ror#11
+	add	r7,r7,r2			@ h+=Ch(e,f,g)
+#if 12==31
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2			@ done?
+#endif
+#if 12<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r12,r8,r9			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#14*4]		@ from future BODY_16_xx
+	eor	r12,r8,r9			@ a^b, b^c in next round
+	ldr	r1,[sp,#11*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r8,ror#20	@ Sigma0(a)
+	and	r3,r3,r12			@ (b^c)&=(a^b)
+	add	r11,r11,r7			@ d+=h
+	eor	r3,r3,r9			@ Maj(a,b,c)
+	add	r7,r7,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r7,r7,r3			@ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+	@ ldr	r2,[r1],#4			@ 13
+# if 13==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r11,r11,ror#5
+	add	r7,r7,r3			@ h+=Maj(a,b,c) from the past
+	eor	r0,r0,r11,ror#19	@ Sigma1(e)
+# ifndef __ARMEB__
+	rev	r2,r2
+# endif
+#else
+	@ ldrb	r2,[r1,#3]			@ 13
+	add	r7,r7,r3			@ h+=Maj(a,b,c) from the past
+	ldrb	r3,[r1,#2]
+	ldrb	r0,[r1,#1]
+	orr	r2,r2,r3,lsl#8
+	ldrb	r3,[r1],#4
+	orr	r2,r2,r0,lsl#16
+# if 13==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r11,r11,ror#5
+	orr	r2,r2,r3,lsl#24
+	eor	r0,r0,r11,ror#19	@ Sigma1(e)
+#endif
+	ldr	r3,[r14],#4			@ *K256++
+	add	r6,r6,r2			@ h+=X[i]
+	str	r2,[sp,#13*4]
+	eor	r2,r4,r5
+	add	r6,r6,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r11
+	add	r6,r6,r3			@ h+=K256[i]
+	eor	r2,r2,r5			@ Ch(e,f,g)
+	eor	r0,r7,r7,ror#11
+	add	r6,r6,r2			@ h+=Ch(e,f,g)
+#if 13==31
+	and	r3,r3,#0xff
+	cmp	r3,#0xf2			@ done?
+#endif
+#if 13<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r7,r8			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#15*4]		@ from future BODY_16_xx
+	eor	r3,r7,r8			@ a^b, b^c in next round
+	ldr	r1,[sp,#12*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r7,ror#20	@ Sigma0(a)
+	and	r12,r12,r3			@ (b^c)&=(a^b)
+	add	r10,r10,r6			@ d+=h
+	eor	r12,r12,r8			@ Maj(a,b,c)
+	add	r6,r6,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r6,r6,r12			@ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+	@ ldr	r2,[r1],#4			@ 14
+# if 14==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r10,r10,ror#5
+	add	r6,r6,r12			@ h+=Maj(a,b,c) from the past
+	eor	r0,r0,r10,ror#19	@ Sigma1(e)
+# ifndef __ARMEB__
+	rev	r2,r2
+# endif
+#else
+	@ ldrb	r2,[r1,#3]			@ 14
+	add	r6,r6,r12			@ h+=Maj(a,b,c) from the past
+	ldrb	r12,[r1,#2]
+	ldrb	r0,[r1,#1]
+	orr	r2,r2,r12,lsl#8
+	ldrb	r12,[r1],#4
+	orr	r2,r2,r0,lsl#16
+# if 14==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r10,r10,ror#5
+	orr	r2,r2,r12,lsl#24
+	eor	r0,r0,r10,ror#19	@ Sigma1(e)
+#endif
+	ldr	r12,[r14],#4			@ *K256++
+	add	r5,r5,r2			@ h+=X[i]
+	str	r2,[sp,#14*4]
+	eor	r2,r11,r4
+	add	r5,r5,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r10
+	add	r5,r5,r12			@ h+=K256[i]
+	eor	r2,r2,r4			@ Ch(e,f,g)
+	eor	r0,r6,r6,ror#11
+	add	r5,r5,r2			@ h+=Ch(e,f,g)
+#if 14==31
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2			@ done?
+#endif
+#if 14<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r12,r6,r7			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#0*4]		@ from future BODY_16_xx
+	eor	r12,r6,r7			@ a^b, b^c in next round
+	ldr	r1,[sp,#13*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r6,ror#20	@ Sigma0(a)
+	and	r3,r3,r12			@ (b^c)&=(a^b)
+	add	r9,r9,r5			@ d+=h
+	eor	r3,r3,r7			@ Maj(a,b,c)
+	add	r5,r5,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r5,r5,r3			@ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+	@ ldr	r2,[r1],#4			@ 15
+# if 15==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r9,r9,ror#5
+	add	r5,r5,r3			@ h+=Maj(a,b,c) from the past
+	eor	r0,r0,r9,ror#19	@ Sigma1(e)
+# ifndef __ARMEB__
+	rev	r2,r2
+# endif
+#else
+	@ ldrb	r2,[r1,#3]			@ 15
+	add	r5,r5,r3			@ h+=Maj(a,b,c) from the past
+	ldrb	r3,[r1,#2]
+	ldrb	r0,[r1,#1]
+	orr	r2,r2,r3,lsl#8
+	ldrb	r3,[r1],#4
+	orr	r2,r2,r0,lsl#16
+# if 15==15
+	str	r1,[sp,#17*4]			@ make room for r1
+# endif
+	eor	r0,r9,r9,ror#5
+	orr	r2,r2,r3,lsl#24
+	eor	r0,r0,r9,ror#19	@ Sigma1(e)
+#endif
+	ldr	r3,[r14],#4			@ *K256++
+	add	r4,r4,r2			@ h+=X[i]
+	str	r2,[sp,#15*4]
+	eor	r2,r10,r11
+	add	r4,r4,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r9
+	add	r4,r4,r3			@ h+=K256[i]
+	eor	r2,r2,r11			@ Ch(e,f,g)
+	eor	r0,r5,r5,ror#11
+	add	r4,r4,r2			@ h+=Ch(e,f,g)
+#if 15==31
+	and	r3,r3,#0xff
+	cmp	r3,#0xf2			@ done?
+#endif
+#if 15<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r5,r6			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#1*4]		@ from future BODY_16_xx
+	eor	r3,r5,r6			@ a^b, b^c in next round
+	ldr	r1,[sp,#14*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r5,ror#20	@ Sigma0(a)
+	and	r12,r12,r3			@ (b^c)&=(a^b)
+	add	r8,r8,r4			@ d+=h
+	eor	r12,r12,r6			@ Maj(a,b,c)
+	add	r4,r4,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r4,r4,r12			@ h+=Maj(a,b,c)
+Lrounds_16_xx:
+	@ ldr	r2,[sp,#1*4]		@ 16
+	@ ldr	r1,[sp,#14*4]
+	mov	r0,r2,ror#7
+	add	r4,r4,r12			@ h+=Maj(a,b,c) from the past
+	mov	r12,r1,ror#17
+	eor	r0,r0,r2,ror#18
+	eor	r12,r12,r1,ror#19
+	eor	r0,r0,r2,lsr#3	@ sigma0(X[i+1])
+	ldr	r2,[sp,#0*4]
+	eor	r12,r12,r1,lsr#10	@ sigma1(X[i+14])
+	ldr	r1,[sp,#9*4]
+
+	add	r12,r12,r0
+	eor	r0,r8,r8,ror#5	@ from BODY_00_15
+	add	r2,r2,r12
+	eor	r0,r0,r8,ror#19	@ Sigma1(e)
+	add	r2,r2,r1			@ X[i]
+	ldr	r12,[r14],#4			@ *K256++
+	add	r11,r11,r2			@ h+=X[i]
+	str	r2,[sp,#0*4]
+	eor	r2,r9,r10
+	add	r11,r11,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r8
+	add	r11,r11,r12			@ h+=K256[i]
+	eor	r2,r2,r10			@ Ch(e,f,g)
+	eor	r0,r4,r4,ror#11
+	add	r11,r11,r2			@ h+=Ch(e,f,g)
+#if 16==31
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2			@ done?
+#endif
+#if 16<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r12,r4,r5			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#2*4]		@ from future BODY_16_xx
+	eor	r12,r4,r5			@ a^b, b^c in next round
+	ldr	r1,[sp,#15*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r4,ror#20	@ Sigma0(a)
+	and	r3,r3,r12			@ (b^c)&=(a^b)
+	add	r7,r7,r11			@ d+=h
+	eor	r3,r3,r5			@ Maj(a,b,c)
+	add	r11,r11,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r11,r11,r3			@ h+=Maj(a,b,c)
+	@ ldr	r2,[sp,#2*4]		@ 17
+	@ ldr	r1,[sp,#15*4]
+	mov	r0,r2,ror#7
+	add	r11,r11,r3			@ h+=Maj(a,b,c) from the past
+	mov	r3,r1,ror#17
+	eor	r0,r0,r2,ror#18
+	eor	r3,r3,r1,ror#19
+	eor	r0,r0,r2,lsr#3	@ sigma0(X[i+1])
+	ldr	r2,[sp,#1*4]
+	eor	r3,r3,r1,lsr#10	@ sigma1(X[i+14])
+	ldr	r1,[sp,#10*4]
+
+	add	r3,r3,r0
+	eor	r0,r7,r7,ror#5	@ from BODY_00_15
+	add	r2,r2,r3
+	eor	r0,r0,r7,ror#19	@ Sigma1(e)
+	add	r2,r2,r1			@ X[i]
+	ldr	r3,[r14],#4			@ *K256++
+	add	r10,r10,r2			@ h+=X[i]
+	str	r2,[sp,#1*4]
+	eor	r2,r8,r9
+	add	r10,r10,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r7
+	add	r10,r10,r3			@ h+=K256[i]
+	eor	r2,r2,r9			@ Ch(e,f,g)
+	eor	r0,r11,r11,ror#11
+	add	r10,r10,r2			@ h+=Ch(e,f,g)
+#if 17==31
+	and	r3,r3,#0xff
+	cmp	r3,#0xf2			@ done?
+#endif
+#if 17<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r11,r4			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#3*4]		@ from future BODY_16_xx
+	eor	r3,r11,r4			@ a^b, b^c in next round
+	ldr	r1,[sp,#0*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r11,ror#20	@ Sigma0(a)
+	and	r12,r12,r3			@ (b^c)&=(a^b)
+	add	r6,r6,r10			@ d+=h
+	eor	r12,r12,r4			@ Maj(a,b,c)
+	add	r10,r10,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r10,r10,r12			@ h+=Maj(a,b,c)
+	@ ldr	r2,[sp,#3*4]		@ 18
+	@ ldr	r1,[sp,#0*4]
+	mov	r0,r2,ror#7
+	add	r10,r10,r12			@ h+=Maj(a,b,c) from the past
+	mov	r12,r1,ror#17
+	eor	r0,r0,r2,ror#18
+	eor	r12,r12,r1,ror#19
+	eor	r0,r0,r2,lsr#3	@ sigma0(X[i+1])
+	ldr	r2,[sp,#2*4]
+	eor	r12,r12,r1,lsr#10	@ sigma1(X[i+14])
+	ldr	r1,[sp,#11*4]
+
+	add	r12,r12,r0
+	eor	r0,r6,r6,ror#5	@ from BODY_00_15
+	add	r2,r2,r12
+	eor	r0,r0,r6,ror#19	@ Sigma1(e)
+	add	r2,r2,r1			@ X[i]
+	ldr	r12,[r14],#4			@ *K256++
+	add	r9,r9,r2			@ h+=X[i]
+	str	r2,[sp,#2*4]
+	eor	r2,r7,r8
+	add	r9,r9,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r6
+	add	r9,r9,r12			@ h+=K256[i]
+	eor	r2,r2,r8			@ Ch(e,f,g)
+	eor	r0,r10,r10,ror#11
+	add	r9,r9,r2			@ h+=Ch(e,f,g)
+#if 18==31
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2			@ done?
+#endif
+#if 18<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r12,r10,r11			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#4*4]		@ from future BODY_16_xx
+	eor	r12,r10,r11			@ a^b, b^c in next round
+	ldr	r1,[sp,#1*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r10,ror#20	@ Sigma0(a)
+	and	r3,r3,r12			@ (b^c)&=(a^b)
+	add	r5,r5,r9			@ d+=h
+	eor	r3,r3,r11			@ Maj(a,b,c)
+	add	r9,r9,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r9,r9,r3			@ h+=Maj(a,b,c)
+	@ ldr	r2,[sp,#4*4]		@ 19
+	@ ldr	r1,[sp,#1*4]
+	mov	r0,r2,ror#7
+	add	r9,r9,r3			@ h+=Maj(a,b,c) from the past
+	mov	r3,r1,ror#17
+	eor	r0,r0,r2,ror#18
+	eor	r3,r3,r1,ror#19
+	eor	r0,r0,r2,lsr#3	@ sigma0(X[i+1])
+	ldr	r2,[sp,#3*4]
+	eor	r3,r3,r1,lsr#10	@ sigma1(X[i+14])
+	ldr	r1,[sp,#12*4]
+
+	add	r3,r3,r0
+	eor	r0,r5,r5,ror#5	@ from BODY_00_15
+	add	r2,r2,r3
+	eor	r0,r0,r5,ror#19	@ Sigma1(e)
+	add	r2,r2,r1			@ X[i]
+	ldr	r3,[r14],#4			@ *K256++
+	add	r8,r8,r2			@ h+=X[i]
+	str	r2,[sp,#3*4]
+	eor	r2,r6,r7
+	add	r8,r8,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r5
+	add	r8,r8,r3			@ h+=K256[i]
+	eor	r2,r2,r7			@ Ch(e,f,g)
+	eor	r0,r9,r9,ror#11
+	add	r8,r8,r2			@ h+=Ch(e,f,g)
+#if 19==31
+	and	r3,r3,#0xff
+	cmp	r3,#0xf2			@ done?
+#endif
+#if 19<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r9,r10			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#5*4]		@ from future BODY_16_xx
+	eor	r3,r9,r10			@ a^b, b^c in next round
+	ldr	r1,[sp,#2*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r9,ror#20	@ Sigma0(a)
+	and	r12,r12,r3			@ (b^c)&=(a^b)
+	add	r4,r4,r8			@ d+=h
+	eor	r12,r12,r10			@ Maj(a,b,c)
+	add	r8,r8,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r8,r8,r12			@ h+=Maj(a,b,c)
+	@ ldr	r2,[sp,#5*4]		@ 20
+	@ ldr	r1,[sp,#2*4]
+	mov	r0,r2,ror#7
+	add	r8,r8,r12			@ h+=Maj(a,b,c) from the past
+	mov	r12,r1,ror#17
+	eor	r0,r0,r2,ror#18
+	eor	r12,r12,r1,ror#19
+	eor	r0,r0,r2,lsr#3	@ sigma0(X[i+1])
+	ldr	r2,[sp,#4*4]
+	eor	r12,r12,r1,lsr#10	@ sigma1(X[i+14])
+	ldr	r1,[sp,#13*4]
+
+	add	r12,r12,r0
+	eor	r0,r4,r4,ror#5	@ from BODY_00_15
+	add	r2,r2,r12
+	eor	r0,r0,r4,ror#19	@ Sigma1(e)
+	add	r2,r2,r1			@ X[i]
+	ldr	r12,[r14],#4			@ *K256++
+	add	r7,r7,r2			@ h+=X[i]
+	str	r2,[sp,#4*4]
+	eor	r2,r5,r6
+	add	r7,r7,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r4
+	add	r7,r7,r12			@ h+=K256[i]
+	eor	r2,r2,r6			@ Ch(e,f,g)
+	eor	r0,r8,r8,ror#11
+	add	r7,r7,r2			@ h+=Ch(e,f,g)
+#if 20==31
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2			@ done?
+#endif
+#if 20<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r12,r8,r9			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#6*4]		@ from future BODY_16_xx
+	eor	r12,r8,r9			@ a^b, b^c in next round
+	ldr	r1,[sp,#3*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r8,ror#20	@ Sigma0(a)
+	and	r3,r3,r12			@ (b^c)&=(a^b)
+	add	r11,r11,r7			@ d+=h
+	eor	r3,r3,r9			@ Maj(a,b,c)
+	add	r7,r7,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r7,r7,r3			@ h+=Maj(a,b,c)
+	@ ldr	r2,[sp,#6*4]		@ 21
+	@ ldr	r1,[sp,#3*4]
+	mov	r0,r2,ror#7
+	add	r7,r7,r3			@ h+=Maj(a,b,c) from the past
+	mov	r3,r1,ror#17
+	eor	r0,r0,r2,ror#18
+	eor	r3,r3,r1,ror#19
+	eor	r0,r0,r2,lsr#3	@ sigma0(X[i+1])
+	ldr	r2,[sp,#5*4]
+	eor	r3,r3,r1,lsr#10	@ sigma1(X[i+14])
+	ldr	r1,[sp,#14*4]
+
+	add	r3,r3,r0
+	eor	r0,r11,r11,ror#5	@ from BODY_00_15
+	add	r2,r2,r3
+	eor	r0,r0,r11,ror#19	@ Sigma1(e)
+	add	r2,r2,r1			@ X[i]
+	ldr	r3,[r14],#4			@ *K256++
+	add	r6,r6,r2			@ h+=X[i]
+	str	r2,[sp,#5*4]
+	eor	r2,r4,r5
+	add	r6,r6,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r11
+	add	r6,r6,r3			@ h+=K256[i]
+	eor	r2,r2,r5			@ Ch(e,f,g)
+	eor	r0,r7,r7,ror#11
+	add	r6,r6,r2			@ h+=Ch(e,f,g)
+#if 21==31
+	and	r3,r3,#0xff
+	cmp	r3,#0xf2			@ done?
+#endif
+#if 21<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r7,r8			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#7*4]		@ from future BODY_16_xx
+	eor	r3,r7,r8			@ a^b, b^c in next round
+	ldr	r1,[sp,#4*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r7,ror#20	@ Sigma0(a)
+	and	r12,r12,r3			@ (b^c)&=(a^b)
+	add	r10,r10,r6			@ d+=h
+	eor	r12,r12,r8			@ Maj(a,b,c)
+	add	r6,r6,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r6,r6,r12			@ h+=Maj(a,b,c)
+	@ ldr	r2,[sp,#7*4]		@ 22
+	@ ldr	r1,[sp,#4*4]
+	mov	r0,r2,ror#7
+	add	r6,r6,r12			@ h+=Maj(a,b,c) from the past
+	mov	r12,r1,ror#17
+	eor	r0,r0,r2,ror#18
+	eor	r12,r12,r1,ror#19
+	eor	r0,r0,r2,lsr#3	@ sigma0(X[i+1])
+	ldr	r2,[sp,#6*4]
+	eor	r12,r12,r1,lsr#10	@ sigma1(X[i+14])
+	ldr	r1,[sp,#15*4]
+
+	add	r12,r12,r0
+	eor	r0,r10,r10,ror#5	@ from BODY_00_15
+	add	r2,r2,r12
+	eor	r0,r0,r10,ror#19	@ Sigma1(e)
+	add	r2,r2,r1			@ X[i]
+	ldr	r12,[r14],#4			@ *K256++
+	add	r5,r5,r2			@ h+=X[i]
+	str	r2,[sp,#6*4]
+	eor	r2,r11,r4
+	add	r5,r5,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r10
+	add	r5,r5,r12			@ h+=K256[i]
+	eor	r2,r2,r4			@ Ch(e,f,g)
+	eor	r0,r6,r6,ror#11
+	add	r5,r5,r2			@ h+=Ch(e,f,g)
+#if 22==31
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2			@ done?
+#endif
+#if 22<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r12,r6,r7			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#8*4]		@ from future BODY_16_xx
+	eor	r12,r6,r7			@ a^b, b^c in next round
+	ldr	r1,[sp,#5*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r6,ror#20	@ Sigma0(a)
+	and	r3,r3,r12			@ (b^c)&=(a^b)
+	add	r9,r9,r5			@ d+=h
+	eor	r3,r3,r7			@ Maj(a,b,c)
+	add	r5,r5,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r5,r5,r3			@ h+=Maj(a,b,c)
+	@ ldr	r2,[sp,#8*4]		@ 23
+	@ ldr	r1,[sp,#5*4]
+	mov	r0,r2,ror#7
+	add	r5,r5,r3			@ h+=Maj(a,b,c) from the past
+	mov	r3,r1,ror#17
+	eor	r0,r0,r2,ror#18
+	eor	r3,r3,r1,ror#19
+	eor	r0,r0,r2,lsr#3	@ sigma0(X[i+1])
+	ldr	r2,[sp,#7*4]
+	eor	r3,r3,r1,lsr#10	@ sigma1(X[i+14])
+	ldr	r1,[sp,#0*4]
+
+	add	r3,r3,r0
+	eor	r0,r9,r9,ror#5	@ from BODY_00_15
+	add	r2,r2,r3
+	eor	r0,r0,r9,ror#19	@ Sigma1(e)
+	add	r2,r2,r1			@ X[i]
+	ldr	r3,[r14],#4			@ *K256++
+	add	r4,r4,r2			@ h+=X[i]
+	str	r2,[sp,#7*4]
+	eor	r2,r10,r11
+	add	r4,r4,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r9
+	add	r4,r4,r3			@ h+=K256[i]
+	eor	r2,r2,r11			@ Ch(e,f,g)
+	eor	r0,r5,r5,ror#11
+	add	r4,r4,r2			@ h+=Ch(e,f,g)
+#if 23==31
+	and	r3,r3,#0xff
+	cmp	r3,#0xf2			@ done?
+#endif
+#if 23<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r5,r6			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#9*4]		@ from future BODY_16_xx
+	eor	r3,r5,r6			@ a^b, b^c in next round
+	ldr	r1,[sp,#6*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r5,ror#20	@ Sigma0(a)
+	and	r12,r12,r3			@ (b^c)&=(a^b)
+	add	r8,r8,r4			@ d+=h
+	eor	r12,r12,r6			@ Maj(a,b,c)
+	add	r4,r4,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r4,r4,r12			@ h+=Maj(a,b,c)
+	@ ldr	r2,[sp,#9*4]		@ 24
+	@ ldr	r1,[sp,#6*4]
+	mov	r0,r2,ror#7
+	add	r4,r4,r12			@ h+=Maj(a,b,c) from the past
+	mov	r12,r1,ror#17
+	eor	r0,r0,r2,ror#18
+	eor	r12,r12,r1,ror#19
+	eor	r0,r0,r2,lsr#3	@ sigma0(X[i+1])
+	ldr	r2,[sp,#8*4]
+	eor	r12,r12,r1,lsr#10	@ sigma1(X[i+14])
+	ldr	r1,[sp,#1*4]
+
+	add	r12,r12,r0
+	eor	r0,r8,r8,ror#5	@ from BODY_00_15
+	add	r2,r2,r12
+	eor	r0,r0,r8,ror#19	@ Sigma1(e)
+	add	r2,r2,r1			@ X[i]
+	ldr	r12,[r14],#4			@ *K256++
+	add	r11,r11,r2			@ h+=X[i]
+	str	r2,[sp,#8*4]
+	eor	r2,r9,r10
+	add	r11,r11,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r8
+	add	r11,r11,r12			@ h+=K256[i]
+	eor	r2,r2,r10			@ Ch(e,f,g)
+	eor	r0,r4,r4,ror#11
+	add	r11,r11,r2			@ h+=Ch(e,f,g)
+#if 24==31
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2			@ done?
+#endif
+#if 24<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r12,r4,r5			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#10*4]		@ from future BODY_16_xx
+	eor	r12,r4,r5			@ a^b, b^c in next round
+	ldr	r1,[sp,#7*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r4,ror#20	@ Sigma0(a)
+	and	r3,r3,r12			@ (b^c)&=(a^b)
+	add	r7,r7,r11			@ d+=h
+	eor	r3,r3,r5			@ Maj(a,b,c)
+	add	r11,r11,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r11,r11,r3			@ h+=Maj(a,b,c)
+	@ ldr	r2,[sp,#10*4]		@ 25
+	@ ldr	r1,[sp,#7*4]
+	mov	r0,r2,ror#7
+	add	r11,r11,r3			@ h+=Maj(a,b,c) from the past
+	mov	r3,r1,ror#17
+	eor	r0,r0,r2,ror#18
+	eor	r3,r3,r1,ror#19
+	eor	r0,r0,r2,lsr#3	@ sigma0(X[i+1])
+	ldr	r2,[sp,#9*4]
+	eor	r3,r3,r1,lsr#10	@ sigma1(X[i+14])
+	ldr	r1,[sp,#2*4]
+
+	add	r3,r3,r0
+	eor	r0,r7,r7,ror#5	@ from BODY_00_15
+	add	r2,r2,r3
+	eor	r0,r0,r7,ror#19	@ Sigma1(e)
+	add	r2,r2,r1			@ X[i]
+	ldr	r3,[r14],#4			@ *K256++
+	add	r10,r10,r2			@ h+=X[i]
+	str	r2,[sp,#9*4]
+	eor	r2,r8,r9
+	add	r10,r10,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r7
+	add	r10,r10,r3			@ h+=K256[i]
+	eor	r2,r2,r9			@ Ch(e,f,g)
+	eor	r0,r11,r11,ror#11
+	add	r10,r10,r2			@ h+=Ch(e,f,g)
+#if 25==31
+	and	r3,r3,#0xff
+	cmp	r3,#0xf2			@ done?
+#endif
+#if 25<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r11,r4			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#11*4]		@ from future BODY_16_xx
+	eor	r3,r11,r4			@ a^b, b^c in next round
+	ldr	r1,[sp,#8*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r11,ror#20	@ Sigma0(a)
+	and	r12,r12,r3			@ (b^c)&=(a^b)
+	add	r6,r6,r10			@ d+=h
+	eor	r12,r12,r4			@ Maj(a,b,c)
+	add	r10,r10,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r10,r10,r12			@ h+=Maj(a,b,c)
+	@ ldr	r2,[sp,#11*4]		@ 26
+	@ ldr	r1,[sp,#8*4]
+	mov	r0,r2,ror#7
+	add	r10,r10,r12			@ h+=Maj(a,b,c) from the past
+	mov	r12,r1,ror#17
+	eor	r0,r0,r2,ror#18
+	eor	r12,r12,r1,ror#19
+	eor	r0,r0,r2,lsr#3	@ sigma0(X[i+1])
+	ldr	r2,[sp,#10*4]
+	eor	r12,r12,r1,lsr#10	@ sigma1(X[i+14])
+	ldr	r1,[sp,#3*4]
+
+	add	r12,r12,r0
+	eor	r0,r6,r6,ror#5	@ from BODY_00_15
+	add	r2,r2,r12
+	eor	r0,r0,r6,ror#19	@ Sigma1(e)
+	add	r2,r2,r1			@ X[i]
+	ldr	r12,[r14],#4			@ *K256++
+	add	r9,r9,r2			@ h+=X[i]
+	str	r2,[sp,#10*4]
+	eor	r2,r7,r8
+	add	r9,r9,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r6
+	add	r9,r9,r12			@ h+=K256[i]
+	eor	r2,r2,r8			@ Ch(e,f,g)
+	eor	r0,r10,r10,ror#11
+	add	r9,r9,r2			@ h+=Ch(e,f,g)
+#if 26==31
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2			@ done?
+#endif
+#if 26<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r12,r10,r11			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#12*4]		@ from future BODY_16_xx
+	eor	r12,r10,r11			@ a^b, b^c in next round
+	ldr	r1,[sp,#9*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r10,ror#20	@ Sigma0(a)
+	and	r3,r3,r12			@ (b^c)&=(a^b)
+	add	r5,r5,r9			@ d+=h
+	eor	r3,r3,r11			@ Maj(a,b,c)
+	add	r9,r9,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r9,r9,r3			@ h+=Maj(a,b,c)
+	@ ldr	r2,[sp,#12*4]		@ 27
+	@ ldr	r1,[sp,#9*4]
+	mov	r0,r2,ror#7
+	add	r9,r9,r3			@ h+=Maj(a,b,c) from the past
+	mov	r3,r1,ror#17
+	eor	r0,r0,r2,ror#18
+	eor	r3,r3,r1,ror#19
+	eor	r0,r0,r2,lsr#3	@ sigma0(X[i+1])
+	ldr	r2,[sp,#11*4]
+	eor	r3,r3,r1,lsr#10	@ sigma1(X[i+14])
+	ldr	r1,[sp,#4*4]
+
+	add	r3,r3,r0
+	eor	r0,r5,r5,ror#5	@ from BODY_00_15
+	add	r2,r2,r3
+	eor	r0,r0,r5,ror#19	@ Sigma1(e)
+	add	r2,r2,r1			@ X[i]
+	ldr	r3,[r14],#4			@ *K256++
+	add	r8,r8,r2			@ h+=X[i]
+	str	r2,[sp,#11*4]
+	eor	r2,r6,r7
+	add	r8,r8,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r5
+	add	r8,r8,r3			@ h+=K256[i]
+	eor	r2,r2,r7			@ Ch(e,f,g)
+	eor	r0,r9,r9,ror#11
+	add	r8,r8,r2			@ h+=Ch(e,f,g)
+#if 27==31
+	and	r3,r3,#0xff
+	cmp	r3,#0xf2			@ done?
+#endif
+#if 27<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r9,r10			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#13*4]		@ from future BODY_16_xx
+	eor	r3,r9,r10			@ a^b, b^c in next round
+	ldr	r1,[sp,#10*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r9,ror#20	@ Sigma0(a)
+	and	r12,r12,r3			@ (b^c)&=(a^b)
+	add	r4,r4,r8			@ d+=h
+	eor	r12,r12,r10			@ Maj(a,b,c)
+	add	r8,r8,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r8,r8,r12			@ h+=Maj(a,b,c)
+	@ ldr	r2,[sp,#13*4]		@ 28
+	@ ldr	r1,[sp,#10*4]
+	mov	r0,r2,ror#7
+	add	r8,r8,r12			@ h+=Maj(a,b,c) from the past
+	mov	r12,r1,ror#17
+	eor	r0,r0,r2,ror#18
+	eor	r12,r12,r1,ror#19
+	eor	r0,r0,r2,lsr#3	@ sigma0(X[i+1])
+	ldr	r2,[sp,#12*4]
+	eor	r12,r12,r1,lsr#10	@ sigma1(X[i+14])
+	ldr	r1,[sp,#5*4]
+
+	add	r12,r12,r0
+	eor	r0,r4,r4,ror#5	@ from BODY_00_15
+	add	r2,r2,r12
+	eor	r0,r0,r4,ror#19	@ Sigma1(e)
+	add	r2,r2,r1			@ X[i]
+	ldr	r12,[r14],#4			@ *K256++
+	add	r7,r7,r2			@ h+=X[i]
+	str	r2,[sp,#12*4]
+	eor	r2,r5,r6
+	add	r7,r7,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r4
+	add	r7,r7,r12			@ h+=K256[i]
+	eor	r2,r2,r6			@ Ch(e,f,g)
+	eor	r0,r8,r8,ror#11
+	add	r7,r7,r2			@ h+=Ch(e,f,g)
+#if 28==31
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2			@ done?
+#endif
+#if 28<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r12,r8,r9			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#14*4]		@ from future BODY_16_xx
+	eor	r12,r8,r9			@ a^b, b^c in next round
+	ldr	r1,[sp,#11*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r8,ror#20	@ Sigma0(a)
+	and	r3,r3,r12			@ (b^c)&=(a^b)
+	add	r11,r11,r7			@ d+=h
+	eor	r3,r3,r9			@ Maj(a,b,c)
+	add	r7,r7,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r7,r7,r3			@ h+=Maj(a,b,c)
+	@ ldr	r2,[sp,#14*4]		@ 29
+	@ ldr	r1,[sp,#11*4]
+	mov	r0,r2,ror#7
+	add	r7,r7,r3			@ h+=Maj(a,b,c) from the past
+	mov	r3,r1,ror#17
+	eor	r0,r0,r2,ror#18
+	eor	r3,r3,r1,ror#19
+	eor	r0,r0,r2,lsr#3	@ sigma0(X[i+1])
+	ldr	r2,[sp,#13*4]
+	eor	r3,r3,r1,lsr#10	@ sigma1(X[i+14])
+	ldr	r1,[sp,#6*4]
+
+	add	r3,r3,r0
+	eor	r0,r11,r11,ror#5	@ from BODY_00_15
+	add	r2,r2,r3
+	eor	r0,r0,r11,ror#19	@ Sigma1(e)
+	add	r2,r2,r1			@ X[i]
+	ldr	r3,[r14],#4			@ *K256++
+	add	r6,r6,r2			@ h+=X[i]
+	str	r2,[sp,#13*4]
+	eor	r2,r4,r5
+	add	r6,r6,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r11
+	add	r6,r6,r3			@ h+=K256[i]
+	eor	r2,r2,r5			@ Ch(e,f,g)
+	eor	r0,r7,r7,ror#11
+	add	r6,r6,r2			@ h+=Ch(e,f,g)
+#if 29==31
+	and	r3,r3,#0xff
+	cmp	r3,#0xf2			@ done?
+#endif
+#if 29<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r7,r8			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#15*4]		@ from future BODY_16_xx
+	eor	r3,r7,r8			@ a^b, b^c in next round
+	ldr	r1,[sp,#12*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r7,ror#20	@ Sigma0(a)
+	and	r12,r12,r3			@ (b^c)&=(a^b)
+	add	r10,r10,r6			@ d+=h
+	eor	r12,r12,r8			@ Maj(a,b,c)
+	add	r6,r6,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r6,r6,r12			@ h+=Maj(a,b,c)
+	@ ldr	r2,[sp,#15*4]		@ 30
+	@ ldr	r1,[sp,#12*4]
+	mov	r0,r2,ror#7
+	add	r6,r6,r12			@ h+=Maj(a,b,c) from the past
+	mov	r12,r1,ror#17
+	eor	r0,r0,r2,ror#18
+	eor	r12,r12,r1,ror#19
+	eor	r0,r0,r2,lsr#3	@ sigma0(X[i+1])
+	ldr	r2,[sp,#14*4]
+	eor	r12,r12,r1,lsr#10	@ sigma1(X[i+14])
+	ldr	r1,[sp,#7*4]
+
+	add	r12,r12,r0
+	eor	r0,r10,r10,ror#5	@ from BODY_00_15
+	add	r2,r2,r12
+	eor	r0,r0,r10,ror#19	@ Sigma1(e)
+	add	r2,r2,r1			@ X[i]
+	ldr	r12,[r14],#4			@ *K256++
+	add	r5,r5,r2			@ h+=X[i]
+	str	r2,[sp,#14*4]
+	eor	r2,r11,r4
+	add	r5,r5,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r10
+	add	r5,r5,r12			@ h+=K256[i]
+	eor	r2,r2,r4			@ Ch(e,f,g)
+	eor	r0,r6,r6,ror#11
+	add	r5,r5,r2			@ h+=Ch(e,f,g)
+#if 30==31
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2			@ done?
+#endif
+#if 30<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r12,r6,r7			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#0*4]		@ from future BODY_16_xx
+	eor	r12,r6,r7			@ a^b, b^c in next round
+	ldr	r1,[sp,#13*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r6,ror#20	@ Sigma0(a)
+	and	r3,r3,r12			@ (b^c)&=(a^b)
+	add	r9,r9,r5			@ d+=h
+	eor	r3,r3,r7			@ Maj(a,b,c)
+	add	r5,r5,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r5,r5,r3			@ h+=Maj(a,b,c)
+	@ ldr	r2,[sp,#0*4]		@ 31
+	@ ldr	r1,[sp,#13*4]
+	mov	r0,r2,ror#7
+	add	r5,r5,r3			@ h+=Maj(a,b,c) from the past
+	mov	r3,r1,ror#17
+	eor	r0,r0,r2,ror#18
+	eor	r3,r3,r1,ror#19
+	eor	r0,r0,r2,lsr#3	@ sigma0(X[i+1])
+	ldr	r2,[sp,#15*4]
+	eor	r3,r3,r1,lsr#10	@ sigma1(X[i+14])
+	ldr	r1,[sp,#8*4]
+
+	add	r3,r3,r0
+	eor	r0,r9,r9,ror#5	@ from BODY_00_15
+	add	r2,r2,r3
+	eor	r0,r0,r9,ror#19	@ Sigma1(e)
+	add	r2,r2,r1			@ X[i]
+	ldr	r3,[r14],#4			@ *K256++
+	add	r4,r4,r2			@ h+=X[i]
+	str	r2,[sp,#15*4]
+	eor	r2,r10,r11
+	add	r4,r4,r0,ror#6	@ h+=Sigma1(e)
+	and	r2,r2,r9
+	add	r4,r4,r3			@ h+=K256[i]
+	eor	r2,r2,r11			@ Ch(e,f,g)
+	eor	r0,r5,r5,ror#11
+	add	r4,r4,r2			@ h+=Ch(e,f,g)
+#if 31==31
+	and	r3,r3,#0xff
+	cmp	r3,#0xf2			@ done?
+#endif
+#if 31<15
+# if __ARM_ARCH__>=7
+	ldr	r2,[r1],#4			@ prefetch
+# else
+	ldrb	r2,[r1,#3]
+# endif
+	eor	r3,r5,r6			@ a^b, b^c in next round
+#else
+	ldr	r2,[sp,#1*4]		@ from future BODY_16_xx
+	eor	r3,r5,r6			@ a^b, b^c in next round
+	ldr	r1,[sp,#14*4]	@ from future BODY_16_xx
+#endif
+	eor	r0,r0,r5,ror#20	@ Sigma0(a)
+	and	r12,r12,r3			@ (b^c)&=(a^b)
+	add	r8,r8,r4			@ d+=h
+	eor	r12,r12,r6			@ Maj(a,b,c)
+	add	r4,r4,r0,ror#2	@ h+=Sigma0(a)
+	@ add	r4,r4,r12			@ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+	ite	eq			@ Thumb2 thing, sanity check in ARM
+#endif
+	ldreq	r3,[sp,#16*4]		@ pull ctx
+	bne	Lrounds_16_xx
+
+	add	r4,r4,r12		@ h+=Maj(a,b,c) from the past
+	ldr	r0,[r3,#0]
+	ldr	r2,[r3,#4]
+	ldr	r12,[r3,#8]
+	add	r4,r4,r0
+	ldr	r0,[r3,#12]
+	add	r5,r5,r2
+	ldr	r2,[r3,#16]
+	add	r6,r6,r12
+	ldr	r12,[r3,#20]
+	add	r7,r7,r0
+	ldr	r0,[r3,#24]
+	add	r8,r8,r2
+	ldr	r2,[r3,#28]
+	add	r9,r9,r12
+	ldr	r1,[sp,#17*4]		@ pull inp
+	ldr	r12,[sp,#18*4]		@ pull inp+len
+	add	r10,r10,r0
+	add	r11,r11,r2
+	stmia	r3,{r4,r5,r6,r7,r8,r9,r10,r11}
+	cmp	r1,r12
+	sub	r14,r14,#256	@ rewind Ktbl
+	bne	Loop
+
+	add	sp,sp,#19*4	@ destroy frame
+#if __ARM_ARCH__>=5
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,pc}
+#else
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,lr}
+	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+
+#if __ARM_MAX_ARCH__>=7
+
+
+
+.globl	_sha256_block_data_order_neon
+.private_extern	_sha256_block_data_order_neon
+
+.align	5
+.skip	16
+_sha256_block_data_order_neon:
+LNEON:
+	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
+
+	sub	r11,sp,#16*4+16
+	adr	r14,K256
+	bic	r11,r11,#15		@ align for 128-bit stores
+	mov	r12,sp
+	mov	sp,r11			@ alloca
+	add	r2,r1,r2,lsl#6	@ len to point at the end of inp
+
+	vld1.8	{q0},[r1]!
+	vld1.8	{q1},[r1]!
+	vld1.8	{q2},[r1]!
+	vld1.8	{q3},[r1]!
+	vld1.32	{q8},[r14,:128]!
+	vld1.32	{q9},[r14,:128]!
+	vld1.32	{q10},[r14,:128]!
+	vld1.32	{q11},[r14,:128]!
+	vrev32.8	q0,q0		@ yes, even on
+	str	r0,[sp,#64]
+	vrev32.8	q1,q1		@ big-endian
+	str	r1,[sp,#68]
+	mov	r1,sp
+	vrev32.8	q2,q2
+	str	r2,[sp,#72]
+	vrev32.8	q3,q3
+	str	r12,[sp,#76]		@ save original sp
+	vadd.i32	q8,q8,q0
+	vadd.i32	q9,q9,q1
+	vst1.32	{q8},[r1,:128]!
+	vadd.i32	q10,q10,q2
+	vst1.32	{q9},[r1,:128]!
+	vadd.i32	q11,q11,q3
+	vst1.32	{q10},[r1,:128]!
+	vst1.32	{q11},[r1,:128]!
+
+	ldmia	r0,{r4,r5,r6,r7,r8,r9,r10,r11}
+	sub	r1,r1,#64
+	ldr	r2,[sp,#0]
+	eor	r12,r12,r12
+	eor	r3,r5,r6
+	b	L_00_48
+
+.align	4
+L_00_48:
+	vext.8	q8,q0,q1,#4
+	add	r11,r11,r2
+	eor	r2,r9,r10
+	eor	r0,r8,r8,ror#5
+	vext.8	q9,q2,q3,#4
+	add	r4,r4,r12
+	and	r2,r2,r8
+	eor	r12,r0,r8,ror#19
+	vshr.u32	q10,q8,#7
+	eor	r0,r4,r4,ror#11
+	eor	r2,r2,r10
+	vadd.i32	q0,q0,q9
+	add	r11,r11,r12,ror#6
+	eor	r12,r4,r5
+	vshr.u32	q9,q8,#3
+	eor	r0,r0,r4,ror#20
+	add	r11,r11,r2
+	vsli.32	q10,q8,#25
+	ldr	r2,[sp,#4]
+	and	r3,r3,r12
+	vshr.u32	q11,q8,#18
+	add	r7,r7,r11
+	add	r11,r11,r0,ror#2
+	eor	r3,r3,r5
+	veor	q9,q9,q10
+	add	r10,r10,r2
+	vsli.32	q11,q8,#14
+	eor	r2,r8,r9
+	eor	r0,r7,r7,ror#5
+	vshr.u32	d24,d7,#17
+	add	r11,r11,r3
+	and	r2,r2,r7
+	veor	q9,q9,q11
+	eor	r3,r0,r7,ror#19
+	eor	r0,r11,r11,ror#11
+	vsli.32	d24,d7,#15
+	eor	r2,r2,r9
+	add	r10,r10,r3,ror#6
+	vshr.u32	d25,d7,#10
+	eor	r3,r11,r4
+	eor	r0,r0,r11,ror#20
+	vadd.i32	q0,q0,q9
+	add	r10,r10,r2
+	ldr	r2,[sp,#8]
+	veor	d25,d25,d24
+	and	r12,r12,r3
+	add	r6,r6,r10
+	vshr.u32	d24,d7,#19
+	add	r10,r10,r0,ror#2
+	eor	r12,r12,r4
+	vsli.32	d24,d7,#13
+	add	r9,r9,r2
+	eor	r2,r7,r8
+	veor	d25,d25,d24
+	eor	r0,r6,r6,ror#5
+	add	r10,r10,r12
+	vadd.i32	d0,d0,d25
+	and	r2,r2,r6
+	eor	r12,r0,r6,ror#19
+	vshr.u32	d24,d0,#17
+	eor	r0,r10,r10,ror#11
+	eor	r2,r2,r8
+	vsli.32	d24,d0,#15
+	add	r9,r9,r12,ror#6
+	eor	r12,r10,r11
+	vshr.u32	d25,d0,#10
+	eor	r0,r0,r10,ror#20
+	add	r9,r9,r2
+	veor	d25,d25,d24
+	ldr	r2,[sp,#12]
+	and	r3,r3,r12
+	vshr.u32	d24,d0,#19
+	add	r5,r5,r9
+	add	r9,r9,r0,ror#2
+	eor	r3,r3,r11
+	vld1.32	{q8},[r14,:128]!
+	add	r8,r8,r2
+	vsli.32	d24,d0,#13
+	eor	r2,r6,r7
+	eor	r0,r5,r5,ror#5
+	veor	d25,d25,d24
+	add	r9,r9,r3
+	and	r2,r2,r5
+	vadd.i32	d1,d1,d25
+	eor	r3,r0,r5,ror#19
+	eor	r0,r9,r9,ror#11
+	vadd.i32	q8,q8,q0
+	eor	r2,r2,r7
+	add	r8,r8,r3,ror#6
+	eor	r3,r9,r10
+	eor	r0,r0,r9,ror#20
+	add	r8,r8,r2
+	ldr	r2,[sp,#16]
+	and	r12,r12,r3
+	add	r4,r4,r8
+	vst1.32	{q8},[r1,:128]!
+	add	r8,r8,r0,ror#2
+	eor	r12,r12,r10
+	vext.8	q8,q1,q2,#4
+	add	r7,r7,r2
+	eor	r2,r5,r6
+	eor	r0,r4,r4,ror#5
+	vext.8	q9,q3,q0,#4
+	add	r8,r8,r12
+	and	r2,r2,r4
+	eor	r12,r0,r4,ror#19
+	vshr.u32	q10,q8,#7
+	eor	r0,r8,r8,ror#11
+	eor	r2,r2,r6
+	vadd.i32	q1,q1,q9
+	add	r7,r7,r12,ror#6
+	eor	r12,r8,r9
+	vshr.u32	q9,q8,#3
+	eor	r0,r0,r8,ror#20
+	add	r7,r7,r2
+	vsli.32	q10,q8,#25
+	ldr	r2,[sp,#20]
+	and	r3,r3,r12
+	vshr.u32	q11,q8,#18
+	add	r11,r11,r7
+	add	r7,r7,r0,ror#2
+	eor	r3,r3,r9
+	veor	q9,q9,q10
+	add	r6,r6,r2
+	vsli.32	q11,q8,#14
+	eor	r2,r4,r5
+	eor	r0,r11,r11,ror#5
+	vshr.u32	d24,d1,#17
+	add	r7,r7,r3
+	and	r2,r2,r11
+	veor	q9,q9,q11
+	eor	r3,r0,r11,ror#19
+	eor	r0,r7,r7,ror#11
+	vsli.32	d24,d1,#15
+	eor	r2,r2,r5
+	add	r6,r6,r3,ror#6
+	vshr.u32	d25,d1,#10
+	eor	r3,r7,r8
+	eor	r0,r0,r7,ror#20
+	vadd.i32	q1,q1,q9
+	add	r6,r6,r2
+	ldr	r2,[sp,#24]
+	veor	d25,d25,d24
+	and	r12,r12,r3
+	add	r10,r10,r6
+	vshr.u32	d24,d1,#19
+	add	r6,r6,r0,ror#2
+	eor	r12,r12,r8
+	vsli.32	d24,d1,#13
+	add	r5,r5,r2
+	eor	r2,r11,r4
+	veor	d25,d25,d24
+	eor	r0,r10,r10,ror#5
+	add	r6,r6,r12
+	vadd.i32	d2,d2,d25
+	and	r2,r2,r10
+	eor	r12,r0,r10,ror#19
+	vshr.u32	d24,d2,#17
+	eor	r0,r6,r6,ror#11
+	eor	r2,r2,r4
+	vsli.32	d24,d2,#15
+	add	r5,r5,r12,ror#6
+	eor	r12,r6,r7
+	vshr.u32	d25,d2,#10
+	eor	r0,r0,r6,ror#20
+	add	r5,r5,r2
+	veor	d25,d25,d24
+	ldr	r2,[sp,#28]
+	and	r3,r3,r12
+	vshr.u32	d24,d2,#19
+	add	r9,r9,r5
+	add	r5,r5,r0,ror#2
+	eor	r3,r3,r7
+	vld1.32	{q8},[r14,:128]!
+	add	r4,r4,r2
+	vsli.32	d24,d2,#13
+	eor	r2,r10,r11
+	eor	r0,r9,r9,ror#5
+	veor	d25,d25,d24
+	add	r5,r5,r3
+	and	r2,r2,r9
+	vadd.i32	d3,d3,d25
+	eor	r3,r0,r9,ror#19
+	eor	r0,r5,r5,ror#11
+	vadd.i32	q8,q8,q1
+	eor	r2,r2,r11
+	add	r4,r4,r3,ror#6
+	eor	r3,r5,r6
+	eor	r0,r0,r5,ror#20
+	add	r4,r4,r2
+	ldr	r2,[sp,#32]
+	and	r12,r12,r3
+	add	r8,r8,r4
+	vst1.32	{q8},[r1,:128]!
+	add	r4,r4,r0,ror#2
+	eor	r12,r12,r6
+	vext.8	q8,q2,q3,#4
+	add	r11,r11,r2
+	eor	r2,r9,r10
+	eor	r0,r8,r8,ror#5
+	vext.8	q9,q0,q1,#4
+	add	r4,r4,r12
+	and	r2,r2,r8
+	eor	r12,r0,r8,ror#19
+	vshr.u32	q10,q8,#7
+	eor	r0,r4,r4,ror#11
+	eor	r2,r2,r10
+	vadd.i32	q2,q2,q9
+	add	r11,r11,r12,ror#6
+	eor	r12,r4,r5
+	vshr.u32	q9,q8,#3
+	eor	r0,r0,r4,ror#20
+	add	r11,r11,r2
+	vsli.32	q10,q8,#25
+	ldr	r2,[sp,#36]
+	and	r3,r3,r12
+	vshr.u32	q11,q8,#18
+	add	r7,r7,r11
+	add	r11,r11,r0,ror#2
+	eor	r3,r3,r5
+	veor	q9,q9,q10
+	add	r10,r10,r2
+	vsli.32	q11,q8,#14
+	eor	r2,r8,r9
+	eor	r0,r7,r7,ror#5
+	vshr.u32	d24,d3,#17
+	add	r11,r11,r3
+	and	r2,r2,r7
+	veor	q9,q9,q11
+	eor	r3,r0,r7,ror#19
+	eor	r0,r11,r11,ror#11
+	vsli.32	d24,d3,#15
+	eor	r2,r2,r9
+	add	r10,r10,r3,ror#6
+	vshr.u32	d25,d3,#10
+	eor	r3,r11,r4
+	eor	r0,r0,r11,ror#20
+	vadd.i32	q2,q2,q9
+	add	r10,r10,r2
+	ldr	r2,[sp,#40]
+	veor	d25,d25,d24
+	and	r12,r12,r3
+	add	r6,r6,r10
+	vshr.u32	d24,d3,#19
+	add	r10,r10,r0,ror#2
+	eor	r12,r12,r4
+	vsli.32	d24,d3,#13
+	add	r9,r9,r2
+	eor	r2,r7,r8
+	veor	d25,d25,d24
+	eor	r0,r6,r6,ror#5
+	add	r10,r10,r12
+	vadd.i32	d4,d4,d25
+	and	r2,r2,r6
+	eor	r12,r0,r6,ror#19
+	vshr.u32	d24,d4,#17
+	eor	r0,r10,r10,ror#11
+	eor	r2,r2,r8
+	vsli.32	d24,d4,#15
+	add	r9,r9,r12,ror#6
+	eor	r12,r10,r11
+	vshr.u32	d25,d4,#10
+	eor	r0,r0,r10,ror#20
+	add	r9,r9,r2
+	veor	d25,d25,d24
+	ldr	r2,[sp,#44]
+	and	r3,r3,r12
+	vshr.u32	d24,d4,#19
+	add	r5,r5,r9
+	add	r9,r9,r0,ror#2
+	eor	r3,r3,r11
+	vld1.32	{q8},[r14,:128]!
+	add	r8,r8,r2
+	vsli.32	d24,d4,#13
+	eor	r2,r6,r7
+	eor	r0,r5,r5,ror#5
+	veor	d25,d25,d24
+	add	r9,r9,r3
+	and	r2,r2,r5
+	vadd.i32	d5,d5,d25
+	eor	r3,r0,r5,ror#19
+	eor	r0,r9,r9,ror#11
+	vadd.i32	q8,q8,q2
+	eor	r2,r2,r7
+	add	r8,r8,r3,ror#6
+	eor	r3,r9,r10
+	eor	r0,r0,r9,ror#20
+	add	r8,r8,r2
+	ldr	r2,[sp,#48]
+	and	r12,r12,r3
+	add	r4,r4,r8
+	vst1.32	{q8},[r1,:128]!
+	add	r8,r8,r0,ror#2
+	eor	r12,r12,r10
+	vext.8	q8,q3,q0,#4
+	add	r7,r7,r2
+	eor	r2,r5,r6
+	eor	r0,r4,r4,ror#5
+	vext.8	q9,q1,q2,#4
+	add	r8,r8,r12
+	and	r2,r2,r4
+	eor	r12,r0,r4,ror#19
+	vshr.u32	q10,q8,#7
+	eor	r0,r8,r8,ror#11
+	eor	r2,r2,r6
+	vadd.i32	q3,q3,q9
+	add	r7,r7,r12,ror#6
+	eor	r12,r8,r9
+	vshr.u32	q9,q8,#3
+	eor	r0,r0,r8,ror#20
+	add	r7,r7,r2
+	vsli.32	q10,q8,#25
+	ldr	r2,[sp,#52]
+	and	r3,r3,r12
+	vshr.u32	q11,q8,#18
+	add	r11,r11,r7
+	add	r7,r7,r0,ror#2
+	eor	r3,r3,r9
+	veor	q9,q9,q10
+	add	r6,r6,r2
+	vsli.32	q11,q8,#14
+	eor	r2,r4,r5
+	eor	r0,r11,r11,ror#5
+	vshr.u32	d24,d5,#17
+	add	r7,r7,r3
+	and	r2,r2,r11
+	veor	q9,q9,q11
+	eor	r3,r0,r11,ror#19
+	eor	r0,r7,r7,ror#11
+	vsli.32	d24,d5,#15
+	eor	r2,r2,r5
+	add	r6,r6,r3,ror#6
+	vshr.u32	d25,d5,#10
+	eor	r3,r7,r8
+	eor	r0,r0,r7,ror#20
+	vadd.i32	q3,q3,q9
+	add	r6,r6,r2
+	ldr	r2,[sp,#56]
+	veor	d25,d25,d24
+	and	r12,r12,r3
+	add	r10,r10,r6
+	vshr.u32	d24,d5,#19
+	add	r6,r6,r0,ror#2
+	eor	r12,r12,r8
+	vsli.32	d24,d5,#13
+	add	r5,r5,r2
+	eor	r2,r11,r4
+	veor	d25,d25,d24
+	eor	r0,r10,r10,ror#5
+	add	r6,r6,r12
+	vadd.i32	d6,d6,d25
+	and	r2,r2,r10
+	eor	r12,r0,r10,ror#19
+	vshr.u32	d24,d6,#17
+	eor	r0,r6,r6,ror#11
+	eor	r2,r2,r4
+	vsli.32	d24,d6,#15
+	add	r5,r5,r12,ror#6
+	eor	r12,r6,r7
+	vshr.u32	d25,d6,#10
+	eor	r0,r0,r6,ror#20
+	add	r5,r5,r2
+	veor	d25,d25,d24
+	ldr	r2,[sp,#60]
+	and	r3,r3,r12
+	vshr.u32	d24,d6,#19
+	add	r9,r9,r5
+	add	r5,r5,r0,ror#2
+	eor	r3,r3,r7
+	vld1.32	{q8},[r14,:128]!
+	add	r4,r4,r2
+	vsli.32	d24,d6,#13
+	eor	r2,r10,r11
+	eor	r0,r9,r9,ror#5
+	veor	d25,d25,d24
+	add	r5,r5,r3
+	and	r2,r2,r9
+	vadd.i32	d7,d7,d25
+	eor	r3,r0,r9,ror#19
+	eor	r0,r5,r5,ror#11
+	vadd.i32	q8,q8,q3
+	eor	r2,r2,r11
+	add	r4,r4,r3,ror#6
+	eor	r3,r5,r6
+	eor	r0,r0,r5,ror#20
+	add	r4,r4,r2
+	ldr	r2,[r14]
+	and	r12,r12,r3
+	add	r8,r8,r4
+	vst1.32	{q8},[r1,:128]!
+	add	r4,r4,r0,ror#2
+	eor	r12,r12,r6
+	teq	r2,#0				@ check for K256 terminator
+	ldr	r2,[sp,#0]
+	sub	r1,r1,#64
+	bne	L_00_48
+
+	ldr	r1,[sp,#68]
+	ldr	r0,[sp,#72]
+	sub	r14,r14,#256	@ rewind r14
+	teq	r1,r0
+	it	eq
+	subeq	r1,r1,#64		@ avoid SEGV
+	vld1.8	{q0},[r1]!		@ load next input block
+	vld1.8	{q1},[r1]!
+	vld1.8	{q2},[r1]!
+	vld1.8	{q3},[r1]!
+	it	ne
+	strne	r1,[sp,#68]
+	mov	r1,sp
+	add	r11,r11,r2
+	eor	r2,r9,r10
+	eor	r0,r8,r8,ror#5
+	add	r4,r4,r12
+	vld1.32	{q8},[r14,:128]!
+	and	r2,r2,r8
+	eor	r12,r0,r8,ror#19
+	eor	r0,r4,r4,ror#11
+	eor	r2,r2,r10
+	vrev32.8	q0,q0
+	add	r11,r11,r12,ror#6
+	eor	r12,r4,r5
+	eor	r0,r0,r4,ror#20
+	add	r11,r11,r2
+	vadd.i32	q8,q8,q0
+	ldr	r2,[sp,#4]
+	and	r3,r3,r12
+	add	r7,r7,r11
+	add	r11,r11,r0,ror#2
+	eor	r3,r3,r5
+	add	r10,r10,r2
+	eor	r2,r8,r9
+	eor	r0,r7,r7,ror#5
+	add	r11,r11,r3
+	and	r2,r2,r7
+	eor	r3,r0,r7,ror#19
+	eor	r0,r11,r11,ror#11
+	eor	r2,r2,r9
+	add	r10,r10,r3,ror#6
+	eor	r3,r11,r4
+	eor	r0,r0,r11,ror#20
+	add	r10,r10,r2
+	ldr	r2,[sp,#8]
+	and	r12,r12,r3
+	add	r6,r6,r10
+	add	r10,r10,r0,ror#2
+	eor	r12,r12,r4
+	add	r9,r9,r2
+	eor	r2,r7,r8
+	eor	r0,r6,r6,ror#5
+	add	r10,r10,r12
+	and	r2,r2,r6
+	eor	r12,r0,r6,ror#19
+	eor	r0,r10,r10,ror#11
+	eor	r2,r2,r8
+	add	r9,r9,r12,ror#6
+	eor	r12,r10,r11
+	eor	r0,r0,r10,ror#20
+	add	r9,r9,r2
+	ldr	r2,[sp,#12]
+	and	r3,r3,r12
+	add	r5,r5,r9
+	add	r9,r9,r0,ror#2
+	eor	r3,r3,r11
+	add	r8,r8,r2
+	eor	r2,r6,r7
+	eor	r0,r5,r5,ror#5
+	add	r9,r9,r3
+	and	r2,r2,r5
+	eor	r3,r0,r5,ror#19
+	eor	r0,r9,r9,ror#11
+	eor	r2,r2,r7
+	add	r8,r8,r3,ror#6
+	eor	r3,r9,r10
+	eor	r0,r0,r9,ror#20
+	add	r8,r8,r2
+	ldr	r2,[sp,#16]
+	and	r12,r12,r3
+	add	r4,r4,r8
+	add	r8,r8,r0,ror#2
+	eor	r12,r12,r10
+	vst1.32	{q8},[r1,:128]!
+	add	r7,r7,r2
+	eor	r2,r5,r6
+	eor	r0,r4,r4,ror#5
+	add	r8,r8,r12
+	vld1.32	{q8},[r14,:128]!
+	and	r2,r2,r4
+	eor	r12,r0,r4,ror#19
+	eor	r0,r8,r8,ror#11
+	eor	r2,r2,r6
+	vrev32.8	q1,q1
+	add	r7,r7,r12,ror#6
+	eor	r12,r8,r9
+	eor	r0,r0,r8,ror#20
+	add	r7,r7,r2
+	vadd.i32	q8,q8,q1
+	ldr	r2,[sp,#20]
+	and	r3,r3,r12
+	add	r11,r11,r7
+	add	r7,r7,r0,ror#2
+	eor	r3,r3,r9
+	add	r6,r6,r2
+	eor	r2,r4,r5
+	eor	r0,r11,r11,ror#5
+	add	r7,r7,r3
+	and	r2,r2,r11
+	eor	r3,r0,r11,ror#19
+	eor	r0,r7,r7,ror#11
+	eor	r2,r2,r5
+	add	r6,r6,r3,ror#6
+	eor	r3,r7,r8
+	eor	r0,r0,r7,ror#20
+	add	r6,r6,r2
+	ldr	r2,[sp,#24]
+	and	r12,r12,r3
+	add	r10,r10,r6
+	add	r6,r6,r0,ror#2
+	eor	r12,r12,r8
+	add	r5,r5,r2
+	eor	r2,r11,r4
+	eor	r0,r10,r10,ror#5
+	add	r6,r6,r12
+	and	r2,r2,r10
+	eor	r12,r0,r10,ror#19
+	eor	r0,r6,r6,ror#11
+	eor	r2,r2,r4
+	add	r5,r5,r12,ror#6
+	eor	r12,r6,r7
+	eor	r0,r0,r6,ror#20
+	add	r5,r5,r2
+	ldr	r2,[sp,#28]
+	and	r3,r3,r12
+	add	r9,r9,r5
+	add	r5,r5,r0,ror#2
+	eor	r3,r3,r7
+	add	r4,r4,r2
+	eor	r2,r10,r11
+	eor	r0,r9,r9,ror#5
+	add	r5,r5,r3
+	and	r2,r2,r9
+	eor	r3,r0,r9,ror#19
+	eor	r0,r5,r5,ror#11
+	eor	r2,r2,r11
+	add	r4,r4,r3,ror#6
+	eor	r3,r5,r6
+	eor	r0,r0,r5,ror#20
+	add	r4,r4,r2
+	ldr	r2,[sp,#32]
+	and	r12,r12,r3
+	add	r8,r8,r4
+	add	r4,r4,r0,ror#2
+	eor	r12,r12,r6
+	vst1.32	{q8},[r1,:128]!
+	add	r11,r11,r2
+	eor	r2,r9,r10
+	eor	r0,r8,r8,ror#5
+	add	r4,r4,r12
+	vld1.32	{q8},[r14,:128]!
+	and	r2,r2,r8
+	eor	r12,r0,r8,ror#19
+	eor	r0,r4,r4,ror#11
+	eor	r2,r2,r10
+	vrev32.8	q2,q2
+	add	r11,r11,r12,ror#6
+	eor	r12,r4,r5
+	eor	r0,r0,r4,ror#20
+	add	r11,r11,r2
+	vadd.i32	q8,q8,q2
+	ldr	r2,[sp,#36]
+	and	r3,r3,r12
+	add	r7,r7,r11
+	add	r11,r11,r0,ror#2
+	eor	r3,r3,r5
+	add	r10,r10,r2
+	eor	r2,r8,r9
+	eor	r0,r7,r7,ror#5
+	add	r11,r11,r3
+	and	r2,r2,r7
+	eor	r3,r0,r7,ror#19
+	eor	r0,r11,r11,ror#11
+	eor	r2,r2,r9
+	add	r10,r10,r3,ror#6
+	eor	r3,r11,r4
+	eor	r0,r0,r11,ror#20
+	add	r10,r10,r2
+	ldr	r2,[sp,#40]
+	and	r12,r12,r3
+	add	r6,r6,r10
+	add	r10,r10,r0,ror#2
+	eor	r12,r12,r4
+	add	r9,r9,r2
+	eor	r2,r7,r8
+	eor	r0,r6,r6,ror#5
+	add	r10,r10,r12
+	and	r2,r2,r6
+	eor	r12,r0,r6,ror#19
+	eor	r0,r10,r10,ror#11
+	eor	r2,r2,r8
+	add	r9,r9,r12,ror#6
+	eor	r12,r10,r11
+	eor	r0,r0,r10,ror#20
+	add	r9,r9,r2
+	ldr	r2,[sp,#44]
+	and	r3,r3,r12
+	add	r5,r5,r9
+	add	r9,r9,r0,ror#2
+	eor	r3,r3,r11
+	add	r8,r8,r2
+	eor	r2,r6,r7
+	eor	r0,r5,r5,ror#5
+	add	r9,r9,r3
+	and	r2,r2,r5
+	eor	r3,r0,r5,ror#19
+	eor	r0,r9,r9,ror#11
+	eor	r2,r2,r7
+	add	r8,r8,r3,ror#6
+	eor	r3,r9,r10
+	eor	r0,r0,r9,ror#20
+	add	r8,r8,r2
+	ldr	r2,[sp,#48]
+	and	r12,r12,r3
+	add	r4,r4,r8
+	add	r8,r8,r0,ror#2
+	eor	r12,r12,r10
+	vst1.32	{q8},[r1,:128]!
+	add	r7,r7,r2
+	eor	r2,r5,r6
+	eor	r0,r4,r4,ror#5
+	add	r8,r8,r12
+	vld1.32	{q8},[r14,:128]!
+	and	r2,r2,r4
+	eor	r12,r0,r4,ror#19
+	eor	r0,r8,r8,ror#11
+	eor	r2,r2,r6
+	vrev32.8	q3,q3
+	add	r7,r7,r12,ror#6
+	eor	r12,r8,r9
+	eor	r0,r0,r8,ror#20
+	add	r7,r7,r2
+	vadd.i32	q8,q8,q3
+	ldr	r2,[sp,#52]
+	and	r3,r3,r12
+	add	r11,r11,r7
+	add	r7,r7,r0,ror#2
+	eor	r3,r3,r9
+	add	r6,r6,r2
+	eor	r2,r4,r5
+	eor	r0,r11,r11,ror#5
+	add	r7,r7,r3
+	and	r2,r2,r11
+	eor	r3,r0,r11,ror#19
+	eor	r0,r7,r7,ror#11
+	eor	r2,r2,r5
+	add	r6,r6,r3,ror#6
+	eor	r3,r7,r8
+	eor	r0,r0,r7,ror#20
+	add	r6,r6,r2
+	ldr	r2,[sp,#56]
+	and	r12,r12,r3
+	add	r10,r10,r6
+	add	r6,r6,r0,ror#2
+	eor	r12,r12,r8
+	add	r5,r5,r2
+	eor	r2,r11,r4
+	eor	r0,r10,r10,ror#5
+	add	r6,r6,r12
+	and	r2,r2,r10
+	eor	r12,r0,r10,ror#19
+	eor	r0,r6,r6,ror#11
+	eor	r2,r2,r4
+	add	r5,r5,r12,ror#6
+	eor	r12,r6,r7
+	eor	r0,r0,r6,ror#20
+	add	r5,r5,r2
+	ldr	r2,[sp,#60]
+	and	r3,r3,r12
+	add	r9,r9,r5
+	add	r5,r5,r0,ror#2
+	eor	r3,r3,r7
+	add	r4,r4,r2
+	eor	r2,r10,r11
+	eor	r0,r9,r9,ror#5
+	add	r5,r5,r3
+	and	r2,r2,r9
+	eor	r3,r0,r9,ror#19
+	eor	r0,r5,r5,ror#11
+	eor	r2,r2,r11
+	add	r4,r4,r3,ror#6
+	eor	r3,r5,r6
+	eor	r0,r0,r5,ror#20
+	add	r4,r4,r2
+	ldr	r2,[sp,#64]
+	and	r12,r12,r3
+	add	r8,r8,r4
+	add	r4,r4,r0,ror#2
+	eor	r12,r12,r6
+	vst1.32	{q8},[r1,:128]!
+	ldr	r0,[r2,#0]
+	add	r4,r4,r12			@ h+=Maj(a,b,c) from the past
+	ldr	r12,[r2,#4]
+	ldr	r3,[r2,#8]
+	ldr	r1,[r2,#12]
+	add	r4,r4,r0			@ accumulate
+	ldr	r0,[r2,#16]
+	add	r5,r5,r12
+	ldr	r12,[r2,#20]
+	add	r6,r6,r3
+	ldr	r3,[r2,#24]
+	add	r7,r7,r1
+	ldr	r1,[r2,#28]
+	add	r8,r8,r0
+	str	r4,[r2],#4
+	add	r9,r9,r12
+	str	r5,[r2],#4
+	add	r10,r10,r3
+	str	r6,[r2],#4
+	add	r11,r11,r1
+	str	r7,[r2],#4
+	stmia	r2,{r8,r9,r10,r11}
+
+	ittte	ne
+	movne	r1,sp
+	ldrne	r2,[sp,#0]
+	eorne	r12,r12,r12
+	ldreq	sp,[sp,#76]			@ restore original sp
+	itt	ne
+	eorne	r3,r5,r6
+	bne	L_00_48
+
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
+
+#endif
+#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
+
+# if defined(__thumb2__)
+#  define INST(a,b,c,d)	.byte	c,d|0xc,a,b
+# else
+#  define INST(a,b,c,d)	.byte	a,b,c,d
+# endif
+
+
+.align	5
+sha256_block_data_order_armv8:
+LARMv8:
+	vld1.32	{q0,q1},[r0]
+	sub	r3,r3,#256+32
+	add	r2,r1,r2,lsl#6	@ len to point at the end of inp
+	b	Loop_v8
+
+.align	4
+Loop_v8:
+	vld1.8	{q8,q9},[r1]!
+	vld1.8	{q10,q11},[r1]!
+	vld1.32	{q12},[r3]!
+	vrev32.8	q8,q8
+	vrev32.8	q9,q9
+	vrev32.8	q10,q10
+	vrev32.8	q11,q11
+	vmov	q14,q0	@ offload
+	vmov	q15,q1
+	teq	r1,r2
+	vld1.32	{q13},[r3]!
+	vadd.i32	q12,q12,q8
+	INST(0xe2,0x03,0xfa,0xf3)	@ sha256su0 q8,q9
+	vmov	q2,q0
+	INST(0x68,0x0c,0x02,0xf3)	@ sha256h q0,q1,q12
+	INST(0x68,0x2c,0x14,0xf3)	@ sha256h2 q1,q2,q12
+	INST(0xe6,0x0c,0x64,0xf3)	@ sha256su1 q8,q10,q11
+	vld1.32	{q12},[r3]!
+	vadd.i32	q13,q13,q9
+	INST(0xe4,0x23,0xfa,0xf3)	@ sha256su0 q9,q10
+	vmov	q2,q0
+	INST(0x6a,0x0c,0x02,0xf3)	@ sha256h q0,q1,q13
+	INST(0x6a,0x2c,0x14,0xf3)	@ sha256h2 q1,q2,q13
+	INST(0xe0,0x2c,0x66,0xf3)	@ sha256su1 q9,q11,q8
+	vld1.32	{q13},[r3]!
+	vadd.i32	q12,q12,q10
+	INST(0xe6,0x43,0xfa,0xf3)	@ sha256su0 q10,q11
+	vmov	q2,q0
+	INST(0x68,0x0c,0x02,0xf3)	@ sha256h q0,q1,q12
+	INST(0x68,0x2c,0x14,0xf3)	@ sha256h2 q1,q2,q12
+	INST(0xe2,0x4c,0x60,0xf3)	@ sha256su1 q10,q8,q9
+	vld1.32	{q12},[r3]!
+	vadd.i32	q13,q13,q11
+	INST(0xe0,0x63,0xfa,0xf3)	@ sha256su0 q11,q8
+	vmov	q2,q0
+	INST(0x6a,0x0c,0x02,0xf3)	@ sha256h q0,q1,q13
+	INST(0x6a,0x2c,0x14,0xf3)	@ sha256h2 q1,q2,q13
+	INST(0xe4,0x6c,0x62,0xf3)	@ sha256su1 q11,q9,q10
+	vld1.32	{q13},[r3]!
+	vadd.i32	q12,q12,q8
+	INST(0xe2,0x03,0xfa,0xf3)	@ sha256su0 q8,q9
+	vmov	q2,q0
+	INST(0x68,0x0c,0x02,0xf3)	@ sha256h q0,q1,q12
+	INST(0x68,0x2c,0x14,0xf3)	@ sha256h2 q1,q2,q12
+	INST(0xe6,0x0c,0x64,0xf3)	@ sha256su1 q8,q10,q11
+	vld1.32	{q12},[r3]!
+	vadd.i32	q13,q13,q9
+	INST(0xe4,0x23,0xfa,0xf3)	@ sha256su0 q9,q10
+	vmov	q2,q0
+	INST(0x6a,0x0c,0x02,0xf3)	@ sha256h q0,q1,q13
+	INST(0x6a,0x2c,0x14,0xf3)	@ sha256h2 q1,q2,q13
+	INST(0xe0,0x2c,0x66,0xf3)	@ sha256su1 q9,q11,q8
+	vld1.32	{q13},[r3]!
+	vadd.i32	q12,q12,q10
+	INST(0xe6,0x43,0xfa,0xf3)	@ sha256su0 q10,q11
+	vmov	q2,q0
+	INST(0x68,0x0c,0x02,0xf3)	@ sha256h q0,q1,q12
+	INST(0x68,0x2c,0x14,0xf3)	@ sha256h2 q1,q2,q12
+	INST(0xe2,0x4c,0x60,0xf3)	@ sha256su1 q10,q8,q9
+	vld1.32	{q12},[r3]!
+	vadd.i32	q13,q13,q11
+	INST(0xe0,0x63,0xfa,0xf3)	@ sha256su0 q11,q8
+	vmov	q2,q0
+	INST(0x6a,0x0c,0x02,0xf3)	@ sha256h q0,q1,q13
+	INST(0x6a,0x2c,0x14,0xf3)	@ sha256h2 q1,q2,q13
+	INST(0xe4,0x6c,0x62,0xf3)	@ sha256su1 q11,q9,q10
+	vld1.32	{q13},[r3]!
+	vadd.i32	q12,q12,q8
+	INST(0xe2,0x03,0xfa,0xf3)	@ sha256su0 q8,q9
+	vmov	q2,q0
+	INST(0x68,0x0c,0x02,0xf3)	@ sha256h q0,q1,q12
+	INST(0x68,0x2c,0x14,0xf3)	@ sha256h2 q1,q2,q12
+	INST(0xe6,0x0c,0x64,0xf3)	@ sha256su1 q8,q10,q11
+	vld1.32	{q12},[r3]!
+	vadd.i32	q13,q13,q9
+	INST(0xe4,0x23,0xfa,0xf3)	@ sha256su0 q9,q10
+	vmov	q2,q0
+	INST(0x6a,0x0c,0x02,0xf3)	@ sha256h q0,q1,q13
+	INST(0x6a,0x2c,0x14,0xf3)	@ sha256h2 q1,q2,q13
+	INST(0xe0,0x2c,0x66,0xf3)	@ sha256su1 q9,q11,q8
+	vld1.32	{q13},[r3]!
+	vadd.i32	q12,q12,q10
+	INST(0xe6,0x43,0xfa,0xf3)	@ sha256su0 q10,q11
+	vmov	q2,q0
+	INST(0x68,0x0c,0x02,0xf3)	@ sha256h q0,q1,q12
+	INST(0x68,0x2c,0x14,0xf3)	@ sha256h2 q1,q2,q12
+	INST(0xe2,0x4c,0x60,0xf3)	@ sha256su1 q10,q8,q9
+	vld1.32	{q12},[r3]!
+	vadd.i32	q13,q13,q11
+	INST(0xe0,0x63,0xfa,0xf3)	@ sha256su0 q11,q8
+	vmov	q2,q0
+	INST(0x6a,0x0c,0x02,0xf3)	@ sha256h q0,q1,q13
+	INST(0x6a,0x2c,0x14,0xf3)	@ sha256h2 q1,q2,q13
+	INST(0xe4,0x6c,0x62,0xf3)	@ sha256su1 q11,q9,q10
+	vld1.32	{q13},[r3]!
+	vadd.i32	q12,q12,q8
+	vmov	q2,q0
+	INST(0x68,0x0c,0x02,0xf3)	@ sha256h q0,q1,q12
+	INST(0x68,0x2c,0x14,0xf3)	@ sha256h2 q1,q2,q12
+
+	vld1.32	{q12},[r3]!
+	vadd.i32	q13,q13,q9
+	vmov	q2,q0
+	INST(0x6a,0x0c,0x02,0xf3)	@ sha256h q0,q1,q13
+	INST(0x6a,0x2c,0x14,0xf3)	@ sha256h2 q1,q2,q13
+
+	vld1.32	{q13},[r3]
+	vadd.i32	q12,q12,q10
+	sub	r3,r3,#256-16	@ rewind
+	vmov	q2,q0
+	INST(0x68,0x0c,0x02,0xf3)	@ sha256h q0,q1,q12
+	INST(0x68,0x2c,0x14,0xf3)	@ sha256h2 q1,q2,q12
+
+	vadd.i32	q13,q13,q11
+	vmov	q2,q0
+	INST(0x6a,0x0c,0x02,0xf3)	@ sha256h q0,q1,q13
+	INST(0x6a,0x2c,0x14,0xf3)	@ sha256h2 q1,q2,q13
+
+	vadd.i32	q0,q0,q14
+	vadd.i32	q1,q1,q15
+	it	ne
+	bne	Loop_v8
+
+	vst1.32	{q0,q1},[r0]
+
+	bx	lr		@ bx lr
+
+#endif
+.byte	83,72,65,50,53,54,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,65,82,77,118,52,47,78,69,79,78,47,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+.align	2
+#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
+.comm	_OPENSSL_armcap_P,4
+.non_lazy_symbol_pointer
+OPENSSL_armcap_P:
+.indirect_symbol	_OPENSSL_armcap_P
+.long	0
+.private_extern	_OPENSSL_armcap_P
+#endif
diff --git a/third_party/boringssl/ios-arm/crypto/fipsmodule/sha512-armv4.S b/third_party/boringssl/ios-arm/crypto/fipsmodule/sha512-armv4.S
new file mode 100644
index 0000000..7bd3d67
--- /dev/null
+++ b/third_party/boringssl/ios-arm/crypto/fipsmodule/sha512-armv4.S
@@ -0,0 +1,1873 @@
+
+@ ====================================================================
+@ Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+@ project. The module is, however, dual licensed under OpenSSL and
+@ CRYPTOGAMS licenses depending on where you obtain it. For further
+@ details see http://www.openssl.org/~appro/cryptogams/.
+@
+@ Permission to use under GPL terms is granted.
+@ ====================================================================
+
+@ SHA512 block procedure for ARMv4. September 2007.
+
+@ This code is ~4.5 (four and a half) times faster than code generated
+@ by gcc 3.4 and it spends ~72 clock cycles per byte [on single-issue
+@ Xscale PXA250 core].
+@
+@ July 2010.
+@
+@ Rescheduling for dual-issue pipeline resulted in 6% improvement on
+@ Cortex A8 core and ~40 cycles per processed byte.
+
+@ February 2011.
+@
+@ Profiler-assisted and platform-specific optimization resulted in 7%
+@ improvement on Coxtex A8 core and ~38 cycles per byte.
+
+@ March 2011.
+@
+@ Add NEON implementation. On Cortex A8 it was measured to process
+@ one byte in 23.3 cycles or ~60% faster than integer-only code.
+
+@ August 2012.
+@
+@ Improve NEON performance by 12% on Snapdragon S4. In absolute
+@ terms it's 22.6 cycles per byte, which is disappointing result.
+@ Technical writers asserted that 3-way S4 pipeline can sustain
+@ multiple NEON instructions per cycle, but dual NEON issue could
+@ not be observed, see http://www.openssl.org/~appro/Snapdragon-S4.html
+@ for further details. On side note Cortex-A15 processes one byte in
+@ 16 cycles.
+
+@ Byte order [in]dependence. =========================================
+@
+@ Originally caller was expected to maintain specific *dword* order in
+@ h[0-7], namely with most significant dword at *lower* address, which
+@ was reflected in below two parameters as 0 and 4. Now caller is
+@ expected to maintain native byte order for whole 64-bit values.
+#ifndef __KERNEL__
+# include <openssl/arm_arch.h>
+# define VFP_ABI_PUSH	vstmdb	sp!,{d8-d15}
+# define VFP_ABI_POP	vldmia	sp!,{d8-d15}
+#else
+# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_MAX_ARCH__ 7
+# define VFP_ABI_PUSH
+# define VFP_ABI_POP
+#endif
+
+#ifdef __ARMEL__
+# define LO 0
+# define HI 4
+# define WORD64(hi0,lo0,hi1,lo1)	.word	lo0,hi0, lo1,hi1
+#else
+# define HI 0
+# define LO 4
+# define WORD64(hi0,lo0,hi1,lo1)	.word	hi0,lo0, hi1,lo1
+#endif
+
+.text
+#if __ARM_ARCH__<7 || defined(__APPLE__)
+.code	32
+#else
+.syntax	unified
+# ifdef __thumb2__
+#  define adrl adr
+.thumb
+# else
+.code	32
+# endif
+#endif
+
+
+.align	5
+K512:
+	WORD64(0x428a2f98,0xd728ae22,	0x71374491,0x23ef65cd)
+	WORD64(0xb5c0fbcf,0xec4d3b2f,	0xe9b5dba5,0x8189dbbc)
+	WORD64(0x3956c25b,0xf348b538,	0x59f111f1,0xb605d019)
+	WORD64(0x923f82a4,0xaf194f9b,	0xab1c5ed5,0xda6d8118)
+	WORD64(0xd807aa98,0xa3030242,	0x12835b01,0x45706fbe)
+	WORD64(0x243185be,0x4ee4b28c,	0x550c7dc3,0xd5ffb4e2)
+	WORD64(0x72be5d74,0xf27b896f,	0x80deb1fe,0x3b1696b1)
+	WORD64(0x9bdc06a7,0x25c71235,	0xc19bf174,0xcf692694)
+	WORD64(0xe49b69c1,0x9ef14ad2,	0xefbe4786,0x384f25e3)
+	WORD64(0x0fc19dc6,0x8b8cd5b5,	0x240ca1cc,0x77ac9c65)
+	WORD64(0x2de92c6f,0x592b0275,	0x4a7484aa,0x6ea6e483)
+	WORD64(0x5cb0a9dc,0xbd41fbd4,	0x76f988da,0x831153b5)
+	WORD64(0x983e5152,0xee66dfab,	0xa831c66d,0x2db43210)
+	WORD64(0xb00327c8,0x98fb213f,	0xbf597fc7,0xbeef0ee4)
+	WORD64(0xc6e00bf3,0x3da88fc2,	0xd5a79147,0x930aa725)
+	WORD64(0x06ca6351,0xe003826f,	0x14292967,0x0a0e6e70)
+	WORD64(0x27b70a85,0x46d22ffc,	0x2e1b2138,0x5c26c926)
+	WORD64(0x4d2c6dfc,0x5ac42aed,	0x53380d13,0x9d95b3df)
+	WORD64(0x650a7354,0x8baf63de,	0x766a0abb,0x3c77b2a8)
+	WORD64(0x81c2c92e,0x47edaee6,	0x92722c85,0x1482353b)
+	WORD64(0xa2bfe8a1,0x4cf10364,	0xa81a664b,0xbc423001)
+	WORD64(0xc24b8b70,0xd0f89791,	0xc76c51a3,0x0654be30)
+	WORD64(0xd192e819,0xd6ef5218,	0xd6990624,0x5565a910)
+	WORD64(0xf40e3585,0x5771202a,	0x106aa070,0x32bbd1b8)
+	WORD64(0x19a4c116,0xb8d2d0c8,	0x1e376c08,0x5141ab53)
+	WORD64(0x2748774c,0xdf8eeb99,	0x34b0bcb5,0xe19b48a8)
+	WORD64(0x391c0cb3,0xc5c95a63,	0x4ed8aa4a,0xe3418acb)
+	WORD64(0x5b9cca4f,0x7763e373,	0x682e6ff3,0xd6b2b8a3)
+	WORD64(0x748f82ee,0x5defb2fc,	0x78a5636f,0x43172f60)
+	WORD64(0x84c87814,0xa1f0ab72,	0x8cc70208,0x1a6439ec)
+	WORD64(0x90befffa,0x23631e28,	0xa4506ceb,0xde82bde9)
+	WORD64(0xbef9a3f7,0xb2c67915,	0xc67178f2,0xe372532b)
+	WORD64(0xca273ece,0xea26619c,	0xd186b8c7,0x21c0c207)
+	WORD64(0xeada7dd6,0xcde0eb1e,	0xf57d4f7f,0xee6ed178)
+	WORD64(0x06f067aa,0x72176fba,	0x0a637dc5,0xa2c898a6)
+	WORD64(0x113f9804,0xbef90dae,	0x1b710b35,0x131c471b)
+	WORD64(0x28db77f5,0x23047d84,	0x32caab7b,0x40c72493)
+	WORD64(0x3c9ebe0a,0x15c9bebc,	0x431d67c4,0x9c100d4c)
+	WORD64(0x4cc5d4be,0xcb3e42b6,	0x597f299c,0xfc657e2a)
+	WORD64(0x5fcb6fab,0x3ad6faec,	0x6c44198c,0x4a475817)
+
+#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
+LOPENSSL_armcap:
+.word	OPENSSL_armcap_P-Lsha512_block_data_order
+.skip	32-4
+#else
+.skip	32
+#endif
+
+.globl	_sha512_block_data_order
+.private_extern	_sha512_block_data_order
+
+_sha512_block_data_order:
+Lsha512_block_data_order:
+#if __ARM_ARCH__<7
+	sub	r3,pc,#8		@ _sha512_block_data_order
+#else
+	adr	r3,_sha512_block_data_order
+#endif
+#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
+	ldr	r12,LOPENSSL_armcap
+	ldr	r12,[r3,r12]		@ OPENSSL_armcap_P
+#ifdef	__APPLE__
+	ldr	r12,[r12]
+#endif
+	tst	r12,#ARMV7_NEON
+	bne	LNEON
+#endif
+	add	r2,r1,r2,lsl#7	@ len to point at the end of inp
+	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
+	sub	r14,r3,#672		@ K512
+	sub	sp,sp,#9*8
+
+	ldr	r7,[r0,#32+LO]
+	ldr	r8,[r0,#32+HI]
+	ldr	r9, [r0,#48+LO]
+	ldr	r10, [r0,#48+HI]
+	ldr	r11, [r0,#56+LO]
+	ldr	r12, [r0,#56+HI]
+Loop:
+	str	r9, [sp,#48+0]
+	str	r10, [sp,#48+4]
+	str	r11, [sp,#56+0]
+	str	r12, [sp,#56+4]
+	ldr	r5,[r0,#0+LO]
+	ldr	r6,[r0,#0+HI]
+	ldr	r3,[r0,#8+LO]
+	ldr	r4,[r0,#8+HI]
+	ldr	r9, [r0,#16+LO]
+	ldr	r10, [r0,#16+HI]
+	ldr	r11, [r0,#24+LO]
+	ldr	r12, [r0,#24+HI]
+	str	r3,[sp,#8+0]
+	str	r4,[sp,#8+4]
+	str	r9, [sp,#16+0]
+	str	r10, [sp,#16+4]
+	str	r11, [sp,#24+0]
+	str	r12, [sp,#24+4]
+	ldr	r3,[r0,#40+LO]
+	ldr	r4,[r0,#40+HI]
+	str	r3,[sp,#40+0]
+	str	r4,[sp,#40+4]
+
+L00_15:
+#if __ARM_ARCH__<7
+	ldrb	r3,[r1,#7]
+	ldrb	r9, [r1,#6]
+	ldrb	r10, [r1,#5]
+	ldrb	r11, [r1,#4]
+	ldrb	r4,[r1,#3]
+	ldrb	r12, [r1,#2]
+	orr	r3,r3,r9,lsl#8
+	ldrb	r9, [r1,#1]
+	orr	r3,r3,r10,lsl#16
+	ldrb	r10, [r1],#8
+	orr	r3,r3,r11,lsl#24
+	orr	r4,r4,r12,lsl#8
+	orr	r4,r4,r9,lsl#16
+	orr	r4,r4,r10,lsl#24
+#else
+	ldr	r3,[r1,#4]
+	ldr	r4,[r1],#8
+#ifdef __ARMEL__
+	rev	r3,r3
+	rev	r4,r4
+#endif
+#endif
+	@ Sigma1(x)	(ROTR((x),14) ^ ROTR((x),18)  ^ ROTR((x),41))
+	@ LO		lo>>14^hi<<18 ^ lo>>18^hi<<14 ^ hi>>9^lo<<23
+	@ HI		hi>>14^lo<<18 ^ hi>>18^lo<<14 ^ lo>>9^hi<<23
+	mov	r9,r7,lsr#14
+	str	r3,[sp,#64+0]
+	mov	r10,r8,lsr#14
+	str	r4,[sp,#64+4]
+	eor	r9,r9,r8,lsl#18
+	ldr	r11,[sp,#56+0]	@ h.lo
+	eor	r10,r10,r7,lsl#18
+	ldr	r12,[sp,#56+4]	@ h.hi
+	eor	r9,r9,r7,lsr#18
+	eor	r10,r10,r8,lsr#18
+	eor	r9,r9,r8,lsl#14
+	eor	r10,r10,r7,lsl#14
+	eor	r9,r9,r8,lsr#9
+	eor	r10,r10,r7,lsr#9
+	eor	r9,r9,r7,lsl#23
+	eor	r10,r10,r8,lsl#23	@ Sigma1(e)
+	adds	r3,r3,r9
+	ldr	r9,[sp,#40+0]	@ f.lo
+	adc	r4,r4,r10		@ T += Sigma1(e)
+	ldr	r10,[sp,#40+4]	@ f.hi
+	adds	r3,r3,r11
+	ldr	r11,[sp,#48+0]	@ g.lo
+	adc	r4,r4,r12		@ T += h
+	ldr	r12,[sp,#48+4]	@ g.hi
+
+	eor	r9,r9,r11
+	str	r7,[sp,#32+0]
+	eor	r10,r10,r12
+	str	r8,[sp,#32+4]
+	and	r9,r9,r7
+	str	r5,[sp,#0+0]
+	and	r10,r10,r8
+	str	r6,[sp,#0+4]
+	eor	r9,r9,r11
+	ldr	r11,[r14,#LO]	@ K[i].lo
+	eor	r10,r10,r12		@ Ch(e,f,g)
+	ldr	r12,[r14,#HI]	@ K[i].hi
+
+	adds	r3,r3,r9
+	ldr	r7,[sp,#24+0]	@ d.lo
+	adc	r4,r4,r10		@ T += Ch(e,f,g)
+	ldr	r8,[sp,#24+4]	@ d.hi
+	adds	r3,r3,r11
+	and	r9,r11,#0xff
+	adc	r4,r4,r12		@ T += K[i]
+	adds	r7,r7,r3
+	ldr	r11,[sp,#8+0]	@ b.lo
+	adc	r8,r8,r4		@ d += T
+	teq	r9,#148
+
+	ldr	r12,[sp,#16+0]	@ c.lo
+#if __ARM_ARCH__>=7
+	it	eq			@ Thumb2 thing, sanity check in ARM
+#endif
+	orreq	r14,r14,#1
+	@ Sigma0(x)	(ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39))
+	@ LO		lo>>28^hi<<4  ^ hi>>2^lo<<30 ^ hi>>7^lo<<25
+	@ HI		hi>>28^lo<<4  ^ lo>>2^hi<<30 ^ lo>>7^hi<<25
+	mov	r9,r5,lsr#28
+	mov	r10,r6,lsr#28
+	eor	r9,r9,r6,lsl#4
+	eor	r10,r10,r5,lsl#4
+	eor	r9,r9,r6,lsr#2
+	eor	r10,r10,r5,lsr#2
+	eor	r9,r9,r5,lsl#30
+	eor	r10,r10,r6,lsl#30
+	eor	r9,r9,r6,lsr#7
+	eor	r10,r10,r5,lsr#7
+	eor	r9,r9,r5,lsl#25
+	eor	r10,r10,r6,lsl#25	@ Sigma0(a)
+	adds	r3,r3,r9
+	and	r9,r5,r11
+	adc	r4,r4,r10		@ T += Sigma0(a)
+
+	ldr	r10,[sp,#8+4]	@ b.hi
+	orr	r5,r5,r11
+	ldr	r11,[sp,#16+4]	@ c.hi
+	and	r5,r5,r12
+	and	r12,r6,r10
+	orr	r6,r6,r10
+	orr	r5,r5,r9		@ Maj(a,b,c).lo
+	and	r6,r6,r11
+	adds	r5,r5,r3
+	orr	r6,r6,r12		@ Maj(a,b,c).hi
+	sub	sp,sp,#8
+	adc	r6,r6,r4		@ h += T
+	tst	r14,#1
+	add	r14,r14,#8
+	tst	r14,#1
+	beq	L00_15
+	ldr	r9,[sp,#184+0]
+	ldr	r10,[sp,#184+4]
+	bic	r14,r14,#1
+L16_79:
+	@ sigma0(x)	(ROTR((x),1)  ^ ROTR((x),8)  ^ ((x)>>7))
+	@ LO		lo>>1^hi<<31  ^ lo>>8^hi<<24 ^ lo>>7^hi<<25
+	@ HI		hi>>1^lo<<31  ^ hi>>8^lo<<24 ^ hi>>7
+	mov	r3,r9,lsr#1
+	ldr	r11,[sp,#80+0]
+	mov	r4,r10,lsr#1
+	ldr	r12,[sp,#80+4]
+	eor	r3,r3,r10,lsl#31
+	eor	r4,r4,r9,lsl#31
+	eor	r3,r3,r9,lsr#8
+	eor	r4,r4,r10,lsr#8
+	eor	r3,r3,r10,lsl#24
+	eor	r4,r4,r9,lsl#24
+	eor	r3,r3,r9,lsr#7
+	eor	r4,r4,r10,lsr#7
+	eor	r3,r3,r10,lsl#25
+
+	@ sigma1(x)	(ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6))
+	@ LO		lo>>19^hi<<13 ^ hi>>29^lo<<3 ^ lo>>6^hi<<26
+	@ HI		hi>>19^lo<<13 ^ lo>>29^hi<<3 ^ hi>>6
+	mov	r9,r11,lsr#19
+	mov	r10,r12,lsr#19
+	eor	r9,r9,r12,lsl#13
+	eor	r10,r10,r11,lsl#13
+	eor	r9,r9,r12,lsr#29
+	eor	r10,r10,r11,lsr#29
+	eor	r9,r9,r11,lsl#3
+	eor	r10,r10,r12,lsl#3
+	eor	r9,r9,r11,lsr#6
+	eor	r10,r10,r12,lsr#6
+	ldr	r11,[sp,#120+0]
+	eor	r9,r9,r12,lsl#26
+
+	ldr	r12,[sp,#120+4]
+	adds	r3,r3,r9
+	ldr	r9,[sp,#192+0]
+	adc	r4,r4,r10
+
+	ldr	r10,[sp,#192+4]
+	adds	r3,r3,r11
+	adc	r4,r4,r12
+	adds	r3,r3,r9
+	adc	r4,r4,r10
+	@ Sigma1(x)	(ROTR((x),14) ^ ROTR((x),18)  ^ ROTR((x),41))
+	@ LO		lo>>14^hi<<18 ^ lo>>18^hi<<14 ^ hi>>9^lo<<23
+	@ HI		hi>>14^lo<<18 ^ hi>>18^lo<<14 ^ lo>>9^hi<<23
+	mov	r9,r7,lsr#14
+	str	r3,[sp,#64+0]
+	mov	r10,r8,lsr#14
+	str	r4,[sp,#64+4]
+	eor	r9,r9,r8,lsl#18
+	ldr	r11,[sp,#56+0]	@ h.lo
+	eor	r10,r10,r7,lsl#18
+	ldr	r12,[sp,#56+4]	@ h.hi
+	eor	r9,r9,r7,lsr#18
+	eor	r10,r10,r8,lsr#18
+	eor	r9,r9,r8,lsl#14
+	eor	r10,r10,r7,lsl#14
+	eor	r9,r9,r8,lsr#9
+	eor	r10,r10,r7,lsr#9
+	eor	r9,r9,r7,lsl#23
+	eor	r10,r10,r8,lsl#23	@ Sigma1(e)
+	adds	r3,r3,r9
+	ldr	r9,[sp,#40+0]	@ f.lo
+	adc	r4,r4,r10		@ T += Sigma1(e)
+	ldr	r10,[sp,#40+4]	@ f.hi
+	adds	r3,r3,r11
+	ldr	r11,[sp,#48+0]	@ g.lo
+	adc	r4,r4,r12		@ T += h
+	ldr	r12,[sp,#48+4]	@ g.hi
+
+	eor	r9,r9,r11
+	str	r7,[sp,#32+0]
+	eor	r10,r10,r12
+	str	r8,[sp,#32+4]
+	and	r9,r9,r7
+	str	r5,[sp,#0+0]
+	and	r10,r10,r8
+	str	r6,[sp,#0+4]
+	eor	r9,r9,r11
+	ldr	r11,[r14,#LO]	@ K[i].lo
+	eor	r10,r10,r12		@ Ch(e,f,g)
+	ldr	r12,[r14,#HI]	@ K[i].hi
+
+	adds	r3,r3,r9
+	ldr	r7,[sp,#24+0]	@ d.lo
+	adc	r4,r4,r10		@ T += Ch(e,f,g)
+	ldr	r8,[sp,#24+4]	@ d.hi
+	adds	r3,r3,r11
+	and	r9,r11,#0xff
+	adc	r4,r4,r12		@ T += K[i]
+	adds	r7,r7,r3
+	ldr	r11,[sp,#8+0]	@ b.lo
+	adc	r8,r8,r4		@ d += T
+	teq	r9,#23
+
+	ldr	r12,[sp,#16+0]	@ c.lo
+#if __ARM_ARCH__>=7
+	it	eq			@ Thumb2 thing, sanity check in ARM
+#endif
+	orreq	r14,r14,#1
+	@ Sigma0(x)	(ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39))
+	@ LO		lo>>28^hi<<4  ^ hi>>2^lo<<30 ^ hi>>7^lo<<25
+	@ HI		hi>>28^lo<<4  ^ lo>>2^hi<<30 ^ lo>>7^hi<<25
+	mov	r9,r5,lsr#28
+	mov	r10,r6,lsr#28
+	eor	r9,r9,r6,lsl#4
+	eor	r10,r10,r5,lsl#4
+	eor	r9,r9,r6,lsr#2
+	eor	r10,r10,r5,lsr#2
+	eor	r9,r9,r5,lsl#30
+	eor	r10,r10,r6,lsl#30
+	eor	r9,r9,r6,lsr#7
+	eor	r10,r10,r5,lsr#7
+	eor	r9,r9,r5,lsl#25
+	eor	r10,r10,r6,lsl#25	@ Sigma0(a)
+	adds	r3,r3,r9
+	and	r9,r5,r11
+	adc	r4,r4,r10		@ T += Sigma0(a)
+
+	ldr	r10,[sp,#8+4]	@ b.hi
+	orr	r5,r5,r11
+	ldr	r11,[sp,#16+4]	@ c.hi
+	and	r5,r5,r12
+	and	r12,r6,r10
+	orr	r6,r6,r10
+	orr	r5,r5,r9		@ Maj(a,b,c).lo
+	and	r6,r6,r11
+	adds	r5,r5,r3
+	orr	r6,r6,r12		@ Maj(a,b,c).hi
+	sub	sp,sp,#8
+	adc	r6,r6,r4		@ h += T
+	tst	r14,#1
+	add	r14,r14,#8
+#if __ARM_ARCH__>=7
+	ittt	eq			@ Thumb2 thing, sanity check in ARM
+#endif
+	ldreq	r9,[sp,#184+0]
+	ldreq	r10,[sp,#184+4]
+	beq	L16_79
+	bic	r14,r14,#1
+
+	ldr	r3,[sp,#8+0]
+	ldr	r4,[sp,#8+4]
+	ldr	r9, [r0,#0+LO]
+	ldr	r10, [r0,#0+HI]
+	ldr	r11, [r0,#8+LO]
+	ldr	r12, [r0,#8+HI]
+	adds	r9,r5,r9
+	str	r9, [r0,#0+LO]
+	adc	r10,r6,r10
+	str	r10, [r0,#0+HI]
+	adds	r11,r3,r11
+	str	r11, [r0,#8+LO]
+	adc	r12,r4,r12
+	str	r12, [r0,#8+HI]
+
+	ldr	r5,[sp,#16+0]
+	ldr	r6,[sp,#16+4]
+	ldr	r3,[sp,#24+0]
+	ldr	r4,[sp,#24+4]
+	ldr	r9, [r0,#16+LO]
+	ldr	r10, [r0,#16+HI]
+	ldr	r11, [r0,#24+LO]
+	ldr	r12, [r0,#24+HI]
+	adds	r9,r5,r9
+	str	r9, [r0,#16+LO]
+	adc	r10,r6,r10
+	str	r10, [r0,#16+HI]
+	adds	r11,r3,r11
+	str	r11, [r0,#24+LO]
+	adc	r12,r4,r12
+	str	r12, [r0,#24+HI]
+
+	ldr	r3,[sp,#40+0]
+	ldr	r4,[sp,#40+4]
+	ldr	r9, [r0,#32+LO]
+	ldr	r10, [r0,#32+HI]
+	ldr	r11, [r0,#40+LO]
+	ldr	r12, [r0,#40+HI]
+	adds	r7,r7,r9
+	str	r7,[r0,#32+LO]
+	adc	r8,r8,r10
+	str	r8,[r0,#32+HI]
+	adds	r11,r3,r11
+	str	r11, [r0,#40+LO]
+	adc	r12,r4,r12
+	str	r12, [r0,#40+HI]
+
+	ldr	r5,[sp,#48+0]
+	ldr	r6,[sp,#48+4]
+	ldr	r3,[sp,#56+0]
+	ldr	r4,[sp,#56+4]
+	ldr	r9, [r0,#48+LO]
+	ldr	r10, [r0,#48+HI]
+	ldr	r11, [r0,#56+LO]
+	ldr	r12, [r0,#56+HI]
+	adds	r9,r5,r9
+	str	r9, [r0,#48+LO]
+	adc	r10,r6,r10
+	str	r10, [r0,#48+HI]
+	adds	r11,r3,r11
+	str	r11, [r0,#56+LO]
+	adc	r12,r4,r12
+	str	r12, [r0,#56+HI]
+
+	add	sp,sp,#640
+	sub	r14,r14,#640
+
+	teq	r1,r2
+	bne	Loop
+
+	add	sp,sp,#8*9		@ destroy frame
+#if __ARM_ARCH__>=5
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
+#else
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
+	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+
+#if __ARM_MAX_ARCH__>=7
+
+
+
+.globl	_sha512_block_data_order_neon
+.private_extern	_sha512_block_data_order_neon
+
+.align	4
+_sha512_block_data_order_neon:
+LNEON:
+	dmb	@ errata #451034 on early Cortex A8
+	add	r2,r1,r2,lsl#7	@ len to point at the end of inp
+	adr	r3,K512
+	VFP_ABI_PUSH
+	vldmia	r0,{d16,d17,d18,d19,d20,d21,d22,d23}		@ load context
+Loop_neon:
+	vshr.u64	d24,d20,#14	@ 0
+#if 0<16
+	vld1.64	{d0},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d20,#18
+#if 0>0
+	vadd.i64	d16,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d20,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d20,#50
+	vsli.64	d25,d20,#46
+	vmov	d29,d20
+	vsli.64	d26,d20,#23
+#if 0<16 && defined(__ARMEL__)
+	vrev64.8	d0,d0
+#endif
+	veor	d25,d24
+	vbsl	d29,d21,d22		@ Ch(e,f,g)
+	vshr.u64	d24,d16,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d23
+	vshr.u64	d25,d16,#34
+	vsli.64	d24,d16,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d16,#39
+	vadd.i64	d28,d0
+	vsli.64	d25,d16,#30
+	veor	d30,d16,d17
+	vsli.64	d26,d16,#25
+	veor	d23,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d18,d17		@ Maj(a,b,c)
+	veor	d23,d26			@ Sigma0(a)
+	vadd.i64	d19,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d23,d30
+	vshr.u64	d24,d19,#14	@ 1
+#if 1<16
+	vld1.64	{d1},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d19,#18
+#if 1>0
+	vadd.i64	d23,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d19,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d19,#50
+	vsli.64	d25,d19,#46
+	vmov	d29,d19
+	vsli.64	d26,d19,#23
+#if 1<16 && defined(__ARMEL__)
+	vrev64.8	d1,d1
+#endif
+	veor	d25,d24
+	vbsl	d29,d20,d21		@ Ch(e,f,g)
+	vshr.u64	d24,d23,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d22
+	vshr.u64	d25,d23,#34
+	vsli.64	d24,d23,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d23,#39
+	vadd.i64	d28,d1
+	vsli.64	d25,d23,#30
+	veor	d30,d23,d16
+	vsli.64	d26,d23,#25
+	veor	d22,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d17,d16		@ Maj(a,b,c)
+	veor	d22,d26			@ Sigma0(a)
+	vadd.i64	d18,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d22,d30
+	vshr.u64	d24,d18,#14	@ 2
+#if 2<16
+	vld1.64	{d2},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d18,#18
+#if 2>0
+	vadd.i64	d22,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d18,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d18,#50
+	vsli.64	d25,d18,#46
+	vmov	d29,d18
+	vsli.64	d26,d18,#23
+#if 2<16 && defined(__ARMEL__)
+	vrev64.8	d2,d2
+#endif
+	veor	d25,d24
+	vbsl	d29,d19,d20		@ Ch(e,f,g)
+	vshr.u64	d24,d22,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d21
+	vshr.u64	d25,d22,#34
+	vsli.64	d24,d22,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d22,#39
+	vadd.i64	d28,d2
+	vsli.64	d25,d22,#30
+	veor	d30,d22,d23
+	vsli.64	d26,d22,#25
+	veor	d21,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d16,d23		@ Maj(a,b,c)
+	veor	d21,d26			@ Sigma0(a)
+	vadd.i64	d17,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d21,d30
+	vshr.u64	d24,d17,#14	@ 3
+#if 3<16
+	vld1.64	{d3},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d17,#18
+#if 3>0
+	vadd.i64	d21,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d17,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d17,#50
+	vsli.64	d25,d17,#46
+	vmov	d29,d17
+	vsli.64	d26,d17,#23
+#if 3<16 && defined(__ARMEL__)
+	vrev64.8	d3,d3
+#endif
+	veor	d25,d24
+	vbsl	d29,d18,d19		@ Ch(e,f,g)
+	vshr.u64	d24,d21,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d20
+	vshr.u64	d25,d21,#34
+	vsli.64	d24,d21,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d21,#39
+	vadd.i64	d28,d3
+	vsli.64	d25,d21,#30
+	veor	d30,d21,d22
+	vsli.64	d26,d21,#25
+	veor	d20,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d23,d22		@ Maj(a,b,c)
+	veor	d20,d26			@ Sigma0(a)
+	vadd.i64	d16,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d20,d30
+	vshr.u64	d24,d16,#14	@ 4
+#if 4<16
+	vld1.64	{d4},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d16,#18
+#if 4>0
+	vadd.i64	d20,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d16,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d16,#50
+	vsli.64	d25,d16,#46
+	vmov	d29,d16
+	vsli.64	d26,d16,#23
+#if 4<16 && defined(__ARMEL__)
+	vrev64.8	d4,d4
+#endif
+	veor	d25,d24
+	vbsl	d29,d17,d18		@ Ch(e,f,g)
+	vshr.u64	d24,d20,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d19
+	vshr.u64	d25,d20,#34
+	vsli.64	d24,d20,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d20,#39
+	vadd.i64	d28,d4
+	vsli.64	d25,d20,#30
+	veor	d30,d20,d21
+	vsli.64	d26,d20,#25
+	veor	d19,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d22,d21		@ Maj(a,b,c)
+	veor	d19,d26			@ Sigma0(a)
+	vadd.i64	d23,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d19,d30
+	vshr.u64	d24,d23,#14	@ 5
+#if 5<16
+	vld1.64	{d5},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d23,#18
+#if 5>0
+	vadd.i64	d19,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d23,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d23,#50
+	vsli.64	d25,d23,#46
+	vmov	d29,d23
+	vsli.64	d26,d23,#23
+#if 5<16 && defined(__ARMEL__)
+	vrev64.8	d5,d5
+#endif
+	veor	d25,d24
+	vbsl	d29,d16,d17		@ Ch(e,f,g)
+	vshr.u64	d24,d19,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d18
+	vshr.u64	d25,d19,#34
+	vsli.64	d24,d19,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d19,#39
+	vadd.i64	d28,d5
+	vsli.64	d25,d19,#30
+	veor	d30,d19,d20
+	vsli.64	d26,d19,#25
+	veor	d18,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d21,d20		@ Maj(a,b,c)
+	veor	d18,d26			@ Sigma0(a)
+	vadd.i64	d22,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d18,d30
+	vshr.u64	d24,d22,#14	@ 6
+#if 6<16
+	vld1.64	{d6},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d22,#18
+#if 6>0
+	vadd.i64	d18,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d22,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d22,#50
+	vsli.64	d25,d22,#46
+	vmov	d29,d22
+	vsli.64	d26,d22,#23
+#if 6<16 && defined(__ARMEL__)
+	vrev64.8	d6,d6
+#endif
+	veor	d25,d24
+	vbsl	d29,d23,d16		@ Ch(e,f,g)
+	vshr.u64	d24,d18,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d17
+	vshr.u64	d25,d18,#34
+	vsli.64	d24,d18,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d18,#39
+	vadd.i64	d28,d6
+	vsli.64	d25,d18,#30
+	veor	d30,d18,d19
+	vsli.64	d26,d18,#25
+	veor	d17,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d20,d19		@ Maj(a,b,c)
+	veor	d17,d26			@ Sigma0(a)
+	vadd.i64	d21,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d17,d30
+	vshr.u64	d24,d21,#14	@ 7
+#if 7<16
+	vld1.64	{d7},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d21,#18
+#if 7>0
+	vadd.i64	d17,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d21,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d21,#50
+	vsli.64	d25,d21,#46
+	vmov	d29,d21
+	vsli.64	d26,d21,#23
+#if 7<16 && defined(__ARMEL__)
+	vrev64.8	d7,d7
+#endif
+	veor	d25,d24
+	vbsl	d29,d22,d23		@ Ch(e,f,g)
+	vshr.u64	d24,d17,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d16
+	vshr.u64	d25,d17,#34
+	vsli.64	d24,d17,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d17,#39
+	vadd.i64	d28,d7
+	vsli.64	d25,d17,#30
+	veor	d30,d17,d18
+	vsli.64	d26,d17,#25
+	veor	d16,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d19,d18		@ Maj(a,b,c)
+	veor	d16,d26			@ Sigma0(a)
+	vadd.i64	d20,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d16,d30
+	vshr.u64	d24,d20,#14	@ 8
+#if 8<16
+	vld1.64	{d8},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d20,#18
+#if 8>0
+	vadd.i64	d16,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d20,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d20,#50
+	vsli.64	d25,d20,#46
+	vmov	d29,d20
+	vsli.64	d26,d20,#23
+#if 8<16 && defined(__ARMEL__)
+	vrev64.8	d8,d8
+#endif
+	veor	d25,d24
+	vbsl	d29,d21,d22		@ Ch(e,f,g)
+	vshr.u64	d24,d16,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d23
+	vshr.u64	d25,d16,#34
+	vsli.64	d24,d16,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d16,#39
+	vadd.i64	d28,d8
+	vsli.64	d25,d16,#30
+	veor	d30,d16,d17
+	vsli.64	d26,d16,#25
+	veor	d23,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d18,d17		@ Maj(a,b,c)
+	veor	d23,d26			@ Sigma0(a)
+	vadd.i64	d19,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d23,d30
+	vshr.u64	d24,d19,#14	@ 9
+#if 9<16
+	vld1.64	{d9},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d19,#18
+#if 9>0
+	vadd.i64	d23,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d19,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d19,#50
+	vsli.64	d25,d19,#46
+	vmov	d29,d19
+	vsli.64	d26,d19,#23
+#if 9<16 && defined(__ARMEL__)
+	vrev64.8	d9,d9
+#endif
+	veor	d25,d24
+	vbsl	d29,d20,d21		@ Ch(e,f,g)
+	vshr.u64	d24,d23,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d22
+	vshr.u64	d25,d23,#34
+	vsli.64	d24,d23,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d23,#39
+	vadd.i64	d28,d9
+	vsli.64	d25,d23,#30
+	veor	d30,d23,d16
+	vsli.64	d26,d23,#25
+	veor	d22,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d17,d16		@ Maj(a,b,c)
+	veor	d22,d26			@ Sigma0(a)
+	vadd.i64	d18,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d22,d30
+	vshr.u64	d24,d18,#14	@ 10
+#if 10<16
+	vld1.64	{d10},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d18,#18
+#if 10>0
+	vadd.i64	d22,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d18,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d18,#50
+	vsli.64	d25,d18,#46
+	vmov	d29,d18
+	vsli.64	d26,d18,#23
+#if 10<16 && defined(__ARMEL__)
+	vrev64.8	d10,d10
+#endif
+	veor	d25,d24
+	vbsl	d29,d19,d20		@ Ch(e,f,g)
+	vshr.u64	d24,d22,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d21
+	vshr.u64	d25,d22,#34
+	vsli.64	d24,d22,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d22,#39
+	vadd.i64	d28,d10
+	vsli.64	d25,d22,#30
+	veor	d30,d22,d23
+	vsli.64	d26,d22,#25
+	veor	d21,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d16,d23		@ Maj(a,b,c)
+	veor	d21,d26			@ Sigma0(a)
+	vadd.i64	d17,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d21,d30
+	vshr.u64	d24,d17,#14	@ 11
+#if 11<16
+	vld1.64	{d11},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d17,#18
+#if 11>0
+	vadd.i64	d21,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d17,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d17,#50
+	vsli.64	d25,d17,#46
+	vmov	d29,d17
+	vsli.64	d26,d17,#23
+#if 11<16 && defined(__ARMEL__)
+	vrev64.8	d11,d11
+#endif
+	veor	d25,d24
+	vbsl	d29,d18,d19		@ Ch(e,f,g)
+	vshr.u64	d24,d21,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d20
+	vshr.u64	d25,d21,#34
+	vsli.64	d24,d21,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d21,#39
+	vadd.i64	d28,d11
+	vsli.64	d25,d21,#30
+	veor	d30,d21,d22
+	vsli.64	d26,d21,#25
+	veor	d20,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d23,d22		@ Maj(a,b,c)
+	veor	d20,d26			@ Sigma0(a)
+	vadd.i64	d16,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d20,d30
+	vshr.u64	d24,d16,#14	@ 12
+#if 12<16
+	vld1.64	{d12},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d16,#18
+#if 12>0
+	vadd.i64	d20,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d16,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d16,#50
+	vsli.64	d25,d16,#46
+	vmov	d29,d16
+	vsli.64	d26,d16,#23
+#if 12<16 && defined(__ARMEL__)
+	vrev64.8	d12,d12
+#endif
+	veor	d25,d24
+	vbsl	d29,d17,d18		@ Ch(e,f,g)
+	vshr.u64	d24,d20,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d19
+	vshr.u64	d25,d20,#34
+	vsli.64	d24,d20,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d20,#39
+	vadd.i64	d28,d12
+	vsli.64	d25,d20,#30
+	veor	d30,d20,d21
+	vsli.64	d26,d20,#25
+	veor	d19,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d22,d21		@ Maj(a,b,c)
+	veor	d19,d26			@ Sigma0(a)
+	vadd.i64	d23,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d19,d30
+	vshr.u64	d24,d23,#14	@ 13
+#if 13<16
+	vld1.64	{d13},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d23,#18
+#if 13>0
+	vadd.i64	d19,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d23,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d23,#50
+	vsli.64	d25,d23,#46
+	vmov	d29,d23
+	vsli.64	d26,d23,#23
+#if 13<16 && defined(__ARMEL__)
+	vrev64.8	d13,d13
+#endif
+	veor	d25,d24
+	vbsl	d29,d16,d17		@ Ch(e,f,g)
+	vshr.u64	d24,d19,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d18
+	vshr.u64	d25,d19,#34
+	vsli.64	d24,d19,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d19,#39
+	vadd.i64	d28,d13
+	vsli.64	d25,d19,#30
+	veor	d30,d19,d20
+	vsli.64	d26,d19,#25
+	veor	d18,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d21,d20		@ Maj(a,b,c)
+	veor	d18,d26			@ Sigma0(a)
+	vadd.i64	d22,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d18,d30
+	vshr.u64	d24,d22,#14	@ 14
+#if 14<16
+	vld1.64	{d14},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d22,#18
+#if 14>0
+	vadd.i64	d18,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d22,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d22,#50
+	vsli.64	d25,d22,#46
+	vmov	d29,d22
+	vsli.64	d26,d22,#23
+#if 14<16 && defined(__ARMEL__)
+	vrev64.8	d14,d14
+#endif
+	veor	d25,d24
+	vbsl	d29,d23,d16		@ Ch(e,f,g)
+	vshr.u64	d24,d18,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d17
+	vshr.u64	d25,d18,#34
+	vsli.64	d24,d18,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d18,#39
+	vadd.i64	d28,d14
+	vsli.64	d25,d18,#30
+	veor	d30,d18,d19
+	vsli.64	d26,d18,#25
+	veor	d17,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d20,d19		@ Maj(a,b,c)
+	veor	d17,d26			@ Sigma0(a)
+	vadd.i64	d21,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d17,d30
+	vshr.u64	d24,d21,#14	@ 15
+#if 15<16
+	vld1.64	{d15},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d21,#18
+#if 15>0
+	vadd.i64	d17,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d21,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d21,#50
+	vsli.64	d25,d21,#46
+	vmov	d29,d21
+	vsli.64	d26,d21,#23
+#if 15<16 && defined(__ARMEL__)
+	vrev64.8	d15,d15
+#endif
+	veor	d25,d24
+	vbsl	d29,d22,d23		@ Ch(e,f,g)
+	vshr.u64	d24,d17,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d16
+	vshr.u64	d25,d17,#34
+	vsli.64	d24,d17,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d17,#39
+	vadd.i64	d28,d15
+	vsli.64	d25,d17,#30
+	veor	d30,d17,d18
+	vsli.64	d26,d17,#25
+	veor	d16,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d19,d18		@ Maj(a,b,c)
+	veor	d16,d26			@ Sigma0(a)
+	vadd.i64	d20,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d16,d30
+	mov	r12,#4
+L16_79_neon:
+	subs	r12,#1
+	vshr.u64	q12,q7,#19
+	vshr.u64	q13,q7,#61
+	vadd.i64	d16,d30			@ h+=Maj from the past
+	vshr.u64	q15,q7,#6
+	vsli.64	q12,q7,#45
+	vext.8	q14,q0,q1,#8	@ X[i+1]
+	vsli.64	q13,q7,#3
+	veor	q15,q12
+	vshr.u64	q12,q14,#1
+	veor	q15,q13				@ sigma1(X[i+14])
+	vshr.u64	q13,q14,#8
+	vadd.i64	q0,q15
+	vshr.u64	q15,q14,#7
+	vsli.64	q12,q14,#63
+	vsli.64	q13,q14,#56
+	vext.8	q14,q4,q5,#8	@ X[i+9]
+	veor	q15,q12
+	vshr.u64	d24,d20,#14		@ from NEON_00_15
+	vadd.i64	q0,q14
+	vshr.u64	d25,d20,#18		@ from NEON_00_15
+	veor	q15,q13				@ sigma0(X[i+1])
+	vshr.u64	d26,d20,#41		@ from NEON_00_15
+	vadd.i64	q0,q15
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d20,#50
+	vsli.64	d25,d20,#46
+	vmov	d29,d20
+	vsli.64	d26,d20,#23
+#if 16<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	veor	d25,d24
+	vbsl	d29,d21,d22		@ Ch(e,f,g)
+	vshr.u64	d24,d16,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d23
+	vshr.u64	d25,d16,#34
+	vsli.64	d24,d16,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d16,#39
+	vadd.i64	d28,d0
+	vsli.64	d25,d16,#30
+	veor	d30,d16,d17
+	vsli.64	d26,d16,#25
+	veor	d23,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d18,d17		@ Maj(a,b,c)
+	veor	d23,d26			@ Sigma0(a)
+	vadd.i64	d19,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d23,d30
+	vshr.u64	d24,d19,#14	@ 17
+#if 17<16
+	vld1.64	{d1},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d19,#18
+#if 17>0
+	vadd.i64	d23,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d19,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d19,#50
+	vsli.64	d25,d19,#46
+	vmov	d29,d19
+	vsli.64	d26,d19,#23
+#if 17<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	veor	d25,d24
+	vbsl	d29,d20,d21		@ Ch(e,f,g)
+	vshr.u64	d24,d23,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d22
+	vshr.u64	d25,d23,#34
+	vsli.64	d24,d23,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d23,#39
+	vadd.i64	d28,d1
+	vsli.64	d25,d23,#30
+	veor	d30,d23,d16
+	vsli.64	d26,d23,#25
+	veor	d22,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d17,d16		@ Maj(a,b,c)
+	veor	d22,d26			@ Sigma0(a)
+	vadd.i64	d18,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d22,d30
+	vshr.u64	q12,q0,#19
+	vshr.u64	q13,q0,#61
+	vadd.i64	d22,d30			@ h+=Maj from the past
+	vshr.u64	q15,q0,#6
+	vsli.64	q12,q0,#45
+	vext.8	q14,q1,q2,#8	@ X[i+1]
+	vsli.64	q13,q0,#3
+	veor	q15,q12
+	vshr.u64	q12,q14,#1
+	veor	q15,q13				@ sigma1(X[i+14])
+	vshr.u64	q13,q14,#8
+	vadd.i64	q1,q15
+	vshr.u64	q15,q14,#7
+	vsli.64	q12,q14,#63
+	vsli.64	q13,q14,#56
+	vext.8	q14,q5,q6,#8	@ X[i+9]
+	veor	q15,q12
+	vshr.u64	d24,d18,#14		@ from NEON_00_15
+	vadd.i64	q1,q14
+	vshr.u64	d25,d18,#18		@ from NEON_00_15
+	veor	q15,q13				@ sigma0(X[i+1])
+	vshr.u64	d26,d18,#41		@ from NEON_00_15
+	vadd.i64	q1,q15
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d18,#50
+	vsli.64	d25,d18,#46
+	vmov	d29,d18
+	vsli.64	d26,d18,#23
+#if 18<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	veor	d25,d24
+	vbsl	d29,d19,d20		@ Ch(e,f,g)
+	vshr.u64	d24,d22,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d21
+	vshr.u64	d25,d22,#34
+	vsli.64	d24,d22,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d22,#39
+	vadd.i64	d28,d2
+	vsli.64	d25,d22,#30
+	veor	d30,d22,d23
+	vsli.64	d26,d22,#25
+	veor	d21,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d16,d23		@ Maj(a,b,c)
+	veor	d21,d26			@ Sigma0(a)
+	vadd.i64	d17,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d21,d30
+	vshr.u64	d24,d17,#14	@ 19
+#if 19<16
+	vld1.64	{d3},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d17,#18
+#if 19>0
+	vadd.i64	d21,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d17,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d17,#50
+	vsli.64	d25,d17,#46
+	vmov	d29,d17
+	vsli.64	d26,d17,#23
+#if 19<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	veor	d25,d24
+	vbsl	d29,d18,d19		@ Ch(e,f,g)
+	vshr.u64	d24,d21,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d20
+	vshr.u64	d25,d21,#34
+	vsli.64	d24,d21,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d21,#39
+	vadd.i64	d28,d3
+	vsli.64	d25,d21,#30
+	veor	d30,d21,d22
+	vsli.64	d26,d21,#25
+	veor	d20,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d23,d22		@ Maj(a,b,c)
+	veor	d20,d26			@ Sigma0(a)
+	vadd.i64	d16,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d20,d30
+	vshr.u64	q12,q1,#19
+	vshr.u64	q13,q1,#61
+	vadd.i64	d20,d30			@ h+=Maj from the past
+	vshr.u64	q15,q1,#6
+	vsli.64	q12,q1,#45
+	vext.8	q14,q2,q3,#8	@ X[i+1]
+	vsli.64	q13,q1,#3
+	veor	q15,q12
+	vshr.u64	q12,q14,#1
+	veor	q15,q13				@ sigma1(X[i+14])
+	vshr.u64	q13,q14,#8
+	vadd.i64	q2,q15
+	vshr.u64	q15,q14,#7
+	vsli.64	q12,q14,#63
+	vsli.64	q13,q14,#56
+	vext.8	q14,q6,q7,#8	@ X[i+9]
+	veor	q15,q12
+	vshr.u64	d24,d16,#14		@ from NEON_00_15
+	vadd.i64	q2,q14
+	vshr.u64	d25,d16,#18		@ from NEON_00_15
+	veor	q15,q13				@ sigma0(X[i+1])
+	vshr.u64	d26,d16,#41		@ from NEON_00_15
+	vadd.i64	q2,q15
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d16,#50
+	vsli.64	d25,d16,#46
+	vmov	d29,d16
+	vsli.64	d26,d16,#23
+#if 20<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	veor	d25,d24
+	vbsl	d29,d17,d18		@ Ch(e,f,g)
+	vshr.u64	d24,d20,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d19
+	vshr.u64	d25,d20,#34
+	vsli.64	d24,d20,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d20,#39
+	vadd.i64	d28,d4
+	vsli.64	d25,d20,#30
+	veor	d30,d20,d21
+	vsli.64	d26,d20,#25
+	veor	d19,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d22,d21		@ Maj(a,b,c)
+	veor	d19,d26			@ Sigma0(a)
+	vadd.i64	d23,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d19,d30
+	vshr.u64	d24,d23,#14	@ 21
+#if 21<16
+	vld1.64	{d5},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d23,#18
+#if 21>0
+	vadd.i64	d19,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d23,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d23,#50
+	vsli.64	d25,d23,#46
+	vmov	d29,d23
+	vsli.64	d26,d23,#23
+#if 21<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	veor	d25,d24
+	vbsl	d29,d16,d17		@ Ch(e,f,g)
+	vshr.u64	d24,d19,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d18
+	vshr.u64	d25,d19,#34
+	vsli.64	d24,d19,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d19,#39
+	vadd.i64	d28,d5
+	vsli.64	d25,d19,#30
+	veor	d30,d19,d20
+	vsli.64	d26,d19,#25
+	veor	d18,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d21,d20		@ Maj(a,b,c)
+	veor	d18,d26			@ Sigma0(a)
+	vadd.i64	d22,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d18,d30
+	vshr.u64	q12,q2,#19
+	vshr.u64	q13,q2,#61
+	vadd.i64	d18,d30			@ h+=Maj from the past
+	vshr.u64	q15,q2,#6
+	vsli.64	q12,q2,#45
+	vext.8	q14,q3,q4,#8	@ X[i+1]
+	vsli.64	q13,q2,#3
+	veor	q15,q12
+	vshr.u64	q12,q14,#1
+	veor	q15,q13				@ sigma1(X[i+14])
+	vshr.u64	q13,q14,#8
+	vadd.i64	q3,q15
+	vshr.u64	q15,q14,#7
+	vsli.64	q12,q14,#63
+	vsli.64	q13,q14,#56
+	vext.8	q14,q7,q0,#8	@ X[i+9]
+	veor	q15,q12
+	vshr.u64	d24,d22,#14		@ from NEON_00_15
+	vadd.i64	q3,q14
+	vshr.u64	d25,d22,#18		@ from NEON_00_15
+	veor	q15,q13				@ sigma0(X[i+1])
+	vshr.u64	d26,d22,#41		@ from NEON_00_15
+	vadd.i64	q3,q15
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d22,#50
+	vsli.64	d25,d22,#46
+	vmov	d29,d22
+	vsli.64	d26,d22,#23
+#if 22<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	veor	d25,d24
+	vbsl	d29,d23,d16		@ Ch(e,f,g)
+	vshr.u64	d24,d18,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d17
+	vshr.u64	d25,d18,#34
+	vsli.64	d24,d18,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d18,#39
+	vadd.i64	d28,d6
+	vsli.64	d25,d18,#30
+	veor	d30,d18,d19
+	vsli.64	d26,d18,#25
+	veor	d17,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d20,d19		@ Maj(a,b,c)
+	veor	d17,d26			@ Sigma0(a)
+	vadd.i64	d21,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d17,d30
+	vshr.u64	d24,d21,#14	@ 23
+#if 23<16
+	vld1.64	{d7},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d21,#18
+#if 23>0
+	vadd.i64	d17,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d21,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d21,#50
+	vsli.64	d25,d21,#46
+	vmov	d29,d21
+	vsli.64	d26,d21,#23
+#if 23<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	veor	d25,d24
+	vbsl	d29,d22,d23		@ Ch(e,f,g)
+	vshr.u64	d24,d17,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d16
+	vshr.u64	d25,d17,#34
+	vsli.64	d24,d17,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d17,#39
+	vadd.i64	d28,d7
+	vsli.64	d25,d17,#30
+	veor	d30,d17,d18
+	vsli.64	d26,d17,#25
+	veor	d16,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d19,d18		@ Maj(a,b,c)
+	veor	d16,d26			@ Sigma0(a)
+	vadd.i64	d20,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d16,d30
+	vshr.u64	q12,q3,#19
+	vshr.u64	q13,q3,#61
+	vadd.i64	d16,d30			@ h+=Maj from the past
+	vshr.u64	q15,q3,#6
+	vsli.64	q12,q3,#45
+	vext.8	q14,q4,q5,#8	@ X[i+1]
+	vsli.64	q13,q3,#3
+	veor	q15,q12
+	vshr.u64	q12,q14,#1
+	veor	q15,q13				@ sigma1(X[i+14])
+	vshr.u64	q13,q14,#8
+	vadd.i64	q4,q15
+	vshr.u64	q15,q14,#7
+	vsli.64	q12,q14,#63
+	vsli.64	q13,q14,#56
+	vext.8	q14,q0,q1,#8	@ X[i+9]
+	veor	q15,q12
+	vshr.u64	d24,d20,#14		@ from NEON_00_15
+	vadd.i64	q4,q14
+	vshr.u64	d25,d20,#18		@ from NEON_00_15
+	veor	q15,q13				@ sigma0(X[i+1])
+	vshr.u64	d26,d20,#41		@ from NEON_00_15
+	vadd.i64	q4,q15
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d20,#50
+	vsli.64	d25,d20,#46
+	vmov	d29,d20
+	vsli.64	d26,d20,#23
+#if 24<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	veor	d25,d24
+	vbsl	d29,d21,d22		@ Ch(e,f,g)
+	vshr.u64	d24,d16,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d23
+	vshr.u64	d25,d16,#34
+	vsli.64	d24,d16,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d16,#39
+	vadd.i64	d28,d8
+	vsli.64	d25,d16,#30
+	veor	d30,d16,d17
+	vsli.64	d26,d16,#25
+	veor	d23,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d18,d17		@ Maj(a,b,c)
+	veor	d23,d26			@ Sigma0(a)
+	vadd.i64	d19,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d23,d30
+	vshr.u64	d24,d19,#14	@ 25
+#if 25<16
+	vld1.64	{d9},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d19,#18
+#if 25>0
+	vadd.i64	d23,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d19,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d19,#50
+	vsli.64	d25,d19,#46
+	vmov	d29,d19
+	vsli.64	d26,d19,#23
+#if 25<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	veor	d25,d24
+	vbsl	d29,d20,d21		@ Ch(e,f,g)
+	vshr.u64	d24,d23,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d22
+	vshr.u64	d25,d23,#34
+	vsli.64	d24,d23,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d23,#39
+	vadd.i64	d28,d9
+	vsli.64	d25,d23,#30
+	veor	d30,d23,d16
+	vsli.64	d26,d23,#25
+	veor	d22,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d17,d16		@ Maj(a,b,c)
+	veor	d22,d26			@ Sigma0(a)
+	vadd.i64	d18,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d22,d30
+	vshr.u64	q12,q4,#19
+	vshr.u64	q13,q4,#61
+	vadd.i64	d22,d30			@ h+=Maj from the past
+	vshr.u64	q15,q4,#6
+	vsli.64	q12,q4,#45
+	vext.8	q14,q5,q6,#8	@ X[i+1]
+	vsli.64	q13,q4,#3
+	veor	q15,q12
+	vshr.u64	q12,q14,#1
+	veor	q15,q13				@ sigma1(X[i+14])
+	vshr.u64	q13,q14,#8
+	vadd.i64	q5,q15
+	vshr.u64	q15,q14,#7
+	vsli.64	q12,q14,#63
+	vsli.64	q13,q14,#56
+	vext.8	q14,q1,q2,#8	@ X[i+9]
+	veor	q15,q12
+	vshr.u64	d24,d18,#14		@ from NEON_00_15
+	vadd.i64	q5,q14
+	vshr.u64	d25,d18,#18		@ from NEON_00_15
+	veor	q15,q13				@ sigma0(X[i+1])
+	vshr.u64	d26,d18,#41		@ from NEON_00_15
+	vadd.i64	q5,q15
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d18,#50
+	vsli.64	d25,d18,#46
+	vmov	d29,d18
+	vsli.64	d26,d18,#23
+#if 26<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	veor	d25,d24
+	vbsl	d29,d19,d20		@ Ch(e,f,g)
+	vshr.u64	d24,d22,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d21
+	vshr.u64	d25,d22,#34
+	vsli.64	d24,d22,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d22,#39
+	vadd.i64	d28,d10
+	vsli.64	d25,d22,#30
+	veor	d30,d22,d23
+	vsli.64	d26,d22,#25
+	veor	d21,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d16,d23		@ Maj(a,b,c)
+	veor	d21,d26			@ Sigma0(a)
+	vadd.i64	d17,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d21,d30
+	vshr.u64	d24,d17,#14	@ 27
+#if 27<16
+	vld1.64	{d11},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d17,#18
+#if 27>0
+	vadd.i64	d21,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d17,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d17,#50
+	vsli.64	d25,d17,#46
+	vmov	d29,d17
+	vsli.64	d26,d17,#23
+#if 27<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	veor	d25,d24
+	vbsl	d29,d18,d19		@ Ch(e,f,g)
+	vshr.u64	d24,d21,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d20
+	vshr.u64	d25,d21,#34
+	vsli.64	d24,d21,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d21,#39
+	vadd.i64	d28,d11
+	vsli.64	d25,d21,#30
+	veor	d30,d21,d22
+	vsli.64	d26,d21,#25
+	veor	d20,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d23,d22		@ Maj(a,b,c)
+	veor	d20,d26			@ Sigma0(a)
+	vadd.i64	d16,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d20,d30
+	vshr.u64	q12,q5,#19
+	vshr.u64	q13,q5,#61
+	vadd.i64	d20,d30			@ h+=Maj from the past
+	vshr.u64	q15,q5,#6
+	vsli.64	q12,q5,#45
+	vext.8	q14,q6,q7,#8	@ X[i+1]
+	vsli.64	q13,q5,#3
+	veor	q15,q12
+	vshr.u64	q12,q14,#1
+	veor	q15,q13				@ sigma1(X[i+14])
+	vshr.u64	q13,q14,#8
+	vadd.i64	q6,q15
+	vshr.u64	q15,q14,#7
+	vsli.64	q12,q14,#63
+	vsli.64	q13,q14,#56
+	vext.8	q14,q2,q3,#8	@ X[i+9]
+	veor	q15,q12
+	vshr.u64	d24,d16,#14		@ from NEON_00_15
+	vadd.i64	q6,q14
+	vshr.u64	d25,d16,#18		@ from NEON_00_15
+	veor	q15,q13				@ sigma0(X[i+1])
+	vshr.u64	d26,d16,#41		@ from NEON_00_15
+	vadd.i64	q6,q15
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d16,#50
+	vsli.64	d25,d16,#46
+	vmov	d29,d16
+	vsli.64	d26,d16,#23
+#if 28<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	veor	d25,d24
+	vbsl	d29,d17,d18		@ Ch(e,f,g)
+	vshr.u64	d24,d20,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d19
+	vshr.u64	d25,d20,#34
+	vsli.64	d24,d20,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d20,#39
+	vadd.i64	d28,d12
+	vsli.64	d25,d20,#30
+	veor	d30,d20,d21
+	vsli.64	d26,d20,#25
+	veor	d19,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d22,d21		@ Maj(a,b,c)
+	veor	d19,d26			@ Sigma0(a)
+	vadd.i64	d23,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d19,d30
+	vshr.u64	d24,d23,#14	@ 29
+#if 29<16
+	vld1.64	{d13},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d23,#18
+#if 29>0
+	vadd.i64	d19,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d23,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d23,#50
+	vsli.64	d25,d23,#46
+	vmov	d29,d23
+	vsli.64	d26,d23,#23
+#if 29<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	veor	d25,d24
+	vbsl	d29,d16,d17		@ Ch(e,f,g)
+	vshr.u64	d24,d19,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d18
+	vshr.u64	d25,d19,#34
+	vsli.64	d24,d19,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d19,#39
+	vadd.i64	d28,d13
+	vsli.64	d25,d19,#30
+	veor	d30,d19,d20
+	vsli.64	d26,d19,#25
+	veor	d18,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d21,d20		@ Maj(a,b,c)
+	veor	d18,d26			@ Sigma0(a)
+	vadd.i64	d22,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d18,d30
+	vshr.u64	q12,q6,#19
+	vshr.u64	q13,q6,#61
+	vadd.i64	d18,d30			@ h+=Maj from the past
+	vshr.u64	q15,q6,#6
+	vsli.64	q12,q6,#45
+	vext.8	q14,q7,q0,#8	@ X[i+1]
+	vsli.64	q13,q6,#3
+	veor	q15,q12
+	vshr.u64	q12,q14,#1
+	veor	q15,q13				@ sigma1(X[i+14])
+	vshr.u64	q13,q14,#8
+	vadd.i64	q7,q15
+	vshr.u64	q15,q14,#7
+	vsli.64	q12,q14,#63
+	vsli.64	q13,q14,#56
+	vext.8	q14,q3,q4,#8	@ X[i+9]
+	veor	q15,q12
+	vshr.u64	d24,d22,#14		@ from NEON_00_15
+	vadd.i64	q7,q14
+	vshr.u64	d25,d22,#18		@ from NEON_00_15
+	veor	q15,q13				@ sigma0(X[i+1])
+	vshr.u64	d26,d22,#41		@ from NEON_00_15
+	vadd.i64	q7,q15
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d22,#50
+	vsli.64	d25,d22,#46
+	vmov	d29,d22
+	vsli.64	d26,d22,#23
+#if 30<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	veor	d25,d24
+	vbsl	d29,d23,d16		@ Ch(e,f,g)
+	vshr.u64	d24,d18,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d17
+	vshr.u64	d25,d18,#34
+	vsli.64	d24,d18,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d18,#39
+	vadd.i64	d28,d14
+	vsli.64	d25,d18,#30
+	veor	d30,d18,d19
+	vsli.64	d26,d18,#25
+	veor	d17,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d20,d19		@ Maj(a,b,c)
+	veor	d17,d26			@ Sigma0(a)
+	vadd.i64	d21,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d17,d30
+	vshr.u64	d24,d21,#14	@ 31
+#if 31<16
+	vld1.64	{d15},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d21,#18
+#if 31>0
+	vadd.i64	d17,d30			@ h+=Maj from the past
+#endif
+	vshr.u64	d26,d21,#41
+	vld1.64	{d28},[r3,:64]!	@ K[i++]
+	vsli.64	d24,d21,#50
+	vsli.64	d25,d21,#46
+	vmov	d29,d21
+	vsli.64	d26,d21,#23
+#if 31<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	veor	d25,d24
+	vbsl	d29,d22,d23		@ Ch(e,f,g)
+	vshr.u64	d24,d17,#28
+	veor	d26,d25			@ Sigma1(e)
+	vadd.i64	d27,d29,d16
+	vshr.u64	d25,d17,#34
+	vsli.64	d24,d17,#36
+	vadd.i64	d27,d26
+	vshr.u64	d26,d17,#39
+	vadd.i64	d28,d15
+	vsli.64	d25,d17,#30
+	veor	d30,d17,d18
+	vsli.64	d26,d17,#25
+	veor	d16,d24,d25
+	vadd.i64	d27,d28
+	vbsl	d30,d19,d18		@ Maj(a,b,c)
+	veor	d16,d26			@ Sigma0(a)
+	vadd.i64	d20,d27
+	vadd.i64	d30,d27
+	@ vadd.i64	d16,d30
+	bne	L16_79_neon
+
+	vadd.i64	d16,d30		@ h+=Maj from the past
+	vldmia	r0,{d24,d25,d26,d27,d28,d29,d30,d31}	@ load context to temp
+	vadd.i64	q8,q12		@ vectorized accumulate
+	vadd.i64	q9,q13
+	vadd.i64	q10,q14
+	vadd.i64	q11,q15
+	vstmia	r0,{d16,d17,d18,d19,d20,d21,d22,d23}	@ save context
+	teq	r1,r2
+	sub	r3,#640	@ rewind K512
+	bne	Loop_neon
+
+	VFP_ABI_POP
+	bx	lr				@ .word	0xe12fff1e
+
+#endif
+.byte	83,72,65,53,49,50,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,65,82,77,118,52,47,78,69,79,78,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+.align	2
+#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
+.comm	_OPENSSL_armcap_P,4
+.non_lazy_symbol_pointer
+OPENSSL_armcap_P:
+.indirect_symbol	_OPENSSL_armcap_P
+.long	0
+.private_extern	_OPENSSL_armcap_P
+#endif
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index f17facaf..9fd1f81f 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -22327,6 +22327,7 @@
   <int value="-743103250" label="enable-linkable-ephemeral-apps"/>
   <int value="-741806604" label="DownloadsUi:disabled"/>
   <int value="-723224470" label="enable-password-force-saving:enabled"/>
+  <int value="-722474177" label="browser-side-navigation:disabled"/>
   <int value="-716953514" label="disable-password-separated-signin-flow"/>
   <int value="-715733307" label="force-effective-connection-type"/>
   <int value="-714710496" label="VideoFullscreenOrientationLock:disabled"/>
@@ -22576,6 +22577,7 @@
   <int value="274103741" label="enable-ntp-popular-sites"/>
   <int value="278756320" label="disable-app-list-app-info"/>
   <int value="280644887" label="mash"/>
+  <int value="283232244" label="OmniboxUIExperimentNarrowDropdown:enabled"/>
   <int value="301869874" label="NTPPhysicalWebPageSuggestions:disabled"/>
   <int value="304901781" label="NewUsbBackend:enabled"/>
   <int value="313303258" label="WebPaymentsModifiers:disabled"/>
@@ -22699,6 +22701,7 @@
   <int value="690185633" label="NonValidatingReloadOnNormalReload:disabled"/>
   <int value="691020108" label="NTPCondensedTileLayout:disabled"/>
   <int value="693012666" label="QuickUnlockPin:disabled"/>
+  <int value="694985670" label="OmniboxUIExperimentNarrowDropdown:disabled"/>
   <int value="696600628" label="VibrateRequiresUserGesture:disabled"/>
   <int value="698809951" label="WebRtcHWVP8Encoding:enabled"/>
   <int value="709850261" label="disable-touch-editing"/>
@@ -22897,6 +22900,7 @@
   <int value="1372680885" label="enable-mtp-write-support"/>
   <int value="1373777956" label="disable-threaded-gpu-rasterization"/>
   <int value="1376437124" label="show-cert-link"/>
+  <int value="1377056573" label="browser-side-navigation:enabled"/>
   <int value="1378310092" label="disable-suggestions-service"/>
   <int value="1381746642" label="enable-automatic-password-saving"/>
   <int value="1382500494" label="disable-drive-apps-in-app-list"/>
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 49479bd7..135459f1 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -516,9 +516,8 @@
           ],
        'perf_tests': [
          # crbug.com/698831
-         # ('cc_perftests', 2),
-         # crbug.com/709274
-         # ('load_library_perf_tests', 2),
+         # ('cc_perftests', 'build150-m1'),
+         ('load_library_perf_tests', 'build150-m1'),
          ('net_perftests', 'build150-m1'),
          ('tracing_perftests', 'build150-m1'),
          ('media_perftests', 'build151-m1')]
diff --git a/tools/perf/page_sets/tough_video_cases.py b/tools/perf/page_sets/tough_video_cases.py
index fb487d5..e32cf3ef 100644
--- a/tools/perf/page_sets/tough_video_cases.py
+++ b/tools/perf/page_sets/tough_video_cases.py
@@ -372,20 +372,6 @@
     self.PlayAction(action_runner)
 
 
-class Page35(ToughVideoCasesPage):
-
-  def __init__(self, page_set):
-    super(Page35, self).__init__(
-      url='file://tough_video_cases/video.html?src=crowd720_vp9.webm&seek',
-      page_set=page_set,
-      tags=['vp9', 'video_only', 'seek'])
-
-    self.skip_basic_metrics = True
-
-  def RunPageInteractions(self, action_runner):
-    self.SeekBeforeAndAfterPlayhead(action_runner)
-
-
 class Page36(ToughVideoCasesPage):
 
   def __init__(self, page_set):
@@ -439,5 +425,4 @@
     self.AddStory(Page26(self))
     self.AddStory(Page31(self))
     self.AddStory(Page33(self))
-    self.AddStory(Page35(self))
     self.AddStory(Page36(self))
diff --git a/tools/vim/chromium.ycm_extra_conf.py b/tools/vim/chromium.ycm_extra_conf.py
index 2669573..cfc434c3 100644
--- a/tools/vim/chromium.ycm_extra_conf.py
+++ b/tools/vim/chromium.ycm_extra_conf.py
@@ -45,7 +45,7 @@
 #   * That whole ninja & clang thing? We could support other configs if someone
 #     were willing to write the correct commands and a parser.
 #
-#   * This has only been tested on gPrecise.
+#   * This has only been tested on Linux and macOS.
 
 import os
 import os.path
@@ -233,6 +233,9 @@
   """
   clang_flags = [] + additional_flags
 
+  def abspath(path):
+    return os.path.normpath(os.path.join(out_dir, path))
+
   # Parse flags that are important for YCM's purposes.
   clang_tokens = shlex.split(clang_commandline)
   for flag_index, flag in enumerate(clang_tokens):
@@ -242,8 +245,7 @@
       if flag[2] == '/':
         clang_flags.append(flag)
       else:
-        abs_path = os.path.normpath(os.path.join(out_dir, flag[2:]))
-        clang_flags.append('-I' + abs_path)
+        clang_flags.append('-I' + abspath(flag[2:]))
     elif flag.startswith('-std'):
       clang_flags.append(flag)
     elif flag.startswith('-') and flag[1] in 'DWFfmO':
@@ -257,15 +259,14 @@
       # Copy over both flags.
       if flag_index + 1 < len(clang_tokens):
         clang_flags.append(flag)
-        clang_flags.append(clang_tokens[flag_index + 1])
+        clang_flags.append(abspath(clang_tokens[flag_index + 1]))
     elif flag.startswith('--sysroot='):
       # On Linux we use a sysroot image.
       sysroot_path = flag.lstrip('--sysroot=')
       if sysroot_path.startswith('/'):
         clang_flags.append(flag)
       else:
-        abs_path = os.path.normpath(os.path.join(out_dir, sysroot_path))
-        clang_flags.append('--sysroot=' + abs_path)
+        clang_flags.append('--sysroot=' + abspath(sysroot_path))
   return clang_flags
 
 
diff --git a/tools/vim/tests/chromium.ycm_extra_conf_unittest.py b/tools/vim/tests/chromium.ycm_extra_conf_unittest.py
index 5ed29e91..4655de5f 100755
--- a/tools/vim/tests/chromium.ycm_extra_conf_unittest.py
+++ b/tools/vim/tests/chromium.ycm_extra_conf_unittest.py
@@ -150,8 +150,8 @@
     command_line = self.ycm_extra_conf.GetClangCommandLineFromNinjaForSource(
         self.out_dir, os.path.join(self.chrome_root, 'one.cpp'))
     self.assertEquals(command_line,
-                      ('../../fake-clang++ -Ia -isysroot /mac.sdk -Itag-one '
-                       '../../one.cpp -o obj/one.o'))
+                      ('../../fake-clang++ -Ia -Itag-one ../../one.cpp '
+                       '-o obj/one.o'))
 
   def testCommandLineForUnknownCppFile(self):
     command_line = self.ycm_extra_conf.GetClangCommandLineFromNinjaForSource(
@@ -164,8 +164,8 @@
             self.chrome_root, os.path.join(self.chrome_root, 'one.cpp'))
     self.assertEquals(
         self.NormalizeStringsInList(clang_options), [
-            '-I[SRC]', '-Wno-unknown-warning-option', '-I[OUT]/a', '-isysroot',
-            '/mac.sdk', '-I[OUT]/tag-one'
+            '-I[SRC]', '-Wno-unknown-warning-option', '-I[OUT]/a',
+            '-I[OUT]/tag-one'
         ])
 
   def testOutDirNames(self):
@@ -191,8 +191,7 @@
     self.assertEquals(
         self.NormalizeStringsInList(result['flags']), [
             '-DUSE_CLANG_COMPLETER', '-std=c++11', '-x', 'c++', '-I[SRC]',
-            '-Wno-unknown-warning-option', '-I[OUT]/a', '-isysroot', '/mac.sdk',
-            '-I[OUT]/tag-one'
+            '-Wno-unknown-warning-option', '-I[OUT]/a', '-I[OUT]/tag-one'
         ])
 
   def testGetFlagsForFileForUnknownCppFile(self):
@@ -205,8 +204,7 @@
     self.assertEquals(
         self.NormalizeStringsInList(result['flags']), [
             '-DUSE_CLANG_COMPLETER', '-std=c++11', '-x', 'c++', '-I[SRC]',
-            '-Wno-unknown-warning-option', '-I[OUT]/a', '-isysroot', '/mac.sdk',
-            '-I[OUT]/tag-default'
+            '-Wno-unknown-warning-option', '-I[OUT]/a', '-I[OUT]/tag-default'
         ])
 
   def testGetFlagsForFileForUnknownCppNotTestFile(self):
@@ -219,8 +217,7 @@
     self.assertEquals(
         self.NormalizeStringsInList(result['flags']), [
             '-DUSE_CLANG_COMPLETER', '-std=c++11', '-x', 'c++', '-I[SRC]',
-            '-Wno-unknown-warning-option', '-I[OUT]/a', '-isysroot', '/mac.sdk',
-            '-I[OUT]/tag-default'
+            '-Wno-unknown-warning-option', '-I[OUT]/a', '-I[OUT]/tag-default'
         ])
 
   testGetFlagsForFileForKnownObjcFile = TestLanguage('eight.m', 'objective-c')
@@ -245,8 +242,7 @@
     self.assertEquals(
         self.NormalizeStringsInList(result['flags']), [
             '-DUSE_CLANG_COMPLETER', '-std=c++11', '-x', 'c++', '-I[SRC]',
-            '-Wno-unknown-warning-option', '-I[OUT]/a', '-isysroot', '/mac.sdk',
-            '-I[OUT]/tag-default'
+            '-Wno-unknown-warning-option', '-I[OUT]/a', '-I[OUT]/tag-default'
         ])
 
   def testGetFlagsForFileForUnknownUnittestFile(self):
@@ -259,7 +255,7 @@
     self.assertEquals(
         self.NormalizeStringsInList(result['flags']), [
             '-DUSE_CLANG_COMPLETER', '-std=c++11', '-x', 'c++', '-I[SRC]',
-            '-Wno-unknown-warning-option', '-I[OUT]/a', '-isysroot', '/mac.sdk',
+            '-Wno-unknown-warning-option', '-I[OUT]/a',
             '-I[OUT]/tag-default-test'
         ])
 
@@ -273,7 +269,7 @@
     self.assertEquals(
         self.NormalizeStringsInList(result['flags']), [
             '-DUSE_CLANG_COMPLETER', '-std=c++11', '-x', 'c++', '-I[SRC]',
-            '-Wno-unknown-warning-option', '-I[OUT]/a', '-isysroot', '/mac.sdk',
+            '-Wno-unknown-warning-option', '-I[OUT]/a',
             '-I[OUT]/tag-default-test'
         ])
 
@@ -287,8 +283,7 @@
     self.assertEquals(
         self.NormalizeStringsInList(result['flags']), [
             '-DUSE_CLANG_COMPLETER', '-std=c++11', '-x', 'c++', '-I[SRC]',
-            '-Wno-unknown-warning-option', '-I[OUT]/a', '-isysroot', '/mac.sdk',
-            '-I[OUT]/tag-three'
+            '-Wno-unknown-warning-option', '-I[OUT]/a', '-I[OUT]/tag-three'
         ])
 
   def testSourceFileWithNonClangOutputs(self):
@@ -315,8 +310,7 @@
     self.assertEquals(
         self.NormalizeStringsInList(result['flags']), [
             '-DUSE_CLANG_COMPLETER', '-std=c++11', '-x', 'c++', '-I[SRC]',
-            '-Wno-unknown-warning-option', '-I[OUT]/a', '-isysroot', '/mac.sdk',
-            '-I[OUT]/tag-four'
+            '-Wno-unknown-warning-option', '-I[OUT]/a', '-I[OUT]/tag-four'
         ])
 
   def testSourceFileWithOnlyNonClangOutputs(self):
@@ -329,8 +323,7 @@
     self.assertEquals(
         self.NormalizeStringsInList(result['flags']), [
             '-DUSE_CLANG_COMPLETER', '-std=c++11', '-x', 'c++', '-I[SRC]',
-            '-Wno-unknown-warning-option', '-I[OUT]/a', '-isysroot', '/mac.sdk',
-            '-I[OUT]/tag-default'
+            '-Wno-unknown-warning-option', '-I[OUT]/a', '-I[OUT]/tag-default'
         ])
 
   def testGetFlagsForSysrootAbsPath(self):
@@ -350,6 +343,8 @@
             '-Wno-unknown-warning-option',
             '-I[OUT]/a',
             '--sysroot=/usr/lib/sysroot-image',
+            '-isysroot',
+            '/mac.sdk',
         ])
 
   def testGetFlagsForSysrootRelPath(self):
@@ -369,6 +364,8 @@
             '-Wno-unknown-warning-option',
             '-I[OUT]/a',
             '--sysroot=[SRC]/build/sysroot-image',
+            '-isysroot',
+            '[SRC]/build/mac.sdk',
         ])
 
 
diff --git a/tools/vim/tests/data/fake_build_ninja.txt b/tools/vim/tests/data/fake_build_ninja.txt
index 17d0914..5fffada 100644
--- a/tools/vim/tests/data/fake_build_ninja.txt
+++ b/tools/vim/tests/data/fake_build_ninja.txt
@@ -11,13 +11,13 @@
 default_test_file = ../../base/logging_unittest.cc
 
 rule cxx
-  command = $cxx -Ia -isysroot /mac.sdk -Itag-$tag $in -o $out
+  command = $cxx -Ia -Itag-$tag $in -o $out
 
 rule cxx_sysroot_abs
-  command = $cxx -Ia --sysroot=/usr/lib/sysroot-image $in -o $out
+  command = $cxx -Ia --sysroot=/usr/lib/sysroot-image -isysroot /mac.sdk $in -o $out
 
 rule cxx_sysroot_rel
-  command = $cxx -Ia --sysroot=../../build/sysroot-image $in -o $out
+  command = $cxx -Ia --sysroot=../../build/sysroot-image -isysroot ../../build/mac.sdk $in -o $out
 
 rule link
   command = $link $in $out
diff --git a/ui/app_list/views/search_result_answer_card_view.cc b/ui/app_list/views/search_result_answer_card_view.cc
index 0132a12..009a232 100644
--- a/ui/app_list/views/search_result_answer_card_view.cc
+++ b/ui/app_list/views/search_result_answer_card_view.cc
@@ -42,6 +42,8 @@
       return;
     selected_ = selected;
     UpdateBackgroundColor();
+    if (selected)
+      ScrollRectToVisible(GetLocalBounds());
   }
 
   void SetSearchResult(SearchResult* search_result) {
diff --git a/ui/app_list/views/search_result_list_view.cc b/ui/app_list/views/search_result_list_view.cc
index 4835d5f..1f820a44 100644
--- a/ui/app_list/views/search_result_list_view.cc
+++ b/ui/app_list/views/search_result_list_view.cc
@@ -191,6 +191,7 @@
 
   if (new_selected >= 0) {
     SearchResultView* selected_view = GetResultViewAt(new_selected);
+    ScrollRectToVisible(selected_view->bounds());
     selected_view->ClearSelectedAction();
     selected_view->SchedulePaint();
     selected_view->NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true);
diff --git a/ui/app_list/views/search_result_page_view.cc b/ui/app_list/views/search_result_page_view.cc
index 67e6b72..d94b6d7 100644
--- a/ui/app_list/views/search_result_page_view.cc
+++ b/ui/app_list/views/search_result_page_view.cc
@@ -19,6 +19,8 @@
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/shadow_value.h"
 #include "ui/views/background.h"
+#include "ui/views/controls/scroll_view.h"
+#include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/fill_layout.h"
 #include "ui/views/shadow_border.h"
@@ -53,11 +55,23 @@
   ~SearchCardView() override {}
 };
 
+class ZeroWidthVerticalScrollBar : public views::OverlayScrollBar {
+ public:
+  ZeroWidthVerticalScrollBar() : OverlayScrollBar(false) {}
+
+  // OverlayScrollBar overrides:
+  int GetThickness() const override { return 0; }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ZeroWidthVerticalScrollBar);
+};
+
 }  // namespace
 
 SearchResultPageView::SearchResultPageView()
     : selected_index_(0),
-      is_fullscreen_app_list_enabled_(features::IsFullscreenAppListEnabled()) {
+      is_fullscreen_app_list_enabled_(features::IsFullscreenAppListEnabled()),
+      contents_view_(new views::View) {
   gfx::ShadowValue shadow = GetShadowForZHeight(kSearchResultZHeight);
   std::unique_ptr<views::Border> border(new views::ShadowBorder(shadow));
 
@@ -68,8 +82,19 @@
   views::BoxLayout* layout = new views::BoxLayout(views::BoxLayout::kVertical,
                                                   gfx::Insets(), kGroupSpacing);
   layout->set_inside_border_insets(insets);
+  contents_view_->SetLayoutManager(layout);
 
-  SetLayoutManager(layout);
+  views::ScrollView* const scroller = new views::ScrollView;
+  scroller->SetContents(contents_view_);
+  // Setting clip height is necessary to make ScrollView take into account its
+  // contents' size. Using zeroes doesn't prevent it from scrolling and sizing
+  // correctly.
+  scroller->ClipHeightTo(0, 0);
+  scroller->SetVerticalScrollBar(new ZeroWidthVerticalScrollBar);
+  scroller->SetBackgroundColor(SK_ColorTRANSPARENT);
+  AddChildView(scroller);
+
+  SetLayoutManager(new views::FillLayout);
 }
 
 SearchResultPageView::~SearchResultPageView() {
@@ -85,7 +110,7 @@
 void SearchResultPageView::AddSearchResultContainerView(
     AppListModel::SearchResults* results_model,
     SearchResultContainerView* result_container) {
-  AddChildView(new SearchCardView(result_container));
+  contents_view_->AddChildView(new SearchCardView(result_container));
   result_container_views_.push_back(result_container);
   result_container->SetResults(results_model);
   result_container->set_delegate(this);
@@ -188,7 +213,7 @@
   int result_y_index = 0;
   for (size_t i = 0; i < result_container_views_.size(); ++i) {
     SearchResultContainerView* view = result_container_views_[i];
-    ReorderChildView(view->parent(), i);
+    contents_view_->ReorderChildView(view->parent(), i);
 
     view->NotifyFirstResultYIndex(result_y_index);
 
diff --git a/ui/app_list/views/search_result_page_view.h b/ui/app_list/views/search_result_page_view.h
index f929ed63..0691e67f 100644
--- a/ui/app_list/views/search_result_page_view.h
+++ b/ui/app_list/views/search_result_page_view.h
@@ -69,6 +69,9 @@
   // Whether launcher is shown in fullscreen mode.
   bool const is_fullscreen_app_list_enabled_;
 
+  // View containing SearchCardView instances. Owned by view hierarchy.
+  views::View* const contents_view_;
+
   DISALLOW_COPY_AND_ASSIGN(SearchResultPageView);
 };
 
diff --git a/ui/app_list/views/search_result_tile_item_list_view.cc b/ui/app_list/views/search_result_tile_item_list_view.cc
index 5f163b0c..78ff797 100644
--- a/ui/app_list/views/search_result_tile_item_list_view.cc
+++ b/ui/app_list/views/search_result_tile_item_list_view.cc
@@ -94,8 +94,10 @@
   if (old_selected >= 0)
     tile_views_[old_selected]->SetSelected(false);
 
-  if (new_selected >= 0)
+  if (new_selected >= 0) {
     tile_views_[new_selected]->SetSelected(true);
+    ScrollRectToVisible(GetLocalBounds());
+  }
 }
 
 bool SearchResultTileItemListView::OnKeyPressed(const ui::KeyEvent& event) {
diff --git a/ui/aura/mus/window_port_mus.cc b/ui/aura/mus/window_port_mus.cc
index 03acb08f..72af5f3 100644
--- a/ui/aura/mus/window_port_mus.cc
+++ b/ui/aura/mus/window_port_mus.cc
@@ -539,7 +539,7 @@
       nullptr,
       aura::Env::GetInstance()->context_factory()->GetGpuMemoryBufferManager());
   local_compositor_frame_sink_ = frame_sink->GetWeakPtr();
-  return frame_sink;
+  return std::move(frame_sink);
 }
 
 cc::SurfaceId WindowPortMus::GetSurfaceId() const {
diff --git a/ui/base/models/dialog_model.h b/ui/base/models/dialog_model.h
index 5607a16..d42d520c 100644
--- a/ui/base/models/dialog_model.h
+++ b/ui/base/models/dialog_model.h
@@ -30,10 +30,6 @@
   // present, ui::DIALOG_BUTTON_NONE otherwise.
   virtual int GetDefaultDialogButton() const = 0;
 
-  // Returns whether the default dialog button should be colored blue as a call
-  // to action.
-  virtual bool ShouldDefaultButtonBeBlue() const = 0;
-
   // Returns the label of the specified dialog button.
   virtual base::string16 GetDialogButtonLabel(DialogButton button) const = 0;
 
diff --git a/ui/views/controls/button/md_text_button.cc b/ui/views/controls/button/md_text_button.cc
index 55159d8..43c0b48b 100644
--- a/ui/views/controls/button/md_text_button.cc
+++ b/ui/views/controls/button/md_text_button.cc
@@ -28,6 +28,14 @@
 
 namespace {
 
+bool UseMaterialSecondaryButtons() {
+#if defined(OS_MACOSX)
+  return true;
+#else
+  return ui::MaterialDesignController::IsSecondaryUiMaterial();
+#endif  // defined(OS_MACOSX)
+}
+
 LabelButton* CreateButton(ButtonListener* listener,
                           const base::string16& text,
                           bool md) {
@@ -44,15 +52,14 @@
 // static
 LabelButton* MdTextButton::CreateSecondaryUiButton(ButtonListener* listener,
                                                    const base::string16& text) {
-  return CreateButton(listener, text,
-                      ui::MaterialDesignController::IsSecondaryUiMaterial());
+  return CreateButton(listener, text, UseMaterialSecondaryButtons());
 }
 
 // static
 LabelButton* MdTextButton::CreateSecondaryUiBlueButton(
     ButtonListener* listener,
     const base::string16& text) {
-  if (ui::MaterialDesignController::IsSecondaryUiMaterial()) {
+  if (UseMaterialSecondaryButtons()) {
     MdTextButton* md_button =
         MdTextButton::Create(listener, text, style::CONTEXT_BUTTON_MD);
     md_button->SetProminent(true);
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index 0bc292f..be21567 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -500,8 +500,8 @@
   if (drag_drop_client_)
     aura::client::SetDragDropClient(host_->window(), drag_drop_client_.get());
 
-  static_cast<aura::client::FocusClient*>(focus_client_.get())->
-      FocusWindow(content_window_);
+  wm::SetActivationDelegate(content_window_, this);
+  aura::client::GetFocusClient(content_window_)->FocusWindow(content_window_);
 
   OnHostResized(host());
 
@@ -537,10 +537,6 @@
   event_client_.reset(new DesktopEventClient);
   aura::client::SetEventClient(host_->window(), event_client_.get());
 
-  aura::client::GetFocusClient(content_window_)->FocusWindow(content_window_);
-
-  wm::SetActivationDelegate(content_window_, this);
-
   shadow_controller_.reset(
       new wm::ShadowController(wm::GetActivationClient(host_->window())));
 
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
index 872cd30..0e8bd99 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
@@ -12,6 +12,7 @@
 #include "build/build_config.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/cursor_client.h"
+#include "ui/aura/client/focus_client.h"
 #include "ui/aura/client/window_parenting_client.h"
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/aura/window.h"
@@ -103,6 +104,21 @@
   EXPECT_FALSE(widget.GetNativeView()->IsVisible());
 }
 
+// Verifies that the native view isn't activated if Widget requires that.
+TEST_F(DesktopNativeWidgetAuraTest, NativeViewNoActivate) {
+  // Widget of TYPE_POPUP can't be activated.
+  Widget widget;
+  Widget::InitParams init_params = CreateParams(Widget::InitParams::TYPE_POPUP);
+  init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  DesktopNativeWidgetAura* widget_aura = new DesktopNativeWidgetAura(&widget);
+  init_params.native_widget = widget_aura;
+  widget.Init(init_params);
+
+  EXPECT_FALSE(widget.CanActivate());
+  EXPECT_EQ(nullptr, aura::client::GetFocusClient(widget_aura->content_window())
+                         ->GetFocusedWindow());
+}
+
 // Verifies that if the DesktopWindowTreeHost is already shown, the native view
 // still reports not visible as we haven't shown the content window.
 TEST_F(DesktopNativeWidgetAuraTest, WidgetNotVisibleOnlyWindowTreeHostShown) {
diff --git a/ui/views/window/dialog_client_view.cc b/ui/views/window/dialog_client_view.cc
index a9414fb..0e4a4c34 100644
--- a/ui/views/window/dialog_client_view.cc
+++ b/ui/views/window/dialog_client_view.cc
@@ -282,13 +282,8 @@
                             (type != ui::DIALOG_BUTTON_CANCEL ||
                              PlatformStyle::kDialogDefaultButtonCanBeCancel);
 
-    // The default button is always blue in Harmony.
-    if (is_default && (ui::MaterialDesignController::IsSecondaryUiMaterial() ||
-                       delegate->ShouldDefaultButtonBeBlue())) {
-      button = MdTextButton::CreateSecondaryUiBlueButton(this, title);
-    } else {
-      button = MdTextButton::CreateSecondaryUiButton(this, title);
-    }
+    button = is_default ? MdTextButton::CreateSecondaryUiBlueButton(this, title)
+                        : MdTextButton::CreateSecondaryUiButton(this, title);
 
     const int minimum_width = LayoutProvider::Get()->GetDistanceMetric(
         views::DISTANCE_DIALOG_BUTTON_MINIMUM_WIDTH);
diff --git a/ui/views/window/dialog_delegate.cc b/ui/views/window/dialog_delegate.cc
index 0d6b99fe..b02a804 100644
--- a/ui/views/window/dialog_delegate.cc
+++ b/ui/views/window/dialog_delegate.cc
@@ -147,10 +147,6 @@
   return ui::DIALOG_BUTTON_NONE;
 }
 
-bool DialogDelegate::ShouldDefaultButtonBeBlue() const {
-  return false;
-}
-
 base::string16 DialogDelegate::GetDialogButtonLabel(
     ui::DialogButton button) const {
   if (button == ui::DIALOG_BUTTON_OK)
diff --git a/ui/views/window/dialog_delegate.h b/ui/views/window/dialog_delegate.h
index 9f19c73..becd0692 100644
--- a/ui/views/window/dialog_delegate.h
+++ b/ui/views/window/dialog_delegate.h
@@ -95,7 +95,6 @@
   // Overridden from ui::DialogModel:
   int GetDialogButtons() const override;
   int GetDefaultDialogButton() const override;
-  bool ShouldDefaultButtonBeBlue() const override;
   base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
   bool IsDialogButtonEnabled(ui::DialogButton button) const override;