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 +++++++++++----------- .../se/leap/bitmaskclient/eip/GatewaysManager.java | 5 +- .../leap/bitmaskclient/eip/VpnConfigGenerator.java | 9 +--- .../providersetup/ProviderApiManagerBase.java | 3 +- 5 files changed, 43 insertions(+), 41 deletions(-) (limited to 'app/src/main/java/se') 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) { diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java index d114665b..5e05b7c1 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -22,7 +22,6 @@ 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.models.Constants.GATEWAYS; import static se.leap.bitmaskclient.base.models.Constants.HOST; -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.SORTED_GATEWAYS; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningCert; @@ -124,6 +123,7 @@ public class GatewaysManager { GatewaySelector gatewaySelector; + public GatewaysManager(Context context) { this.context = context; configureFromCurrentProvider(); @@ -392,7 +392,6 @@ public class GatewaysManager { try { JSONObject eipDefinition = provider.getEipServiceJson(); JSONObject secrets = secretsConfigurationFromCurrentProvider(); - JSONArray gatewaysDefined = new JSONArray(); try { gatewaysDefined = eipDefinition.getJSONArray(GATEWAYS); @@ -488,10 +487,8 @@ public class GatewaysManager { private JSONObject secretsConfigurationFromCurrentProvider() { JSONObject result = new JSONObject(); Provider provider = ProviderObservable.getInstance().getCurrentProvider(); - try { result.put(Provider.CA_CERT, provider.getCaCert()); - result.put(PROVIDER_PRIVATE_KEY, provider.getPrivateKey()); result.put(PROVIDER_VPN_CERTIFICATE, provider.getVpnCertificate()); } catch (JSONException e) { e.printStackTrace(); diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java index 2c22d4f7..fa2ab352 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -490,13 +490,6 @@ public class VpnConfigGenerator { + newLine + ""; - String key = - "" - + newLine - + secrets.getString(PROVIDER_PRIVATE_KEY) - + newLine - + ""; - String openvpnCert = "" + newLine @@ -504,7 +497,7 @@ public class VpnConfigGenerator { + newLine + ""; - return ca + newLine + key + newLine + openvpnCert; + return ca + newLine + openvpnCert; } catch (JSONException e) { e.printStackTrace(); return ""; diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java index 14308875..fdaef28b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java @@ -43,13 +43,12 @@ 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.Provider.CA_CERT; import static se.leap.bitmaskclient.base.models.Provider.GEOIP_URL; -import static se.leap.bitmaskclient.base.models.Provider.MOTD_URL; import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_API_IP; import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_IP; +import static se.leap.bitmaskclient.base.utils.ConfigHelper.RSAHelper.parseRsaKeyFromString; import static se.leap.bitmaskclient.base.utils.ConfigHelper.getDomainFromMainURL; import static se.leap.bitmaskclient.base.utils.ConfigHelper.getFingerprintFromCertificate; import static se.leap.bitmaskclient.base.utils.ConfigHelper.getProviderFormattedString; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.parseRsaKeyFromString; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.deleteProviderDetailsFromPreferences; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getFromPersistedProvider; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getLongFromPersistedProvider; -- cgit v1.2.3