diff --git a/src/Android/Android.csproj b/src/Android/Android.csproj
index 1d12a7205..48386943a 100644
--- a/src/Android/Android.csproj
+++ b/src/Android/Android.csproj
@@ -116,7 +116,6 @@
-
diff --git a/src/Android/MainApplication.cs b/src/Android/MainApplication.cs
index 72b04a2aa..0460641e5 100644
--- a/src/Android/MainApplication.cs
+++ b/src/Android/MainApplication.cs
@@ -42,11 +42,6 @@ namespace Bit.Droid
RegisterLocalServices();
var deviceActionService = ServiceContainer.Resolve("deviceActionService");
ServiceContainer.Init(deviceActionService.DeviceUserAgent);
- if(App.Migration.MigrationHelpers.NeedsMigration())
- {
- var task = App.Migration.MigrationHelpers.PerformMigrationAsync();
- Task.Delay(2000).Wait();
- }
}
#if !FDROID
if(Build.VERSION.SdkInt <= BuildVersionCodes.Kitkat)
@@ -74,12 +69,6 @@ namespace Bit.Droid
private void RegisterLocalServices()
{
ServiceContainer.Register("logService", new AndroidLogService());
- ServiceContainer.Register("settingsShim", new App.Migration.SettingsShim());
- if(App.Migration.MigrationHelpers.NeedsMigration())
- {
- ServiceContainer.Register(
- "oldSecureStorageService", new Migration.AndroidKeyStoreStorageService());
- }
Refractored.FabControl.Droid.FloatingActionButtonViewRenderer.Init();
// Note: This might cause a race condition. Investigate more.
diff --git a/src/Android/Migration/AndroidKeyStoreStorageService.cs b/src/Android/Migration/AndroidKeyStoreStorageService.cs
deleted file mode 100644
index 94b2d7411..000000000
--- a/src/Android/Migration/AndroidKeyStoreStorageService.cs
+++ /dev/null
@@ -1,373 +0,0 @@
-using Java.Security;
-using Javax.Crypto;
-using Android.OS;
-using Bit.App.Abstractions;
-using System;
-using Android.Security;
-using Javax.Security.Auth.X500;
-using Java.Math;
-using Android.Security.Keystore;
-using Android.App;
-using Java.Util;
-using Javax.Crypto.Spec;
-using Android.Preferences;
-using Bit.App.Migration;
-using Bit.Core.Utilities;
-using Bit.App.Migration.Abstractions;
-
-namespace Bit.Droid.Migration
-{
- public class AndroidKeyStoreStorageService : IOldSecureStorageService
- {
- private const string AndroidKeyStore = "AndroidKeyStore";
- private const string AesMode = "AES/GCM/NoPadding";
-
- private const string KeyAlias = "bitwardenKey2";
- private const string KeyAliasV1 = "bitwardenKey";
-
- private const string SettingsFormat = "ksSecured2:{0}";
- private const string SettingsFormatV1 = "ksSecured:{0}";
-
- private const string AesKey = "ksSecured2:aesKeyForService";
- private const string AesKeyV1 = "ksSecured:aesKeyForService";
-
- private readonly string _rsaMode;
- private readonly bool _oldAndroid;
- private readonly SettingsShim _settings;
- private readonly KeyStore _keyStore;
-
- public AndroidKeyStoreStorageService()
- {
- _oldAndroid = Build.VERSION.SdkInt < BuildVersionCodes.M;
- _rsaMode = _oldAndroid ? "RSA/ECB/PKCS1Padding" : "RSA/ECB/OAEPWithSHA-1AndMGF1Padding";
-
- _settings = ServiceContainer.Resolve("settingsShim");
-
- _keyStore = KeyStore.GetInstance(AndroidKeyStore);
- _keyStore.Load(null);
-
- /*
- try
- {
- GenerateStoreKey(true);
- }
- catch
- {
- GenerateStoreKey(false);
- }
-
- GenerateAesKey();
- */
- }
-
- public bool Contains(string key)
- {
- return _settings.Contains(string.Format(SettingsFormat, key)) ||
- _settings.Contains(string.Format(SettingsFormatV1, key));
- }
-
- public void Delete(string key)
- {
- CleanupOld(key);
-
- var formattedKey = string.Format(SettingsFormat, key);
- if(_settings.Contains(formattedKey))
- {
- _settings.Remove(formattedKey);
- }
- }
-
- public byte[] Retrieve(string key)
- {
- var formattedKey = string.Format(SettingsFormat, key);
- if(!_settings.Contains(formattedKey))
- {
- return TryGetAndMigrate(key);
- }
-
- var cs = _settings.GetValueOrDefault(formattedKey, null);
- if(string.IsNullOrWhiteSpace(cs))
- {
- return null;
- }
-
- var aesKey = GetAesKey();
- if(aesKey == null)
- {
- return null;
- }
-
- try
- {
- return App.Migration.Crypto.AesCbcDecrypt(new App.Migration.Models.CipherString(cs), aesKey);
- }
- catch
- {
- Console.WriteLine("Failed to decrypt from secure storage.");
- _settings.Remove(formattedKey);
- //Utilities.SendCrashEmail(e);
- //Utilities.SaveCrashFile(e);
- return null;
- }
- }
-
- public void Store(string key, byte[] dataBytes)
- {
- var formattedKey = string.Format(SettingsFormat, key);
- CleanupOld(key);
- if(dataBytes == null)
- {
- _settings.Remove(formattedKey);
- return;
- }
-
- var aesKey = GetAesKey();
- if(aesKey == null)
- {
- return;
- }
-
- try
- {
- var cipherString = App.Migration.Crypto.AesCbcEncrypt(dataBytes, aesKey);
- _settings.AddOrUpdateValue(formattedKey, cipherString.EncryptedString);
- }
- catch
- {
- Console.WriteLine("Failed to encrypt to secure storage.");
- //Utilities.SendCrashEmail(e);
- //Utilities.SaveCrashFile(e);
- }
- }
-
- private void GenerateStoreKey(bool withDate)
- {
- if(_keyStore.ContainsAlias(KeyAlias))
- {
- return;
- }
-
- ClearSettings();
-
- var end = Calendar.Instance;
- end.Add(CalendarField.Year, 99);
-
- if(_oldAndroid)
- {
- var subject = new X500Principal($"CN={KeyAlias}");
-
- var builder = new KeyPairGeneratorSpec.Builder(Application.Context)
- .SetAlias(KeyAlias)
- .SetSubject(subject)
- .SetSerialNumber(BigInteger.Ten);
-
- if(withDate)
- {
- builder.SetStartDate(new Date(0)).SetEndDate(end.Time);
- }
-
- var spec = builder.Build();
- var gen = KeyPairGenerator.GetInstance(KeyProperties.KeyAlgorithmRsa, AndroidKeyStore);
- gen.Initialize(spec);
- gen.GenerateKeyPair();
- }
- else
- {
- var builder = new KeyGenParameterSpec.Builder(KeyAlias, KeyStorePurpose.Decrypt | KeyStorePurpose.Encrypt)
- .SetBlockModes(KeyProperties.BlockModeGcm)
- .SetEncryptionPaddings(KeyProperties.EncryptionPaddingNone);
-
- if(withDate)
- {
- builder.SetKeyValidityStart(new Date(0)).SetKeyValidityEnd(end.Time);
- }
-
- var spec = builder.Build();
- var gen = KeyGenerator.GetInstance(KeyProperties.KeyAlgorithmAes, AndroidKeyStore);
- gen.Init(spec);
- gen.GenerateKey();
- }
- }
-
- private KeyStore.PrivateKeyEntry GetRsaKeyEntry(string alias)
- {
- return _keyStore.GetEntry(alias, null) as KeyStore.PrivateKeyEntry;
- }
-
- private void GenerateAesKey()
- {
- if(_settings.Contains(AesKey))
- {
- return;
- }
-
- var key = App.Migration.Crypto.RandomBytes(512 / 8);
- var encKey = _oldAndroid ? RsaEncrypt(key) : AesEncrypt(key);
- _settings.AddOrUpdateValue(AesKey, encKey);
- }
-
- private App.Migration.Models.SymmetricCryptoKey GetAesKey(bool v1 = false)
- {
- try
- {
- var aesKey = v1 ? AesKeyV1 : AesKey;
- if(!_settings.Contains(aesKey))
- {
- return null;
- }
-
- var encKey = _settings.GetValueOrDefault(aesKey, null);
- if(string.IsNullOrWhiteSpace(encKey))
- {
- return null;
- }
-
- if(_oldAndroid || v1)
- {
- var encKeyBytes = Convert.FromBase64String(encKey);
- var key = RsaDecrypt(encKeyBytes, v1);
- return new App.Migration.Models.SymmetricCryptoKey(key);
- }
- else
- {
- var parts = encKey.Split('|');
- if(parts.Length < 2)
- {
- return null;
- }
-
- var ivBytes = Convert.FromBase64String(parts[0]);
- var encKeyBytes = Convert.FromBase64String(parts[1]);
- var key = AesDecrypt(ivBytes, encKeyBytes);
- return new App.Migration.Models.SymmetricCryptoKey(key);
- }
- }
- catch
- {
- Console.WriteLine("Cannot get AesKey.");
- _keyStore.DeleteEntry(KeyAlias);
- _settings.Remove(AesKey);
- if(!v1)
- {
- //Utilities.SendCrashEmail(e);
- //Utilities.SaveCrashFile(e);
- }
- return null;
- }
- }
-
- private string AesEncrypt(byte[] input)
- {
- using(var entry = _keyStore.GetKey(KeyAlias, null))
- using(var cipher = Cipher.GetInstance(AesMode))
- {
- cipher.Init(CipherMode.EncryptMode, entry);
- var encBytes = cipher.DoFinal(input);
- var ivBytes = cipher.GetIV();
- return $"{Convert.ToBase64String(ivBytes)}|{Convert.ToBase64String(encBytes)}";
- }
- }
-
- private byte[] AesDecrypt(byte[] iv, byte[] encData)
- {
- using(var entry = _keyStore.GetKey(KeyAlias, null))
- using(var cipher = Cipher.GetInstance(AesMode))
- {
- var spec = new GCMParameterSpec(128, iv);
- cipher.Init(CipherMode.DecryptMode, entry, spec);
- var decBytes = cipher.DoFinal(encData);
- return decBytes;
- }
- }
-
- private string RsaEncrypt(byte[] data)
- {
- using(var entry = GetRsaKeyEntry(KeyAlias))
- using(var cipher = Cipher.GetInstance(_rsaMode))
- {
- cipher.Init(CipherMode.EncryptMode, entry.Certificate.PublicKey);
- var cipherText = cipher.DoFinal(data);
- return Convert.ToBase64String(cipherText);
- }
- }
-
- private byte[] RsaDecrypt(byte[] encData, bool v1)
- {
- using(var entry = GetRsaKeyEntry(v1 ? KeyAliasV1 : KeyAlias))
- using(var cipher = Cipher.GetInstance(_rsaMode))
- {
- if(_oldAndroid)
- {
- cipher.Init(CipherMode.DecryptMode, entry.PrivateKey);
- }
- else
- {
- cipher.Init(CipherMode.DecryptMode, entry.PrivateKey, OAEPParameterSpec.Default);
- }
-
- var plainText = cipher.DoFinal(encData);
- return plainText;
- }
- }
-
- private byte[] TryGetAndMigrate(string key)
- {
- var formattedKeyV1 = string.Format(SettingsFormatV1, key);
- if(_settings.Contains(formattedKeyV1))
- {
- var aesKeyV1 = GetAesKey(true);
- if(aesKeyV1 != null)
- {
- try
- {
- var cs = _settings.GetValueOrDefault(formattedKeyV1, null);
- var value = App.Migration.Crypto.AesCbcDecrypt(new App.Migration.Models.CipherString(cs), aesKeyV1);
- Store(key, value);
- return value;
- }
- catch
- {
- Console.WriteLine("Failed to decrypt v1 from secure storage.");
- }
- }
-
- _settings.Remove(formattedKeyV1);
- }
-
- return null;
- }
-
- private void CleanupOld(string key)
- {
- var formattedKeyV1 = string.Format(SettingsFormatV1, key);
- if(_settings.Contains(formattedKeyV1))
- {
- _settings.Remove(formattedKeyV1);
- }
- }
-
- private void ClearSettings(string format = SettingsFormat)
- {
- var prefix = string.Format(format, string.Empty);
-
- using(var sharedPreferences = PreferenceManager.GetDefaultSharedPreferences(Application.Context))
- using(var sharedPreferencesEditor = sharedPreferences.Edit())
- {
- var removed = false;
- foreach(var pref in sharedPreferences.All)
- {
- if(pref.Key.StartsWith(prefix))
- {
- removed = true;
- sharedPreferencesEditor.Remove(pref.Key);
- }
- }
-
- if(removed)
- {
- sharedPreferencesEditor.Commit();
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/App/App.xaml.cs b/src/App/App.xaml.cs
index 1585bad42..0995869c2 100644
--- a/src/App/App.xaml.cs
+++ b/src/App/App.xaml.cs
@@ -97,10 +97,6 @@ namespace Bit.App
}
else if(message.Command == "logout")
{
- if(Migration.MigrationHelpers.Migrating)
- {
- return;
- }
Device.BeginInvokeOnMainThread(async () => await LogOutAsync(false));
}
else if(message.Command == "loggedOut")
@@ -355,10 +351,6 @@ namespace Bit.App
private void SyncIfNeeded()
{
- if(Migration.MigrationHelpers.Migrating)
- {
- return;
- }
if(Xamarin.Essentials.Connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.None)
{
return;
diff --git a/src/App/Migration/Abstractions/IOldSecureStorageService.cs b/src/App/Migration/Abstractions/IOldSecureStorageService.cs
deleted file mode 100644
index cc3a53c85..000000000
--- a/src/App/Migration/Abstractions/IOldSecureStorageService.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace Bit.App.Migration.Abstractions
-{
- public interface IOldSecureStorageService
- {
- bool Contains(string key);
- void Delete(string key);
- byte[] Retrieve(string key);
- void Store(string key, byte[] dataBytes);
- }
-}
diff --git a/src/App/Migration/Crypto.cs b/src/App/Migration/Crypto.cs
deleted file mode 100644
index d17ca639a..000000000
--- a/src/App/Migration/Crypto.cs
+++ /dev/null
@@ -1,199 +0,0 @@
-using Bit.App.Migration.Models;
-using Bit.Core.Enums;
-using PCLCrypto;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Bit.App.Migration
-{
- public static class Crypto
- {
- public static CipherString AesCbcEncrypt(byte[] plainBytes, SymmetricCryptoKey key)
- {
- var parts = AesCbcEncryptToParts(plainBytes, key);
- return new CipherString(parts.Item1, Convert.ToBase64String(parts.Item2),
- Convert.ToBase64String(parts.Item4), parts.Item3 != null ? Convert.ToBase64String(parts.Item3) : null);
- }
-
- public static byte[] AesCbcEncryptToBytes(byte[] plainBytes, SymmetricCryptoKey key)
- {
- var parts = AesCbcEncryptToParts(plainBytes, key);
- var macLength = parts.Item3?.Length ?? 0;
-
- var encBytes = new byte[1 + parts.Item2.Length + macLength + parts.Item4.Length];
- encBytes[0] = (byte)parts.Item1;
- parts.Item2.CopyTo(encBytes, 1);
- if(parts.Item3 != null)
- {
- parts.Item3.CopyTo(encBytes, 1 + parts.Item2.Length);
- }
- parts.Item4.CopyTo(encBytes, 1 + parts.Item2.Length + macLength);
- return encBytes;
- }
-
- private static Tuple AesCbcEncryptToParts(byte[] plainBytes,
- SymmetricCryptoKey key)
- {
- if(key == null)
- {
- throw new ArgumentNullException(nameof(key));
- }
-
- if(plainBytes == null)
- {
- throw new ArgumentNullException(nameof(plainBytes));
- }
-
- var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
- var cryptoKey = provider.CreateSymmetricKey(key.EncKey);
- var iv = RandomBytes(provider.BlockLength);
- var ct = WinRTCrypto.CryptographicEngine.Encrypt(cryptoKey, plainBytes, iv);
- var mac = key.MacKey != null ? ComputeMac(ct, iv, key.MacKey) : null;
-
- return new Tuple(key.EncryptionType, iv, mac, ct);
- }
-
- public static byte[] AesCbcDecrypt(CipherString encyptedValue, SymmetricCryptoKey key)
- {
- if(encyptedValue == null)
- {
- throw new ArgumentNullException(nameof(encyptedValue));
- }
-
- return AesCbcDecrypt(encyptedValue.EncryptionType, encyptedValue.CipherTextBytes,
- encyptedValue.InitializationVectorBytes, encyptedValue.MacBytes, key);
- }
-
- public static byte[] AesCbcDecrypt(EncryptionType type, byte[] ct, byte[] iv, byte[] mac,
- SymmetricCryptoKey key)
- {
- if(key == null)
- {
- throw new ArgumentNullException(nameof(key));
- }
-
- if(ct == null)
- {
- throw new ArgumentNullException(nameof(ct));
- }
-
- if(iv == null)
- {
- throw new ArgumentNullException(nameof(iv));
- }
-
- if(key.MacKey != null && mac == null)
- {
- throw new ArgumentNullException(nameof(mac));
- }
-
- if(key.EncryptionType != type)
- {
- throw new InvalidOperationException(nameof(type));
- }
-
- if(key.MacKey != null && mac != null)
- {
- var computedMacBytes = ComputeMac(ct, iv, key.MacKey);
- if(!MacsEqual(computedMacBytes, mac))
- {
- throw new InvalidOperationException("MAC failed.");
- }
- }
-
- var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
- var cryptoKey = provider.CreateSymmetricKey(key.EncKey);
- var decryptedBytes = WinRTCrypto.CryptographicEngine.Decrypt(cryptoKey, ct, iv);
- return decryptedBytes;
- }
-
- public static byte[] RandomBytes(int length)
- {
- return WinRTCrypto.CryptographicBuffer.GenerateRandom(length);
- }
-
- public static byte[] ComputeMac(byte[] ctBytes, byte[] ivBytes, byte[] macKey)
- {
- if(ctBytes == null)
- {
- throw new ArgumentNullException(nameof(ctBytes));
- }
-
- if(ivBytes == null)
- {
- throw new ArgumentNullException(nameof(ivBytes));
- }
-
- return ComputeMac(ivBytes.Concat(ctBytes), macKey);
- }
-
- public static byte[] ComputeMac(IEnumerable dataBytes, byte[] macKey)
- {
- if(macKey == null)
- {
- throw new ArgumentNullException(nameof(macKey));
- }
-
- if(dataBytes == null)
- {
- throw new ArgumentNullException(nameof(dataBytes));
- }
-
- var algorithm = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm(MacAlgorithm.HmacSha256);
- var hasher = algorithm.CreateHash(macKey);
- hasher.Append(dataBytes.ToArray());
- var mac = hasher.GetValueAndReset();
- return mac;
- }
-
- // Safely compare two MACs in a way that protects against timing attacks (Double HMAC Verification).
- // ref: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/
- // ref: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy
- public static bool MacsEqual(byte[] mac1, byte[] mac2)
- {
- var algorithm = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm(MacAlgorithm.HmacSha256);
- var hasher = algorithm.CreateHash(RandomBytes(32));
-
- hasher.Append(mac1);
- mac1 = hasher.GetValueAndReset();
-
- hasher.Append(mac2);
- mac2 = hasher.GetValueAndReset();
-
- if(mac1.Length != mac2.Length)
- {
- return false;
- }
-
- for(int i = 0; i < mac2.Length; i++)
- {
- if(mac1[i] != mac2[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- // ref: https://tools.ietf.org/html/rfc5869
- public static byte[] HkdfExpand(byte[] prk, byte[] info, int size)
- {
- var hashLen = 32; // sha256
- var okm = new byte[size];
- var previousT = new byte[0];
- var n = (int)Math.Ceiling((double)size / hashLen);
- for(int i = 0; i < n; i++)
- {
- var t = new byte[previousT.Length + info.Length + 1];
- previousT.CopyTo(t, 0);
- info.CopyTo(t, previousT.Length);
- t[t.Length - 1] = (byte)(i + 1);
- previousT = ComputeMac(t, prk);
- previousT.CopyTo(okm, i * hashLen);
- }
- return okm;
- }
- }
-}
diff --git a/src/App/Migration/MigrationHelpers.cs b/src/App/Migration/MigrationHelpers.cs
deleted file mode 100644
index af3425c63..000000000
--- a/src/App/Migration/MigrationHelpers.cs
+++ /dev/null
@@ -1,201 +0,0 @@
-using Bit.Core;
-using Bit.Core.Abstractions;
-using Bit.Core.Enums;
-using Bit.Core.Utilities;
-using System;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Bit.App.Migration
-{
- public static class MigrationHelpers
- {
- public static bool Migrating = false;
-
- public static bool NeedsMigration()
- {
- return ServiceContainer.Resolve("settingsShim")
- .GetValueOrDefault(Constants.OldUserIdKey, null) != null; ;
- }
-
- public static async Task PerformMigrationAsync()
- {
- if(!NeedsMigration() || Migrating)
- {
- return false;
- }
-
- Migrating = true;
- var settingsShim = ServiceContainer.Resolve("settingsShim");
- var oldSecureStorageService = ServiceContainer.Resolve(
- "oldSecureStorageService");
-
- var messagingService = ServiceContainer.Resolve("messagingService");
- var storageService = ServiceContainer.Resolve("storageService");
- var secureStorageService = ServiceContainer.Resolve("secureStorageService");
- var cryptoService = ServiceContainer.Resolve("cryptoService");
- var tokenService = ServiceContainer.Resolve("tokenService");
- var userService = ServiceContainer.Resolve("userService");
- var environmentService = ServiceContainer.Resolve("environmentService");
- var passwordGenerationService = ServiceContainer.Resolve(
- "passwordGenerationService");
- var syncService = ServiceContainer.Resolve("syncService");
- var lockService = ServiceContainer.Resolve("lockService");
-
- // Get old data
-
- var oldTokenBytes = oldSecureStorageService.Retrieve("accessToken");
- var oldToken = oldTokenBytes == null ? null : Encoding.UTF8.GetString(
- oldTokenBytes, 0, oldTokenBytes.Length);
- var oldKeyBytes = oldSecureStorageService.Retrieve("key");
- var oldKey = oldKeyBytes == null ? null : new Models.SymmetricCryptoKey(oldKeyBytes);
- var oldUserId = settingsShim.GetValueOrDefault("userId", null);
-
- var isAuthenticated = oldKey != null && !string.IsNullOrWhiteSpace(oldToken) &&
- !string.IsNullOrWhiteSpace(oldUserId);
- if(!isAuthenticated)
- {
- Migrating = false;
- return false;
- }
-
- var oldRefreshTokenBytes = oldSecureStorageService.Retrieve("refreshToken");
- var oldRefreshToken = oldRefreshTokenBytes == null ? null : Encoding.UTF8.GetString(
- oldRefreshTokenBytes, 0, oldRefreshTokenBytes.Length);
- var oldPinBytes = oldSecureStorageService.Retrieve("pin");
- var oldPin = oldPinBytes == null ? null : Encoding.UTF8.GetString(
- oldPinBytes, 0, oldPinBytes.Length);
-
- var oldEncKey = settingsShim.GetValueOrDefault("encKey", null);
- var oldEncPrivateKey = settingsShim.GetValueOrDefault("encPrivateKey", null);
- var oldEmail = settingsShim.GetValueOrDefault("email", null);
- var oldKdf = (KdfType)settingsShim.GetValueOrDefault("kdf", (int)KdfType.PBKDF2_SHA256);
- var oldKdfIterations = settingsShim.GetValueOrDefault("kdfIterations", 5000);
-
- var oldTwoFactorTokenBytes = oldSecureStorageService.Retrieve(
- string.Format("twoFactorToken_{0}", Convert.ToBase64String(Encoding.UTF8.GetBytes(oldEmail))));
- var oldTwoFactorToken = oldTwoFactorTokenBytes == null ? null : Encoding.UTF8.GetString(
- oldTwoFactorTokenBytes, 0, oldTwoFactorTokenBytes.Length);
-
- var oldAppIdBytes = oldSecureStorageService.Retrieve("appId");
- var oldAppId = oldAppIdBytes == null ? null : new Guid(oldAppIdBytes).ToString();
- var oldAnonAppIdBytes = oldSecureStorageService.Retrieve("anonymousAppId");
- var oldAnonAppId = oldAnonAppIdBytes == null ? null : new Guid(oldAnonAppIdBytes).ToString();
- var oldFingerprint = settingsShim.GetValueOrDefault("setting:fingerprintUnlockOn", false);
-
- // Save settings
-
- await storageService.SaveAsync(Constants.AccessibilityAutofillPersistNotificationKey,
- settingsShim.GetValueOrDefault("setting:persistNotification", false));
- await storageService.SaveAsync(Constants.AccessibilityAutofillPasswordFieldKey,
- settingsShim.GetValueOrDefault("setting:autofillPasswordField", false));
- await storageService.SaveAsync(Constants.DisableAutoTotpCopyKey,
- settingsShim.GetValueOrDefault("setting:disableAutoCopyTotp", false));
- await storageService.SaveAsync(Constants.DisableFaviconKey,
- settingsShim.GetValueOrDefault("setting:disableWebsiteIcons", false));
- await storageService.SaveAsync(Constants.AddSitePromptShownKey,
- settingsShim.GetValueOrDefault("addedSiteAlert", false));
- await storageService.SaveAsync(Constants.PushInitialPromptShownKey,
- settingsShim.GetValueOrDefault("push:initialPromptShown", false));
- await storageService.SaveAsync(Constants.PushCurrentTokenKey,
- settingsShim.GetValueOrDefault("push:currentToken", null));
- await storageService.SaveAsync(Constants.PushRegisteredTokenKey,
- settingsShim.GetValueOrDefault("push:registeredToken", null));
- // For some reason "push:lastRegistrationDate" isn't getting pulled from settingsShim correctly.
- // We don't really need it anyways.
- // var lastReg = settingsShim.GetValueOrDefault("push:lastRegistrationDate", DateTime.MinValue);
- // await storageService.SaveAsync(Constants.PushLastRegistrationDateKey, lastReg);
- await storageService.SaveAsync("rememberedEmail",
- settingsShim.GetValueOrDefault("other:lastLoginEmail", null));
- await storageService.SaveAsync("appExtensionStarted",
- settingsShim.GetValueOrDefault("extension:started", false));
- await storageService.SaveAsync("appExtensionActivated",
- settingsShim.GetValueOrDefault("extension:activated", false));
-
- await environmentService.SetUrlsAsync(new Core.Models.Data.EnvironmentUrlData
- {
- Base = settingsShim.GetValueOrDefault("other:baseUrl", null),
- Api = settingsShim.GetValueOrDefault("other:apiUrl", null),
- WebVault = settingsShim.GetValueOrDefault("other:webVaultUrl", null),
- Identity = settingsShim.GetValueOrDefault("other:identityUrl", null),
- Icons = settingsShim.GetValueOrDefault("other:iconsUrl", null)
- });
-
- await passwordGenerationService.SaveOptionsAsync(new Core.Models.Domain.PasswordGenerationOptions
- {
- Ambiguous = settingsShim.GetValueOrDefault("pwGenerator:ambiguous", false),
- Length = settingsShim.GetValueOrDefault("pwGenerator:length", 15),
- Uppercase = settingsShim.GetValueOrDefault("pwGenerator:uppercase", true),
- Lowercase = settingsShim.GetValueOrDefault("pwGenerator:lowercase", true),
- Number = settingsShim.GetValueOrDefault("pwGenerator:numbers", true),
- MinNumber = settingsShim.GetValueOrDefault("pwGenerator:minNumbers", 0),
- Special = settingsShim.GetValueOrDefault("pwGenerator:special", true),
- MinSpecial = settingsShim.GetValueOrDefault("pwGenerator:minSpecial", 0),
- WordSeparator = "-",
- NumWords = 3
- });
-
- // Save lock options
-
- int? lockOptionsSeconds = settingsShim.GetValueOrDefault("setting:lockSeconds", -10);
- if(lockOptionsSeconds == -10)
- {
- lockOptionsSeconds = 60 * 15;
- }
- else if(lockOptionsSeconds == -1)
- {
- lockOptionsSeconds = null;
- }
- await storageService.SaveAsync(Constants.LockOptionKey,
- lockOptionsSeconds == null ? (int?)null : lockOptionsSeconds.Value / 60);
-
- // Save app ids
-
- await storageService.SaveAsync("appId", oldAppId);
- await storageService.SaveAsync("anonymousAppId", oldAnonAppId);
-
- // Save new authed data
-
- await tokenService.SetTwoFactorTokenAsync(oldTwoFactorToken, oldEmail);
- await tokenService.SetTokensAsync(oldToken, oldRefreshToken);
- await userService.SetInformationAsync(oldUserId, oldEmail, oldKdf, oldKdfIterations);
-
- // Save fingerprint
- if(oldFingerprint)
- {
- await storageService.SaveAsync(Constants.FingerprintUnlockKey, true);
- }
-
- var newKey = new Core.Models.Domain.SymmetricCryptoKey(oldKey.Key);
- await cryptoService.SetKeyAsync(newKey);
- // Key hash is unavailable in old version, store old key until we can move it to key hash
- await secureStorageService.SaveAsync("oldKey", newKey.KeyB64);
- await cryptoService.SetEncKeyAsync(oldEncKey);
- await cryptoService.SetEncPrivateKeyAsync(oldEncPrivateKey);
-
- // Save pin
- if(!oldFingerprint && !string.IsNullOrWhiteSpace(oldPin))
- {
- var pinKey = await cryptoService.MakePinKeyAysnc(oldPin, oldEmail, oldKdf, oldKdfIterations);
- var pinProtectedKey = await cryptoService.EncryptAsync(oldKeyBytes, pinKey);
- await storageService.SaveAsync(Constants.PinProtectedKey, pinProtectedKey.EncryptedString);
- }
-
- // Post migration tasks
- await cryptoService.ToggleKeyAsync();
- await storageService.SaveAsync(Constants.LastActiveKey, DateTime.UtcNow.AddYears(-1));
- await lockService.CheckLockAsync();
-
- // Remove "needs migration" flag
- settingsShim.Remove(Constants.OldUserIdKey);
- await storageService.SaveAsync(Constants.MigratedFromV1, true);
- Migrating = false;
- messagingService.Send("migrated");
- if(Xamarin.Essentials.Connectivity.NetworkAccess != Xamarin.Essentials.NetworkAccess.None)
- {
- var task = Task.Run(() => syncService.FullSyncAsync(true));
- }
- return true;
- }
- }
-}
diff --git a/src/App/Migration/Models/CipherString.cs b/src/App/Migration/Models/CipherString.cs
deleted file mode 100644
index e9c61d74b..000000000
--- a/src/App/Migration/Models/CipherString.cs
+++ /dev/null
@@ -1,117 +0,0 @@
-using System;
-using Bit.Core.Enums;
-
-namespace Bit.App.Migration.Models
-{
- public class CipherString
- {
- private string _decryptedValue;
-
- public CipherString(string encryptedString)
- {
- if(string.IsNullOrWhiteSpace(encryptedString))
- {
- throw new ArgumentException(nameof(encryptedString));
- }
-
- var headerPieces = encryptedString.Split('.');
- string[] encPieces;
-
- EncryptionType encType;
- if(headerPieces.Length == 2 && Enum.TryParse(headerPieces[0], out encType))
- {
- EncryptionType = encType;
- encPieces = headerPieces[1].Split('|');
- }
- else if(headerPieces.Length == 1)
- {
- encPieces = headerPieces[0].Split('|');
- EncryptionType = encPieces.Length == 3 ? EncryptionType.AesCbc128_HmacSha256_B64 :
- EncryptionType.AesCbc256_B64;
- }
- else
- {
- throw new ArgumentException("Malformed header.");
- }
-
- switch(EncryptionType)
- {
- case EncryptionType.AesCbc256_B64:
- if(encPieces.Length != 2)
- {
- throw new ArgumentException("Malformed encPieces.");
- }
- InitializationVector = encPieces[0];
- CipherText = encPieces[1];
- break;
- case EncryptionType.AesCbc128_HmacSha256_B64:
- case EncryptionType.AesCbc256_HmacSha256_B64:
- if(encPieces.Length != 3)
- {
- throw new ArgumentException("Malformed encPieces.");
- }
- InitializationVector = encPieces[0];
- CipherText = encPieces[1];
- Mac = encPieces[2];
- break;
- case EncryptionType.Rsa2048_OaepSha256_B64:
- case EncryptionType.Rsa2048_OaepSha1_B64:
- if(encPieces.Length != 1)
- {
- throw new ArgumentException("Malformed encPieces.");
- }
- CipherText = encPieces[0];
- break;
- case EncryptionType.Rsa2048_OaepSha1_HmacSha256_B64:
- case EncryptionType.Rsa2048_OaepSha256_HmacSha256_B64:
- if(encPieces.Length != 2)
- {
- throw new ArgumentException("Malformed encPieces.");
- }
- CipherText = encPieces[0];
- Mac = encPieces[1];
- break;
- default:
- throw new ArgumentException("Unknown encType.");
- }
-
- EncryptedString = encryptedString;
- }
-
- public CipherString(EncryptionType encryptionType, string initializationVector, string cipherText,
- string mac = null)
- {
- if(string.IsNullOrWhiteSpace(initializationVector))
- {
- throw new ArgumentNullException(nameof(initializationVector));
- }
-
- if(string.IsNullOrWhiteSpace(cipherText))
- {
- throw new ArgumentNullException(nameof(cipherText));
- }
-
- EncryptionType = encryptionType;
- EncryptedString = string.Format("{0}.{1}|{2}", (byte)EncryptionType, initializationVector, cipherText);
-
- if(!string.IsNullOrWhiteSpace(mac))
- {
- EncryptedString = string.Format("{0}|{1}", EncryptedString, mac);
- }
-
- CipherText = cipherText;
- InitializationVector = initializationVector;
- Mac = mac;
- }
-
- public EncryptionType EncryptionType { get; private set; }
- public string EncryptedString { get; private set; }
- public string InitializationVector { get; private set; }
- public string CipherText { get; private set; }
- public string Mac { get; private set; }
- public byte[] InitializationVectorBytes => string.IsNullOrWhiteSpace(InitializationVector) ?
- null : Convert.FromBase64String(InitializationVector);
- public byte[] CipherTextBytes => Convert.FromBase64String(CipherText);
- public byte[] MacBytes => Mac == null ? null : Convert.FromBase64String(Mac);
- }
-}
diff --git a/src/App/Migration/Models/SymmetricCryptoKey.cs b/src/App/Migration/Models/SymmetricCryptoKey.cs
deleted file mode 100644
index 2a0572dba..000000000
--- a/src/App/Migration/Models/SymmetricCryptoKey.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-using Bit.Core.Enums;
-using System;
-using System.Linq;
-
-namespace Bit.App.Migration.Models
-{
- public class SymmetricCryptoKey
- {
- public SymmetricCryptoKey(byte[] rawBytes, EncryptionType? encType = null)
- {
- if(rawBytes == null || rawBytes.Length == 0)
- {
- throw new Exception("Must provide keyBytes.");
- }
-
- if(encType == null)
- {
- if(rawBytes.Length == 32)
- {
- encType = EncryptionType.AesCbc256_B64;
- }
- else if(rawBytes.Length == 64)
- {
- encType = EncryptionType.AesCbc256_HmacSha256_B64;
- }
- else
- {
- throw new Exception("Unable to determine encType.");
- }
- }
-
- EncryptionType = encType.Value;
- Key = rawBytes;
-
- if(EncryptionType == EncryptionType.AesCbc256_B64 && Key.Length == 32)
- {
- EncKey = Key;
- MacKey = null;
- }
- else if(EncryptionType == EncryptionType.AesCbc128_HmacSha256_B64 && Key.Length == 32)
- {
- EncKey = Key.Take(16).ToArray();
- MacKey = Key.Skip(16).Take(16).ToArray();
- }
- else if(EncryptionType == EncryptionType.AesCbc256_HmacSha256_B64 && Key.Length == 64)
- {
- EncKey = Key.Take(32).ToArray();
- MacKey = Key.Skip(32).Take(32).ToArray();
- }
- else
- {
- throw new Exception("Unsupported encType/key length.");
- }
- }
-
- public byte[] Key { get; set; }
- public string B64Key => Convert.ToBase64String(Key);
- public byte[] EncKey { get; set; }
- public byte[] MacKey { get; set; }
- public EncryptionType EncryptionType { get; set; }
- }
-}
diff --git a/src/App/Migration/SettingsShim.cs b/src/App/Migration/SettingsShim.cs
deleted file mode 100644
index f72c6643e..000000000
--- a/src/App/Migration/SettingsShim.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-using System;
-
-namespace Bit.App.Migration
-{
- public class SettingsShim
- {
- private readonly string _sharedName;
-
- public SettingsShim(string sharedName = null)
- {
- _sharedName = sharedName;
- }
-
- public bool Contains(string key)
- {
- return _sharedName != null ? Xamarin.Essentials.Preferences.ContainsKey(key, _sharedName) :
- Xamarin.Essentials.Preferences.ContainsKey(key);
- }
-
- public string GetValueOrDefault(string key, string defaultValue)
- {
- return _sharedName != null ? Xamarin.Essentials.Preferences.Get(key, defaultValue, _sharedName) :
- Xamarin.Essentials.Preferences.Get(key, defaultValue);
- }
-
- public DateTime GetValueOrDefault(string key, DateTime defaultValue)
- {
- return _sharedName != null ? Xamarin.Essentials.Preferences.Get(key, defaultValue, _sharedName) :
- Xamarin.Essentials.Preferences.Get(key, defaultValue);
- }
-
- public bool GetValueOrDefault(string key, bool defaultValue)
- {
- return _sharedName != null ? Xamarin.Essentials.Preferences.Get(key, defaultValue, _sharedName) :
- Xamarin.Essentials.Preferences.Get(key, defaultValue);
- }
-
- public int GetValueOrDefault(string key, int defaultValue)
- {
- return _sharedName != null ? Xamarin.Essentials.Preferences.Get(key, defaultValue, _sharedName) :
- Xamarin.Essentials.Preferences.Get(key, defaultValue);
- }
-
- public long GetValueOrDefault(string key, long defaultValue)
- {
- return _sharedName != null ? Xamarin.Essentials.Preferences.Get(key, defaultValue, _sharedName) :
- Xamarin.Essentials.Preferences.Get(key, defaultValue);
- }
-
- public void AddOrUpdateValue(string key, string value)
- {
- if(_sharedName != null)
- {
- Xamarin.Essentials.Preferences.Set(key, value, _sharedName);
- }
- else
- {
- Xamarin.Essentials.Preferences.Set(key, value);
- }
- }
-
- public void AddOrUpdateValue(string key, DateTime value)
- {
- if(_sharedName != null)
- {
- Xamarin.Essentials.Preferences.Set(key, value, _sharedName);
- }
- else
- {
- Xamarin.Essentials.Preferences.Set(key, value);
- }
- }
-
- public void AddOrUpdateValue(string key, bool value)
- {
- if(_sharedName != null)
- {
- Xamarin.Essentials.Preferences.Set(key, value, _sharedName);
- }
- else
- {
- Xamarin.Essentials.Preferences.Set(key, value);
- }
- }
-
- public void AddOrUpdateValue(string key, long value)
- {
- if(_sharedName != null)
- {
- Xamarin.Essentials.Preferences.Set(key, value, _sharedName);
- }
- else
- {
- Xamarin.Essentials.Preferences.Set(key, value);
- }
- }
-
- public void AddOrUpdateValue(string key, int value)
- {
- if(_sharedName != null)
- {
- Xamarin.Essentials.Preferences.Set(key, value, _sharedName);
- }
- else
- {
- Xamarin.Essentials.Preferences.Set(key, value);
- }
- }
-
- public void Remove(string key)
- {
- if(_sharedName != null)
- {
- Xamarin.Essentials.Preferences.Remove(key, _sharedName);
- }
- else
- {
- Xamarin.Essentials.Preferences.Remove(key);
- }
- }
- }
-}
diff --git a/src/App/Utilities/AppHelpers.cs b/src/App/Utilities/AppHelpers.cs
index 6e4b3298d..a08f63d91 100644
--- a/src/App/Utilities/AppHelpers.cs
+++ b/src/App/Utilities/AppHelpers.cs
@@ -124,23 +124,20 @@ namespace Bit.App.Utilities
{
var currentBuild = deviceActionService.GetBuildNumber();
var lastBuild = await storageService.GetAsync(Constants.LastBuildKey);
- if(!Migration.MigrationHelpers.NeedsMigration())
+ if(lastBuild == null)
{
- if(lastBuild == null)
+ // Installed
+ var currentLock = await storageService.GetAsync(Constants.LockOptionKey);
+ if(currentLock == null)
{
- // Installed
- var currentLock = await storageService.GetAsync(Constants.LockOptionKey);
- if(currentLock == null)
- {
- await storageService.SaveAsync(Constants.LockOptionKey, 15);
- }
- }
- else if(lastBuild != currentBuild)
- {
- // Updated
- var tasks = Task.Run(() => syncService.FullSyncAsync(true));
+ await storageService.SaveAsync(Constants.LockOptionKey, 15);
}
}
+ else if(lastBuild != currentBuild)
+ {
+ // Updated
+ var tasks = Task.Run(() => syncService.FullSyncAsync(true));
+ }
if(lastBuild != currentBuild)
{
await storageService.SaveAsync(Constants.LastBuildKey, currentBuild);
diff --git a/src/iOS/AppDelegate.cs b/src/iOS/AppDelegate.cs
index 9c69b6bd8..3b2a7da88 100644
--- a/src/iOS/AppDelegate.cs
+++ b/src/iOS/AppDelegate.cs
@@ -45,11 +45,6 @@ namespace Bit.iOS
{
Forms.Init();
InitApp();
- if(App.Migration.MigrationHelpers.NeedsMigration())
- {
- var task = App.Migration.MigrationHelpers.PerformMigrationAsync();
- Task.Delay(5000).Wait();
- }
_deviceActionService = ServiceContainer.Resolve("deviceActionService");
_messagingService = ServiceContainer.Resolve("messagingService");
@@ -265,12 +260,6 @@ namespace Bit.iOS
// Migration services
ServiceContainer.Register("logService", new ConsoleLogService());
- ServiceContainer.Register("settingsShim", new App.Migration.SettingsShim(iOSCoreHelpers.AppGroupId));
- if(App.Migration.MigrationHelpers.NeedsMigration())
- {
- ServiceContainer.Register(
- "oldSecureStorageService", new Migration.KeyChainStorageService());
- }
// Note: This might cause a race condition. Investigate more.
Task.Run(() =>
diff --git a/src/iOS/Migration/KeyChainStorageService.cs b/src/iOS/Migration/KeyChainStorageService.cs
deleted file mode 100644
index bc230bc8f..000000000
--- a/src/iOS/Migration/KeyChainStorageService.cs
+++ /dev/null
@@ -1,92 +0,0 @@
-using System;
-using System.Runtime.CompilerServices;
-using Bit.App.Migration.Abstractions;
-using Foundation;
-using Security;
-
-namespace Bit.iOS.Migration
-{
- public class KeyChainStorageService : IOldSecureStorageService
- {
- public void Store(string key, byte[] dataBytes)
- {
- using(var data = NSData.FromArray(dataBytes))
- using(var newRecord = GetKeyRecord(key, data))
- {
- Delete(key);
- CheckError(SecKeyChain.Add(newRecord));
- }
- }
-
- public byte[] Retrieve(string key)
- {
- SecStatusCode resultCode;
-
- using(var existingRecord = GetKeyRecord(key))
- using(var record = SecKeyChain.QueryAsRecord(existingRecord, out resultCode))
- {
- if(resultCode == SecStatusCode.ItemNotFound)
- {
- return null;
- }
-
- CheckError(resultCode);
- return record.Generic.ToArray();
- }
- }
-
- public void Delete(string key)
- {
- using(var record = GetExistingRecord(key))
- {
- if(record != null)
- {
- CheckError(SecKeyChain.Remove(record));
- }
- }
- }
-
- public bool Contains(string key)
- {
- using(var existingRecord = GetExistingRecord(key))
- {
- return existingRecord != null;
- }
- }
-
- private static void CheckError(SecStatusCode resultCode, [CallerMemberName] string caller = null)
- {
- if(resultCode != SecStatusCode.Success)
- {
- throw new Exception(string.Format("Failed to execute {0}. Result code: {1}", caller, resultCode));
- }
- }
-
- private static SecRecord GetKeyRecord(string key, NSData data = null)
- {
- var record = new SecRecord(SecKind.GenericPassword)
- {
- Service = "com.8bit.bitwarden",
- Account = key,
- AccessGroup = "LTZ2PFU5D6.com.8bit.bitwarden"
- };
-
- if(data != null)
- {
- record.Generic = data;
- }
-
- return record;
- }
-
- private static SecRecord GetExistingRecord(string key)
- {
- var existingRecord = GetKeyRecord(key);
-
- SecStatusCode resultCode;
- SecKeyChain.QueryAsRecord(existingRecord, out resultCode);
-
- return resultCode == SecStatusCode.Success ? existingRecord : null;
- }
- }
-}
diff --git a/src/iOS/iOS.csproj b/src/iOS/iOS.csproj
index 099345c58..14fa4a318 100644
--- a/src/iOS/iOS.csproj
+++ b/src/iOS/iOS.csproj
@@ -134,7 +134,6 @@
-