summaryrefslogtreecommitdiff
path: root/src/de/blinkt/openvpn/VpnProfile.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/de/blinkt/openvpn/VpnProfile.java')
-rw-r--r--src/de/blinkt/openvpn/VpnProfile.java148
1 files changed, 122 insertions, 26 deletions
diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java
index 37e9b2ff..ea034b55 100644
--- a/src/de/blinkt/openvpn/VpnProfile.java
+++ b/src/de/blinkt/openvpn/VpnProfile.java
@@ -9,6 +9,11 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
@@ -19,6 +24,11 @@ import java.util.Locale;
import java.util.UUID;
import java.util.Vector;
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+
import org.spongycastle.util.io.pem.PemObject;
import org.spongycastle.util.io.pem.PemWriter;
@@ -30,6 +40,7 @@ import android.os.Build;
import android.preference.PreferenceManager;
import android.security.KeyChain;
import android.security.KeyChainException;
+import android.util.Base64;
public class VpnProfile implements Serializable{
// Parcable
@@ -112,9 +123,10 @@ public class VpnProfile implements Serializable{
static final String MINIVPN = "miniopenvpn";
-
-
-
+ static private native byte[] rsasign(byte[] input,int pkey) throws InvalidKeyException;
+ static {
+ System.loadLibrary("opvpnutil");
+ }
public void clearDefaults() {
mServerName="unkown";
@@ -140,11 +152,6 @@ public class VpnProfile implements Serializable{
return '"' + escapedString + '"';
}
-
- static final String OVPNCONFIGCA = "android-ca.pem";
- static final String OVPNCONFIGUSERCERT = "android-user.pem";
-
-
public VpnProfile(String name) {
mUuid = UUID.randomUUID();
mName = name;
@@ -160,7 +167,7 @@ public class VpnProfile implements Serializable{
}
- public String getConfigFile(Context context)
+ public String getConfigFile(Context context, boolean configForOvpn3)
{
File cacheDir= context.getCacheDir();
@@ -255,10 +262,13 @@ public class VpnProfile implements Serializable{
case VpnProfile.TYPE_USERPASS_KEYSTORE:
cfg+="auth-user-pass\n";
case VpnProfile.TYPE_KEYSTORE:
- cfg+="ca " + cacheDir.getAbsolutePath() + "/" + OVPNCONFIGCA + "\n";
- cfg+="cert " + cacheDir.getAbsolutePath() + "/" + OVPNCONFIGUSERCERT + "\n";
- cfg+="management-external-key\n";
-
+ if(!configForOvpn3) {
+ String[] ks =getKeyStoreCertificates(context);
+ cfg+="### From Keystore ####\n";
+ cfg+="<ca>\n" + ks[0] + "</ca>\n";
+ cfg+="<cert>\n" + ks[0] + "</cert>\n";
+ cfg+="management-external-key\n";
+ }
break;
case VpnProfile.TYPE_USERPASS:
cfg+="auth-user-pass\n";
@@ -498,7 +508,7 @@ public class VpnProfile implements Serializable{
Intent intent = new Intent(context,OpenVpnService.class);
if(mAuthenticationType == VpnProfile.TYPE_KEYSTORE || mAuthenticationType == VpnProfile.TYPE_USERPASS_KEYSTORE) {
- if(!saveCertificates(context))
+ if(getKeyStoreCertificates(context)==null)
return null;
}
@@ -510,7 +520,7 @@ public class VpnProfile implements Serializable{
try {
FileWriter cfg = new FileWriter(context.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE);
- cfg.write(getConfigFile(context));
+ cfg.write(getConfigFile(context,false));
cfg.flush();
cfg.close();
} catch (IOException e) {
@@ -520,7 +530,7 @@ public class VpnProfile implements Serializable{
return intent;
}
- private boolean saveCertificates(Context context) {
+ String[] getKeyStoreCertificates(Context context) {
PrivateKey privateKey = null;
X509Certificate[] cachain=null;
try {
@@ -553,27 +563,30 @@ public class VpnProfile implements Serializable{
}
- FileWriter fout = new FileWriter(context.getCacheDir().getAbsolutePath() + "/" + VpnProfile.OVPNCONFIGCA);
- PemWriter pw = new PemWriter(fout);
+
+ StringWriter caout = new StringWriter();
+
+ PemWriter pw = new PemWriter(caout);
for(X509Certificate cert:cachain) {
pw.writeObject(new PemObject("CERTIFICATE", cert.getEncoded()));
}
-
pw.close();
+
+ StringWriter certout = new StringWriter();
+
+
if(cachain.length>= 1){
X509Certificate usercert = cachain[0];
- FileWriter userout = new FileWriter(context.getCacheDir().getAbsolutePath() + "/" + VpnProfile.OVPNCONFIGUSERCERT);
-
- PemWriter upw = new PemWriter(userout);
+ PemWriter upw = new PemWriter(certout);
upw.writeObject(new PemObject("CERTIFICATE", usercert.getEncoded()));
upw.close();
}
-
- return true;
+
+ return new String[] {caout.toString(),certout.toString()};
} catch (InterruptedException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
@@ -590,7 +603,7 @@ public class VpnProfile implements Serializable{
}
}
}
- return false;
+ return null;
}
private Certificate getCacertFromFile() throws FileNotFoundException, CertificateException {
CertificateFactory certFact = CertificateFactory.getInstance("X.509");
@@ -651,7 +664,7 @@ public class VpnProfile implements Serializable{
return null;
}
}
- private boolean isUserPWAuth() {
+ boolean isUserPWAuth() {
switch(mAuthenticationType) {
case TYPE_USERPASS:
case TYPE_USERPASS_CERTIFICATES:
@@ -748,6 +761,89 @@ public class VpnProfile implements Serializable{
return mPrivateKey;
}
+ public String getSignedData(String b64data) {
+ PrivateKey privkey = getKeystoreKey();
+ Exception err =null;
+
+ byte[] data = Base64.decode(b64data, Base64.DEFAULT);
+
+ // The Jelly Bean *evil* Hack
+ // 4.2 implements the RSA/ECB/PKCS1PADDING in the OpenSSLprovider
+ if(Build.VERSION.SDK_INT==Build.VERSION_CODES.JELLY_BEAN){
+ return processSignJellyBeans(privkey,data);
+ }
+
+
+ try{
+
+
+ Cipher rsasinger = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
+
+ rsasinger.init(Cipher.ENCRYPT_MODE, privkey);
+
+ byte[] signed_bytes = rsasinger.doFinal(data);
+ return Base64.encodeToString(signed_bytes, Base64.NO_WRAP);
+
+ } catch (NoSuchAlgorithmException e){
+ err =e;
+ } catch (InvalidKeyException e) {
+ err =e;
+ } catch (NoSuchPaddingException e) {
+ err =e;
+ } catch (IllegalBlockSizeException e) {
+ err =e;
+ } catch (BadPaddingException e) {
+ err =e;
+ }
+ if(err !=null) {
+ OpenVPN.logError(R.string.error_rsa_sign,err.getClass().toString(),err.getLocalizedMessage());
+ }
+ return null;
+
+ }
+
+
+ private String processSignJellyBeans(PrivateKey privkey, byte[] data) {
+ Exception err =null;
+ try {
+ Method[] allm = privkey.getClass().getSuperclass().getDeclaredMethods();
+ System.out.println(allm);
+ Method getKey = privkey.getClass().getSuperclass().getDeclaredMethod("getOpenSSLKey");
+ getKey.setAccessible(true);
+
+ // Real object type is OpenSSLKey
+ Object opensslkey = getKey.invoke(privkey);
+
+ getKey.setAccessible(false);
+
+ Method getPkeyContext = opensslkey.getClass().getDeclaredMethod("getPkeyContext");
+
+ // integer pointer to EVP_pkey
+ getPkeyContext.setAccessible(true);
+ int pkey = (Integer) getPkeyContext.invoke(opensslkey);
+ getPkeyContext.setAccessible(false);
+
+ byte[] signed_bytes = rsasign(data, pkey);
+ return Base64.encodeToString(signed_bytes, Base64.NO_WRAP);
+
+ } catch (NoSuchMethodException e) {
+ err=e;
+ } catch (IllegalArgumentException e) {
+ err=e;
+ } catch (IllegalAccessException e) {
+ err=e;
+ } catch (InvocationTargetException e) {
+ err=e;
+ } catch (InvalidKeyException e) {
+ err=e;
+ }
+ if(err !=null) {
+ OpenVPN.logError(R.string.error_rsa_sign,err.getClass().toString(),err.getLocalizedMessage());
+ }
+ return null;
+
+ }
+
}