From: csagan5 <32685696+csagan5@users.noreply.github.com>
Date: Fri, 30 Mar 2018 10:09:03 +0200
Subject: Add fingerprinting mitigation for getClientRects,
 getBoundingClientRect

Scale the result of Range::getClientRects and Element::getBoundingClientRect
by a random +/-3% of the original value for each float in the Rect/Quad.
The random value is generated once for each Document and re-used for all the
attached elements.
The rationale is that such value, albeit constant within the rendered Document,
is within the same order of magniture of the floating point precision being
used for fingerprinting and sufficient to poison the well.

See also: http://www.gsd.inesc-id.pt/~mpc/pubs/fingerprinting-trustcom2016.pdf
---
 third_party/blink/renderer/core/dom/document.cc | 14 ++++++++++++++
 third_party/blink/renderer/core/dom/document.h  |  5 +++++
 third_party/blink/renderer/core/dom/element.cc  |  7 +++++++
 third_party/blink/renderer/core/dom/range.cc    |  8 +++++++-
 4 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -279,6 +279,8 @@
 
 #include "extensions/anti_amp_cure.h"
 
+#include "base/rand_util.h"
+
 #ifndef NDEBUG
 using WeakDocumentSet =
     blink::PersistentHeapHashSet<blink::WeakMember<blink::Document>>;
@@ -740,6 +742,10 @@ Document::Document(const DocumentInit& initializer,
 #ifndef NDEBUG
   liveDocumentSet().insert(this);
 #endif
+
+  // add +/- 3% noise against fingerprinting
+  shuffleFactorX_ = 1 + (base::RandDouble() - 0.5) * 0.03;
+  shuffleFactorY_ = 1 + (base::RandDouble() - 0.5) * 0.03;
 }
 
 Document::~Document() {
@@ -766,6 +772,14 @@ Range* Document::CreateRangeAdjustedToTreeScope(const TreeScope& tree_scope,
                        Position::BeforeNode(*shadow_host));
 }
 
+double Document::GetShuffleFactorX() {
+	return shuffleFactorX_;
+}
+
+double Document::GetShuffleFactorY() {
+	return shuffleFactorY_;
+}
+
 SelectorQueryCache& Document::GetSelectorQueryCache() {
   if (!selector_query_cache_)
     selector_query_cache_ = std::make_unique<SelectorQueryCache>();
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
--- a/third_party/blink/renderer/core/dom/document.h
+++ b/third_party/blink/renderer/core/dom/document.h
@@ -408,6 +408,9 @@ class CORE_EXPORT Document : public ContainerNode,
 
   String origin() const;
 
+  double GetShuffleFactorX();
+  double GetShuffleFactorY();
+
   String visibilityState() const;
   mojom::PageVisibilityState GetPageVisibilityState() const;
   bool hidden() const;
@@ -1670,6 +1673,8 @@ class CORE_EXPORT Document : public ContainerNode,
 
   double start_time_;
 
+  double shuffleFactorX_, shuffleFactorY_;
+
   TraceWrapperMember<ScriptRunner> script_runner_;
 
   HeapVector<Member<ScriptElementBase>> current_script_stack_;
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -1348,6 +1348,11 @@ DOMRectList* Element::getClientRects() {
   DCHECK(element_layout_object);
   GetDocument().AdjustFloatQuadsForScrollAndAbsoluteZoom(
       quads, *element_layout_object);
+
+  for (FloatQuad& quad : quads) {
+    quad.Scale(GetDocument().GetShuffleFactorX(), GetDocument().GetShuffleFactorY());
+  }
+
   return DOMRectList::Create(quads);
 }
 
@@ -1365,6 +1370,8 @@ DOMRect* Element::getBoundingClientRect() {
   DCHECK(element_layout_object);
   GetDocument().AdjustFloatRectForScrollAndAbsoluteZoom(result,
                                                         *element_layout_object);
+  result.Scale(GetDocument().GetShuffleFactorX(), GetDocument().GetShuffleFactorY());
+
   return DOMRect::FromFloatRect(result);
 }
 
diff --git a/third_party/blink/renderer/core/dom/range.cc b/third_party/blink/renderer/core/dom/range.cc
--- a/third_party/blink/renderer/core/dom/range.cc
+++ b/third_party/blink/renderer/core/dom/range.cc
@@ -1575,11 +1575,17 @@ DOMRectList* Range::getClientRects() const {
   Vector<FloatQuad> quads;
   GetBorderAndTextQuads(quads);
 
+  for (FloatQuad& quad : quads) {
+    quad.Scale(owner_document_->GetShuffleFactorX(), owner_document_->GetShuffleFactorY());
+  }
+
   return DOMRectList::Create(quads);
 }
 
 DOMRect* Range::getBoundingClientRect() const {
-  return DOMRect::FromFloatRect(BoundingRect());
+  auto rect = BoundingRect();
+  rect.Scale(owner_document_->GetShuffleFactorX(), owner_document_->GetShuffleFactorY());
+  return DOMRect::FromFloatRect(rect);
 }
 
 // TODO(editing-dev): We should make
-- 
2.7.4

