Browse Source

Fix: Gracefully handle key-generation on older iphones

Neeraj Gupta 2 years ago
parent
commit
d1b6caf40e
2 changed files with 61 additions and 0 deletions
  1. 17 0
      lib/utils/crypto_util.dart
  2. 44 0
      lib/utils/device_info.dart

+ 17 - 0
lib/utils/crypto_util.dart

@@ -6,6 +6,7 @@ import 'package:flutter_sodium/flutter_sodium.dart';
 import 'package:logging/logging.dart';
 import 'package:logging/logging.dart';
 import 'package:photos/models/derived_key_result.dart';
 import 'package:photos/models/derived_key_result.dart';
 import 'package:photos/models/encryption_result.dart';
 import 'package:photos/models/encryption_result.dart';
+import "package:photos/utils/device_info.dart";
 
 
 const int encryptionChunkSize = 4 * 1024 * 1024;
 const int encryptionChunkSize = 4 * 1024 * 1024;
 final int decryptionChunkSize =
 final int decryptionChunkSize =
@@ -377,6 +378,22 @@ class CryptoUtil {
     final logger = Logger("pwhash");
     final logger = Logger("pwhash");
     int memLimit = Sodium.cryptoPwhashMemlimitSensitive;
     int memLimit = Sodium.cryptoPwhashMemlimitSensitive;
     int opsLimit = Sodium.cryptoPwhashOpslimitSensitive;
     int opsLimit = Sodium.cryptoPwhashOpslimitSensitive;
+    if (await isLowSpecDevice()) {
+      logger.info("low spec device detected");
+      // When sensitive memLimit (1 GB) is used, on low spec device the OS might
+      // kill the app with OOM. To avoid that, start with 256 MB and
+      // corresponding ops limit (16).
+      // This ensures that the product of these two variables
+      // (the area under the graph that determines the amount of work required)
+      // stays the same
+      // SODIUM_CRYPTO_PWHASH_MEMLIMIT_SENSITIVE: 1073741824
+      // SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE: 268435456
+      // SODIUM_CRYPTO_PWHASH_OPSLIMIT_SENSITIVE: 4
+      memLimit = Sodium.cryptoPwhashMemlimitModerate;
+      final factor = Sodium.cryptoPwhashMemlimitSensitive ~/
+          Sodium.cryptoPwhashMemlimitModerate; // = 4
+      opsLimit = opsLimit * factor; // = 16
+    }
     Uint8List key;
     Uint8List key;
     while (memLimit >= Sodium.cryptoPwhashMemlimitMin &&
     while (memLimit >= Sodium.cryptoPwhashMemlimitMin &&
         opsLimit <= Sodium.cryptoPwhashOpslimitMax) {
         opsLimit <= Sodium.cryptoPwhashOpslimitMax) {

+ 44 - 0
lib/utils/device_info.dart

@@ -0,0 +1,44 @@
+import 'dart:io';
+
+import "package:device_info/device_info.dart";
+import 'package:flutter/foundation.dart';
+import 'package:logging/logging.dart';
+
+late DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
+
+// https://gist.github.com/adamawolf/3048717
+late Set<String> iOSLowEndMachineCodes = <String>{
+  "iPhone5,1", //iPhone 5 (GSM)
+  "iPhone5,2", //iPhone 5 (GSM+CDMA)
+  "iPhone5,3", //iPhone 5C (GSM)
+  "iPhone5,4", //iPhone 5C (Global)
+  "iPhone6,1", //iPhone 5S (GSM)
+  "iPhone6,2", //iPhone 5S (Global)
+  "iPhone7,1", //iPhone 6 Plus
+  "iPhone7,2", //iPhone 6
+  "iPhone8,1", // iPhone 6s
+  "iPhone8,2", // iPhone 6s Plus
+  "iPhone8,4", // iPhone SE (GSM)
+  "iPhone9,1", // iPhone 7
+  "iPhone9,2", // iPhone 7 Plus
+  "iPhone9,3", // iPhone 7
+  "iPhone9,4", // iPhone 7 Plus
+  "iPhone10,1", // iPhone 8
+  "iPhone10,2", // iPhone 8 Plus
+  "iPhone10,3", // iPhone X Global
+  "iPhone10,4", // iPhone 8
+  "iPhone10,5" //  iPhone 8
+};
+
+Future<bool> isLowSpecDevice() async {
+  try {
+    if (Platform.isIOS) {
+      final IosDeviceInfo iosInfo = await deviceInfoPlugin.iosInfo;
+      debugPrint("ios utc name ${iosInfo.utsname.machine}");
+      return iOSLowEndMachineCodes.contains(iosInfo.utsname.machine);
+    }
+  } catch (e) {
+    Logger("device_info").severe("deviceSpec check failed", e);
+  }
+  return false;
+}