diff options
author | Arne Schwabe <arne@rfc2549.org> | 2012-07-15 16:16:57 +0200 |
---|---|---|
committer | Arne Schwabe <arne@rfc2549.org> | 2012-07-15 16:16:57 +0200 |
commit | 3ab9e38d4473a7a34b820d80cc442ba6c3e30564 (patch) | |
tree | a2390c60dd00cda81c86f18fd4f29103124dc17e | |
parent | 77583ce01023073fec1cbce468c05b6e44097aa0 (diff) |
Add support for Certificates from Keystore under Jelly Beans (Thanks Kenny Root for the right pointers)
Move jniglue/minivpn files to more sensitive places
--HG--
rename : openvpn/src/openvpn/jniglue.c => jni/jniglue.c
rename : openvpn/src/openvpn/jniglue.h => jni/jniglue.h
rename : openvpn/src/openvpn/testmain.c => jni/minivpn.c
-rw-r--r-- | AndroidManifest.xml | 4 | ||||
-rw-r--r-- | jni/Android.mk | 24 | ||||
-rw-r--r-- | jni/jbcrypto.cpp | 67 | ||||
-rw-r--r-- | jni/jniglue.c (renamed from openvpn/src/openvpn/jniglue.c) | 3 | ||||
-rw-r--r-- | jni/jniglue.h (renamed from openvpn/src/openvpn/jniglue.h) | 0 | ||||
-rw-r--r-- | jni/minivpn.c (renamed from openvpn/src/openvpn/testmain.c) | 0 | ||||
-rw-r--r-- | openvpn/Android.mk | 21 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVpnManagementThread.java | 66 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/VpnProfile.java | 3 |
9 files changed, 154 insertions, 34 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index b21461fb..effc6475 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -17,8 +17,8 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.blinkt.openvpn" - android:versionCode="36" - android:versionName="0.5.11" > + android:versionCode="37" + android:versionName="0.5.12" > <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> diff --git a/jni/Android.mk b/jni/Android.mk index ff17b27b..761fa005 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -1,9 +1,31 @@ # Path of the sources -CURRENT_DIR := $(call my-dir) +JNI_DIR := $(call my-dir) include lzo/Android.mk include openssl/Android.mk include openvpn/Android.mk + + +LOCAL_PATH := $(JNI_DIR) + +# The only real JNI library +include $(CLEAR_VARS) +LOCAL_LDLIBS := -llog +LOCAL_C_INCLUDES := openssl/include openssl/crypto openssl +LOCAL_SRC_FILES:= jniglue.c jbcrypto.cpp +LOCAL_MODULE = opvpnutil +LOCAL_STATIC_LIBRARIES := libcrypto_static +include $(BUILD_SHARED_LIBRARY) + + + +include $(CLEAR_VARS) +LOCAL_LDLIBS := -llog +LOCAL_SRC_FILES:= minivpn.c +LOCAL_MODULE = minivp +LOCAL_SHARED_LIBRARIES=openvpn +include $(BUILD_EXECUTABLE) + diff --git a/jni/jbcrypto.cpp b/jni/jbcrypto.cpp new file mode 100644 index 00000000..0c56b974 --- /dev/null +++ b/jni/jbcrypto.cpp @@ -0,0 +1,67 @@ +// +// JBCyrpto.cpp +// xcopenvpn +// +// Created by Arne Schwabe on 12.07.12. +// Copyright (c) 2012 Universität Paderborn. All rights reserved. +// + +#include <jni.h> + +#include <openssl/ssl.h> +#include <openssl/rsa.h> +#include <openssl/objects.h> +#include <openssl/md5.h> + +extern "C" { +jbyteArray Java_de_blinkt_openvpn_OpenVpnManagementThread_rsasign(JNIEnv* env, jclass, jbyteArray from, jint pkeyRef); +} + + +jbyteArray Java_de_blinkt_openvpn_OpenVpnManagementThread_rsasign(JNIEnv* env, jclass, jbyteArray from, jint pkeyRef) { + + // EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef); + EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); + + + if (pkey == NULL || from == NULL) { + jniThrowException(env, "java/lang/NullPointerException", "EVP_KEY is null"); + return NULL; + } + + jbyte* data = env-> GetByteArrayElements (from, NULL); + int datalen = env-> GetArrayLength(from); + + if(data==NULL || datalen == ) + + unsigned int siglen; + unsigned char* sigret = (unsigned char*)malloc(RSA_size(pkey->pkey.rsa)); + + + //int RSA_sign(int type, const unsigned char *m, unsigned int m_len, + // unsigned char *sigret, unsigned int *siglen, RSA *rsa); + + // adapted from s3_clnt.c + if (RSA_sign(NID_md5_sha1, (unsigned char*) data, datalen, + sigret, &siglen, pkey->pkey.rsa) <= 0 ) + { + + ERR_print_errors(errbio); + jniThrowException(env, "java/security/InvalidKeyException", "rsa_sign went wrong, see logcat"); + + ERR_print_errors_fp(stderr); + return NULL; + + + } + + + jbyteArray jb; + + jb =env->NewByteArray(siglen); + + env->SetByteArrayRegion(jb, 0, siglen, (jbyte *) sigret); + free(sigret); + return jb; + +} diff --git a/openvpn/src/openvpn/jniglue.c b/jni/jniglue.c index a385d130..82b54d16 100644 --- a/openvpn/src/openvpn/jniglue.c +++ b/jni/jniglue.c @@ -16,6 +16,7 @@ void android_openvpn_log(int level,const char* prefix,const char* prefix_sep,con __android_log_print(ANDROID_LOG_DEBUG,"openvpn","%s%s%s",prefix,prefix_sep,m1); } -void Java_de_blinkt_openvpn_OpenVpnManagementThread_jniclose(JNIEnv *env,jobject jo, jint fd) { +void Java_de_blinkt_openvpn_OpenVpnManagementThread_jniclose(JNIEnv *env,jclass jo, jint fd) { int ret = close(fd); } + diff --git a/openvpn/src/openvpn/jniglue.h b/jni/jniglue.h index a86d52da..a86d52da 100644 --- a/openvpn/src/openvpn/jniglue.h +++ b/jni/jniglue.h diff --git a/openvpn/src/openvpn/testmain.c b/jni/minivpn.c index e69de29b..e69de29b 100644 --- a/openvpn/src/openvpn/testmain.c +++ b/jni/minivpn.c diff --git a/openvpn/Android.mk b/openvpn/Android.mk index ca15c711..2008adb1 100644 --- a/openvpn/Android.mk +++ b/openvpn/Android.mk @@ -6,8 +6,6 @@ include $(CLEAR_VARS) LOCAL_LDLIBS := -lz -llog LOCAL_C_INCLUDES := openssl/include lzo/include openssl/crypto openssl openvpn/src/compat openvpn/src/openvpn openvpn/include - - #LOCAL_SHARED_LIBRARIES := libssl libcrypto liblzo LOCAL_STATIC_LIBRARIES := libssl_static libcrypto_static liblzo-static @@ -15,7 +13,7 @@ LOCAL_STATIC_LIBRARIES := libssl_static libcrypto_static liblzo-static LOCAL_CFLAGS= -DHAVE_CONFIG_H LOCAL_MODULE = openvpn -LOCAL_SRC_FILES:= src/openvpn/jniglue.c \ +LOCAL_SRC_FILES:= \ src/compat/compat-basename.c \ src/compat/compat-daemon.c \ src/compat/compat-dirname.c \ @@ -92,21 +90,4 @@ include $(BUILD_SHARED_LIBRARY) #include $(BUILD_EXECUTABLE) -include $(CLEAR_VARS) - -LOCAL_LDLIBS := -llog -LOCAL_SRC_FILES:= src/openvpn/jniglue.c -LOCAL_MODULE = opvpnutil -include $(BUILD_SHARED_LIBRARY) - - -include $(CLEAR_VARS) - - -LOCAL_LDLIBS := -llog -LOCAL_SRC_FILES:= src/openvpn/testmain.c -LOCAL_MODULE = minivpn -LOCAL_SHARED_LIBRARIES=openvpn -include $(BUILD_EXECUTABLE) - diff --git a/src/de/blinkt/openvpn/OpenVpnManagementThread.java b/src/de/blinkt/openvpn/OpenVpnManagementThread.java index 69129eb1..4b0cf5ac 100644 --- a/src/de/blinkt/openvpn/OpenVpnManagementThread.java +++ b/src/de/blinkt/openvpn/OpenVpnManagementThread.java @@ -17,6 +17,7 @@ import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException;
import android.net.LocalSocket;
+import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.util.Base64;
import android.util.Log;
@@ -34,6 +35,9 @@ public class OpenVpnManagementThread implements Runnable { private String mCurrentstate;
private static Vector<OpenVpnManagementThread> active=new Vector<OpenVpnManagementThread>();
+
+ static private native void jniclose(int fdint);
+ static private native byte[] rsasign(byte[] input,int pkey) throws InvalidKeyException;
public OpenVpnManagementThread(VpnProfile profile, LocalSocket mgmtsocket, OpenVpnService openVpnService) {
mProfile = profile;
@@ -333,12 +337,7 @@ public class OpenVpnManagementThread implements Runnable { }
return false;
}
-
-
- private native void jniclose(int fdint);
-
-
-
+
private void processPWCommand(String argument) {
//argument has the form Need 'Private Key' password
@@ -401,11 +400,21 @@ public class OpenVpnManagementThread implements Runnable { }
private void processSignCommand(String b64data) {
+
PrivateKey privkey = mProfile.getKeystoreKey();
Exception err =null;
+ // The Jelly Bean *evil* Hack
+
+ byte[] data = Base64.decode(b64data, Base64.DEFAULT);
+
+ if(Build.VERSION.SDK_INT==16){
+ processSignJellyBeans(privkey,data);
+ return;
+ }
+
try{
- byte[] data = Base64.decode(b64data, Base64.DEFAULT);
+
Cipher rsasinger = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
@@ -433,4 +442,47 @@ public class OpenVpnManagementThread implements Runnable { }
+
+ private void 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);
+ String signed_string = Base64.encodeToString(signed_bytes, Base64.NO_WRAP);
+ managmentCommand("rsa-sig\n");
+ managmentCommand(signed_string);
+ managmentCommand("\nEND\n");
+
+ } 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());
+ }
+
+ }
}
diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java index b495cc9e..64ca3db6 100644 --- a/src/de/blinkt/openvpn/VpnProfile.java +++ b/src/de/blinkt/openvpn/VpnProfile.java @@ -24,7 +24,6 @@ import org.spongycastle.util.io.pem.PemWriter; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; -import android.os.Build; import android.security.KeyChain; import android.security.KeyChainException; @@ -555,8 +554,6 @@ public class VpnProfile implements Serializable{ if(mAuthenticationType==TYPE_KEYSTORE || mAuthenticationType==TYPE_USERPASS_KEYSTORE) { if(mAlias==null) return R.string.no_keystore_cert_selected; - if(Build.VERSION.SDK_INT >= 16 && !Build.MODEL.equals("sdk") ) - return R.string.keychain_jellybeans; } if(!mUsePull) { |