Index: content/public/android/java/src/org/chromium/content/browser/installedapp/InstalledAppProviderImpl.java |
diff --git a/content/public/android/java/src/org/chromium/content/browser/installedapp/InstalledAppProviderImpl.java b/content/public/android/java/src/org/chromium/content/browser/installedapp/InstalledAppProviderImpl.java |
index d07abed0a3f938dd176d1d87d8d89a9ea214e5ea..f31e0804a705dd24558cfa57f10294b8d38621bc 100644 |
--- a/content/public/android/java/src/org/chromium/content/browser/installedapp/InstalledAppProviderImpl.java |
+++ b/content/public/android/java/src/org/chromium/content/browser/installedapp/InstalledAppProviderImpl.java |
@@ -109,10 +109,22 @@ public class InstalledAppProviderImpl implements InstalledAppProvider { |
* @param frameUrl Returns false if the Android package does not declare association with the |
* origin of this URL. Can be null. |
*/ |
- private static boolean isAppInstalledAndAssociatedWithOrigin( |
+ private boolean isAppInstalledAndAssociatedWithOrigin( |
String packageName, URI frameUrl, PackageManager pm) { |
if (frameUrl == null) return false; |
+ // Important timing-attack prevention measure: delay by a pseudo-random amount of time, to |
+ // add significant noise to the time taken to check whether this app is installed and |
+ // related. Otherwise, it would be possible to tell whether a non-related app is installed, |
+ // based on the time this operation takes. |
+ // |
+ // Generate a 16-bit hash based on a unique device ID + the package name. |
+ short hash = PackageHash.hashForPackage(packageName); |
+ |
+ // The time delay is the low 13 bits of the hash in usec (between 0 and 8.192ms). |
palmer
2017/04/07 18:56:33
Pico-nit: Use "ms" consistently (not "usec").
Matt Giuca
2017/04/10 08:33:40
Not sure what you mean by this. Are you asking me
|
+ int sleepUsec = hash & 0x1fff; |
+ sleep(sleepUsec / 1000, (sleepUsec % 1000) * 1000); |
+ |
// Early-exit if the Android app is not installed. |
JSONArray statements; |
try { |
@@ -247,4 +259,20 @@ public class InstalledAppProviderImpl implements InstalledAppProvider { |
return assetUrl.getScheme().equals(frameUrl.getScheme()) |
&& assetUrl.getAuthority().equals(frameUrl.getAuthority()); |
} |
+ |
+ /** |
+ * Puts the current thread to sleep for a given amount of time. |
+ * |
+ * This is approximate but should at least be accurate to the millisecond. |
+ * |
+ * Protected and non-static for testing. |
+ */ |
+ protected void sleep(long millis, int nanos) { |
+ try { |
+ Thread.sleep(millis, nanos); |
+ } catch (InterruptedException e) { |
+ // Continue to interrupt the thread after this completes. |
+ Thread.currentThread().interrupt(); |
+ } |
+ } |
} |