From 86bf641b9558e9b9532efbb70391e41b37f620e9 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 22 May 2023 19:47:29 +0200 Subject: sanitize launcher intent --- .../java/se/leap/bitmaskclient/base/StartActivity.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'app/src/main/java/se/leap/bitmaskclient/base') diff --git a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java index 58b057b7..6426c3d6 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java @@ -103,10 +103,27 @@ public class StartActivity extends Activity{ // initialize app necessities VpnStatus.initLogCache(getApplicationContext().getCacheDir()); + sanitizeStartIntent(); prepareEIP(); } + private void sanitizeStartIntent() { + Intent intent = new Intent(); + try { + if (getIntent().hasExtra(EIP_RESTART_ON_BOOT)) { + intent.putExtra(EIP_RESTART_ON_BOOT, getIntent().getBooleanExtra(EIP_RESTART_ON_BOOT, false)); + } + if (getIntent().hasExtra(APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE)) { + intent.putExtra(APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE, false); + } + } catch (RuntimeException e) { + + } + this.setIntent(intent); + } + + /** * check if normal start, first run, up or downgrade * @return @StartupMode -- cgit v1.2.3 From 69164dc81246035deea243181f4134d7018f572f Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 24 May 2023 13:18:02 +0200 Subject: migrate to encrypted shared preferences --- .../se/leap/bitmaskclient/base/StartActivity.java | 8 +- .../leap/bitmaskclient/base/models/Constants.java | 1 + .../base/models/FeatureVersionCode.java | 2 + .../bitmaskclient/base/utils/PreferenceHelper.java | 85 ++++++++++++++++++---- 4 files changed, 82 insertions(+), 14 deletions(-) (limited to 'app/src/main/java/se/leap/bitmaskclient/base') diff --git a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java index 6426c3d6..b622f5ca 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java @@ -38,6 +38,7 @@ import android.util.Log; import androidx.annotation.IntDef; import androidx.annotation.Nullable; +import androidx.security.crypto.EncryptedSharedPreferences; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -81,7 +82,7 @@ public class StartActivity extends Activity{ @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + preferences = PreferenceHelper.getSharedPreferences(this); Log.d(TAG, "Started"); @@ -197,6 +198,11 @@ public class StartActivity extends Activity{ } } + if (hasNewFeature(FeatureVersionCode.ENCRYPTED_SHARED_PREFS)) { + PreferenceHelper.migrateToEncryptedPrefs(this); + preferences = PreferenceHelper.getSharedPreferences(this); + } + // always check if manual gateway selection feature switch has been disabled if (!BuildConfig.allow_manual_gateway_selection && PreferenceHelper.getPreferredCity(this) != null) { PreferenceHelper.setPreferredCity(this, null); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java index 57467974..70bf3943 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java @@ -27,6 +27,7 @@ public interface Constants { ///////////////////////////////////////////// String SHARED_PREFERENCES = "LEAPPreferences"; + String SHARED_ENCRYPTED_PREFERENCES = "LEAPEncryptedPreferences"; String PREFERENCES_APP_VERSION = "bitmask version"; String ALWAYS_ON_SHOW_DIALOG = "DIALOG.ALWAYS_ON_SHOW_DIALOG"; String CLEARLOG = "clearlogconnect"; diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java b/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java index f7251acb..c2eb9694 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java @@ -5,4 +5,6 @@ public interface FeatureVersionCode { int GEOIP_SERVICE = 148; int CALYX_PROVIDER_LILYPAD_UPDATE = 165000; int RISEUP_PROVIDER_LILYPAD_UPDATE = 165000; + + int ENCRYPTED_SHARED_PREFS = 170000; } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java index 9cba221a..eadd37bc 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java @@ -27,6 +27,7 @@ import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_UPD import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.base.models.Constants.RESTART_ON_UPDATE; +import static se.leap.bitmaskclient.base.models.Constants.SHARED_ENCRYPTED_PREFERENCES; import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.models.Constants.SHOW_EXPERIMENTAL; import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; @@ -37,16 +38,21 @@ import static se.leap.bitmaskclient.base.models.Constants.USE_SNOWFLAKE; import android.content.Context; import android.content.SharedPreferences; import android.text.TextUtils; +import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; +import androidx.security.crypto.EncryptedSharedPreferences; import org.json.JSONException; import org.json.JSONObject; +import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import java.security.GeneralSecurityException; import java.util.HashSet; +import java.util.Map; import java.util.Set; import de.blinkt.openvpn.VpnProfile; @@ -60,6 +66,23 @@ import se.leap.bitmaskclient.tor.TorStatusObservable; public class PreferenceHelper { + private static final String TAG = PreferenceHelper.class.getSimpleName(); + + public static SharedPreferences getSharedPreferences(Context context) { + try { + return EncryptedSharedPreferences.create( + SHARED_ENCRYPTED_PREFERENCES, + "leap_secret_shared_prefs", + context, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM + ); + } catch (GeneralSecurityException | IOException e) { + e.printStackTrace(); + } + return context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + } + public static Provider getSavedProviderFromSharedPreferences(@NonNull SharedPreferences preferences) { Provider provider = new Provider(); try { @@ -97,7 +120,7 @@ public class PreferenceHelper { } public static void persistProviderAsync(Context context, Provider provider) { - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); storeProviderInPreferences(preferences, provider, true); } @@ -151,7 +174,7 @@ public class PreferenceHelper { * Sets the profile that is connected (to connect if the service restarts) */ public static void setLastUsedVpnProfile(Context context, VpnProfile connectedProfile) { - SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences prefs = getSharedPreferences(context); SharedPreferences.Editor prefsedit = prefs.edit(); prefsedit.putString(LAST_USED_PROFILE, connectedProfile.toJson()); prefsedit.apply(); @@ -161,7 +184,7 @@ public class PreferenceHelper { * Returns the profile that was last connected (to connect if the service restarts) */ public static VpnProfile getLastConnectedVpnProfile(Context context) { - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); String lastConnectedProfileJson = preferences.getString(LAST_USED_PROFILE, null); return VpnProfile.fromJson(lastConnectedProfileJson); } @@ -204,6 +227,8 @@ public class PreferenceHelper { apply(); } + // used in fatweb flavor + @SuppressWarnings("unused") public static void setLastAppUpdateCheck(Context context) { putLong(context, LAST_UPDATE_CHECK, System.currentTimeMillis()); } @@ -419,7 +444,7 @@ public class PreferenceHelper { if (context == null) { return null; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); return preferences.getStringSet(EXCLUDED_APPS, new HashSet<>()); } @@ -427,7 +452,7 @@ public class PreferenceHelper { if (context == null) { return defValue; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); return preferences.getLong(key, defValue); } @@ -435,7 +460,7 @@ public class PreferenceHelper { if (context == null) { return; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); preferences.edit().putLong(key, value).apply(); } @@ -443,7 +468,7 @@ public class PreferenceHelper { if (context == null) { return defValue; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); return preferences.getString(key, defValue); } @@ -452,7 +477,7 @@ public class PreferenceHelper { if (context == null) { return; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); preferences.edit().putString(key, value).commit(); } @@ -460,7 +485,7 @@ public class PreferenceHelper { if (context == null) { return; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); preferences.edit().putString(key, value).apply(); } @@ -468,7 +493,7 @@ public class PreferenceHelper { if (context == null) { return; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); preferences.edit().putStringSet(key, value).apply(); } @@ -477,7 +502,7 @@ public class PreferenceHelper { return false; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); return preferences.getBoolean(key, defValue); } @@ -486,7 +511,7 @@ public class PreferenceHelper { return; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); preferences.edit().putBoolean(key, value).apply(); } @@ -495,7 +520,41 @@ public class PreferenceHelper { return false; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); return preferences.contains(key); } + + public static void migrateToEncryptedPrefs(Context context) { + SharedPreferences encryptedPrefs = getSharedPreferences(context); + if (!(encryptedPrefs instanceof EncryptedSharedPreferences)) { + Log.e(TAG, "Failed to migrate shared preferences"); + return; + } + SharedPreferences.Editor encryptedEditor = encryptedPrefs.edit(); + SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + Map keys = preferences.getAll(); + + for(Map.Entry entry : keys.entrySet()){ + try { + Object value = entry.getValue(); + if (value instanceof String) { + encryptedEditor.putString(entry.getKey(), (String) value); + } else if (value instanceof Boolean) { + encryptedEditor.putBoolean(entry.getKey(), (Boolean) value); + } else if (value instanceof Integer) { + encryptedEditor.putInt(entry.getKey(), (Integer) value); + } else if (value instanceof Set) { + encryptedEditor.putStringSet(entry.getKey(), (Set) value); + } else if (value instanceof Long) { + encryptedEditor.putLong(entry.getKey(), (Long) value); + } else if (value instanceof Float) { + encryptedEditor.putFloat(entry.getKey(), (Float) value); + } + } catch (ClassCastException e) { + e.printStackTrace(); + } + } + encryptedEditor.commit(); + preferences.edit().clear().apply(); + } } -- cgit v1.2.3 From af123f7a34eaa7839a238b32f2cb4ef473c9ed22 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 24 May 2023 21:47:16 +0200 Subject: use updated encrypted shared preferences API --- .../se/leap/bitmaskclient/base/utils/PreferenceHelper.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'app/src/main/java/se/leap/bitmaskclient/base') diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java index eadd37bc..12196aee 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java @@ -43,6 +43,7 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; import androidx.security.crypto.EncryptedSharedPreferences; +import androidx.security.crypto.MasterKey; import org.json.JSONException; import org.json.JSONObject; @@ -70,13 +71,16 @@ public class PreferenceHelper { public static SharedPreferences getSharedPreferences(Context context) { try { + MasterKey masterKey = new MasterKey.Builder(context) + .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) + .build(); + return EncryptedSharedPreferences.create( - SHARED_ENCRYPTED_PREFERENCES, - "leap_secret_shared_prefs", context, + SHARED_ENCRYPTED_PREFERENCES, + masterKey, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, - EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM - ); + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM); } catch (GeneralSecurityException | IOException e) { e.printStackTrace(); } -- cgit v1.2.3 From 7e55cd7e6c93c0a6613cbf09036b0c6e559b5e8a Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 17 Jul 2023 13:32:31 +0200 Subject: always switch to encrypted shared preferences --- .../se/leap/bitmaskclient/base/BitmaskApp.java | 5 ++--- .../se/leap/bitmaskclient/base/MainActivity.java | 3 +-- .../se/leap/bitmaskclient/base/OnBootReceiver.java | 14 ++++++------- .../se/leap/bitmaskclient/base/StartActivity.java | 2 -- .../bitmaskclient/base/fragments/EipFragment.java | 3 +-- .../base/fragments/GatewaySelectionFragment.java | 24 ++++++++++------------ .../base/fragments/NavigationDrawerFragment.java | 4 ++-- .../base/fragments/SettingsFragment.java | 4 +--- 8 files changed, 25 insertions(+), 34 deletions(-) (limited to 'app/src/main/java/se/leap/bitmaskclient/base') diff --git a/app/src/main/java/se/leap/bitmaskclient/base/BitmaskApp.java b/app/src/main/java/se/leap/bitmaskclient/base/BitmaskApp.java index 0ccef0ae..74b789a9 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/BitmaskApp.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/BitmaskApp.java @@ -22,11 +22,9 @@ import static se.leap.bitmaskclient.appUpdate.DownloadBroadcastReceiver.ACTION_D import static se.leap.bitmaskclient.appUpdate.DownloadServiceCommand.CHECK_VERSION_FILE; import static se.leap.bitmaskclient.appUpdate.DownloadServiceCommand.DOWNLOAD_UPDATE; import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_DOWNLOAD_SERVICE_EVENT; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.utils.ConfigHelper.isCalyxOSWithTetheringSupport; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getSavedProviderFromSharedPreferences; -import android.content.Context; import android.content.IntentFilter; import android.content.SharedPreferences; @@ -42,6 +40,7 @@ import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.appUpdate.DownloadBroadcastReceiver; import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.PRNGFixes; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.eip.EipSetupObserver; import se.leap.bitmaskclient.tethering.TetheringStateManager; import se.leap.bitmaskclient.tor.TorStatusObservable; @@ -64,7 +63,7 @@ public class BitmaskApp extends MultiDexApplication { // Normal app init code...*/ PRNGFixes.apply(); Security.insertProviderAt(Conscrypt.newProvider(), 1); - SharedPreferences preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = PreferenceHelper.getSharedPreferences(this); providerObservable = ProviderObservable.getInstance(); providerObservable.updateProvider(getSavedProviderFromSharedPreferences(preferences)); torStatusObservable = TorStatusObservable.getInstance(); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java index 9225755e..248d96c7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java @@ -33,7 +33,6 @@ import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_CONFIGURE_LEAP; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_LOG_IN; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_SWITCH_PROVIDER; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.storeProviderInPreferences; import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_INVALID_VPN_CERTIFICATE; import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_VPN_PREPARE; @@ -113,7 +112,7 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener, navigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager().findFragmentById(R.id.navigation_drawer); - preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + preferences = PreferenceHelper.getSharedPreferences(this); provider = ProviderObservable.getInstance().getCurrentProvider(); EipSetupObserver.addListener(this); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/OnBootReceiver.java b/app/src/main/java/se/leap/bitmaskclient/base/OnBootReceiver.java index 3b534a7d..a508329c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/OnBootReceiver.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/OnBootReceiver.java @@ -1,5 +1,10 @@ package se.leap.bitmaskclient.base; +import static android.content.Intent.ACTION_BOOT_COMPLETED; +import static se.leap.bitmaskclient.base.models.Constants.APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE; +import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; + import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -8,12 +13,7 @@ import android.os.Build; import android.util.Log; import de.blinkt.openvpn.core.VpnStatus; - -import static android.content.Intent.ACTION_BOOT_COMPLETED; -import static se.leap.bitmaskclient.base.models.Constants.APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE; -import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT; -import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; public class OnBootReceiver extends BroadcastReceiver { @@ -26,7 +26,7 @@ public class OnBootReceiver extends BroadcastReceiver { if (intent == null || !ACTION_BOOT_COMPLETED.equals(intent.getAction())) { return; } - preferences = context.getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE); + preferences = PreferenceHelper.getSharedPreferences(context); boolean providerConfigured = !preferences.getString(PROVIDER_VPN_CERTIFICATE, "").isEmpty(); boolean startOnBoot = preferences.getBoolean(EIP_RESTART_ON_BOOT, false) && Build.VERSION.SDK_INT < Build.VERSION_CODES.O; boolean isAlwaysOnConfigured = VpnStatus.isAlwaysOn(); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java index b622f5ca..94000a0f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java @@ -25,7 +25,6 @@ import static se.leap.bitmaskclient.base.models.Constants.PREFERENCES_APP_VERSIO import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_EIP_DEFINITION; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_CONFIGURE_LEAP; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.storeProviderInPreferences; @@ -38,7 +37,6 @@ import android.util.Log; import androidx.annotation.IntDef; import androidx.annotation.Nullable; -import androidx.security.crypto.EncryptedSharedPreferences; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java index a2fb2683..a8d11869 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java @@ -25,7 +25,6 @@ import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_CONFIGURE_LEAP; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_LOG_IN; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_SWITCH_PROVIDER; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferredCity; import static se.leap.bitmaskclient.eip.EipSetupObserver.reconnectingWithDifferentGateway; @@ -159,7 +158,7 @@ public class EipFragment extends Fragment implements Observer { torStatusObservable = TorStatusObservable.getInstance(); Activity activity = getActivity(); if (activity != null) { - preferences = getActivity().getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE); + preferences = PreferenceHelper.getSharedPreferences(activity); } else { Log.e(TAG, "activity is null in onCreate - no preferences set!"); } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java index 749ffd9f..793c6407 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java @@ -16,6 +16,16 @@ */ package se.leap.bitmaskclient.base.fragments; +import static android.view.View.GONE; +import static android.view.View.VISIBLE; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.PT; +import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; +import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseBridges; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useBridges; +import static se.leap.bitmaskclient.base.utils.ViewHelper.setActionBarSubtitle; + import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -49,18 +59,6 @@ import se.leap.bitmaskclient.eip.EipCommand; import se.leap.bitmaskclient.eip.EipStatus; import se.leap.bitmaskclient.eip.GatewaysManager; -import static android.content.Context.MODE_PRIVATE; -import static android.view.View.GONE; -import static android.view.View.VISIBLE; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.PT; -import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; -import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseBridges; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useBridges; -import static se.leap.bitmaskclient.base.utils.ViewHelper.setActionBarSubtitle; - interface LocationListSelectionListener { void onLocationManuallySelected(Location location); } @@ -89,7 +87,7 @@ public class GatewaySelectionFragment extends Fragment implements Observer, Loca super.onCreate(savedInstanceState); gatewaysManager = new GatewaysManager(getContext()); eipStatus = EipStatus.getInstance(); - preferences = getContext().getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + preferences = PreferenceHelper.getSharedPreferences(getContext()); } @Override diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java index aa894cca..f51fd342 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java @@ -25,7 +25,6 @@ import static se.leap.bitmaskclient.base.models.Constants.ENABLE_DONATION; import static se.leap.bitmaskclient.base.models.Constants.PREFERRED_CITY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_SWITCH_PROVIDER; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferredCity; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getSaveBattery; @@ -63,6 +62,7 @@ import se.leap.bitmaskclient.base.FragmentManagerEnhanced; import se.leap.bitmaskclient.base.MainActivity; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.models.ProviderObservable; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.base.views.IconSwitchEntry; import se.leap.bitmaskclient.base.views.IconTextEntry; import se.leap.bitmaskclient.eip.EipStatus; @@ -110,7 +110,7 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen super.onCreate(savedInstanceState); // Reads in the flag indicating whether or not the user has demonstrated awareness of the // drawer. See PREF_USER_LEARNED_DRAWER for details. - preferences = getContext().getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + preferences = PreferenceHelper.getSharedPreferences(getContext()); preferences.registerOnSharedPreferenceChangeListener(this); } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java index 40bc256c..f36b17ad 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java @@ -1,12 +1,10 @@ package se.leap.bitmaskclient.base.fragments; -import static android.content.Context.MODE_PRIVATE; import static android.view.View.GONE; import static android.view.View.VISIBLE; import static se.leap.bitmaskclient.R.string.advanced_settings; import static se.leap.bitmaskclient.base.models.Constants.GATEWAY_PINNING; import static se.leap.bitmaskclient.base.models.Constants.PREFER_UDP; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; import static se.leap.bitmaskclient.base.models.Constants.USE_IPv6_FIREWALL; import static se.leap.bitmaskclient.base.models.Constants.USE_OBFUSCATION_PINNING; @@ -71,7 +69,7 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - preferences = getContext().getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + preferences = PreferenceHelper.getSharedPreferences(getContext()); preferences.registerOnSharedPreferenceChangeListener(this); firewallManager = new FirewallManager(getContext().getApplicationContext(), false); } -- cgit v1.2.3 From 49742738417fb3db7e60813ca170dffaab65c8c1 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 19 Jul 2023 12:51:59 +0200 Subject: always provide private VPN key over management interface, avoid exposing it in persisted openvpn config. The private key is stored encrypted instead --- .../leap/bitmaskclient/base/models/Provider.java | 11 +++++ .../bitmaskclient/base/utils/ConfigHelper.java | 56 +++++++++++----------- 2 files changed, 40 insertions(+), 27 deletions(-) (limited to 'app/src/main/java/se/leap/bitmaskclient/base') diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java index 08e13cf6..14c78cc3 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java @@ -29,6 +29,7 @@ import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_ALLOW_ANONYMO import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT; import static se.leap.bitmaskclient.base.models.Constants.TYPE; import static se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn; +import static se.leap.bitmaskclient.base.utils.ConfigHelper.RSAHelper.parseRsaKeyFromString; import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS; import android.os.Parcel; @@ -44,6 +45,7 @@ import org.json.JSONObject; import java.net.MalformedURLException; import java.net.URL; +import java.security.interfaces.RSAPrivateKey; import java.util.ArrayList; import java.util.HashSet; import java.util.Locale; @@ -79,6 +81,8 @@ public final class Provider implements Parcelable { private String caCert = ""; private String apiVersion = ""; private String privateKey = ""; + + private transient RSAPrivateKey rsaPrivateKey = null; private String vpnCertificate = ""; private long lastEipServiceUpdate = 0L; private long lastGeoIpUpdate = 0L; @@ -701,6 +705,13 @@ public final class Provider implements Parcelable { return privateKey; } + public RSAPrivateKey getRSAPrivateKey() { + if (rsaPrivateKey == null) { + rsaPrivateKey = parseRsaKeyFromString(privateKey); + } + return rsaPrivateKey; + } + public void setPrivateKey(String privateKey) { this.privateKey = privateKey; } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java index 2412efdd..9289738a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java @@ -131,35 +131,37 @@ public class ConfigHelper { return null; } - public static RSAPrivateKey parseRsaKeyFromString(String rsaKeyString) { - RSAPrivateKey key; - try { - KeyFactory kf; - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { - kf = KeyFactory.getInstance("RSA", "BC"); - } else { - kf = KeyFactory.getInstance("RSA"); + public static class RSAHelper { + public static RSAPrivateKey parseRsaKeyFromString(String rsaKeyString) { + RSAPrivateKey key; + try { + KeyFactory kf; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { + kf = KeyFactory.getInstance("RSA", "BC"); + } else { + kf = KeyFactory.getInstance("RSA"); + } + rsaKeyString = rsaKeyString.replaceFirst("-----BEGIN RSA PRIVATE KEY-----", "").replaceFirst("-----END RSA PRIVATE KEY-----", ""); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(rsaKeyString)); + key = (RSAPrivateKey) kf.generatePrivate(keySpec); + } catch (InvalidKeySpecException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } catch (NullPointerException e) { + e.printStackTrace(); + return null; + } catch (NoSuchProviderException e) { + e.printStackTrace(); + return null; } - rsaKeyString = rsaKeyString.replaceFirst("-----BEGIN RSA PRIVATE KEY-----", "").replaceFirst("-----END RSA PRIVATE KEY-----", ""); - PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(rsaKeyString)); - key = (RSAPrivateKey) kf.generatePrivate(keySpec); - } catch (InvalidKeySpecException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; - } catch (NoSuchAlgorithmException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; - } catch (NullPointerException e) { - e.printStackTrace(); - return null; - } catch (NoSuchProviderException e) { - e.printStackTrace(); - return null; - } - return key; + return key; + } } private static String byteArrayToHex(byte[] input) { -- cgit v1.2.3