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) { | 
