summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2012-07-15 16:16:57 +0200
committerArne Schwabe <arne@rfc2549.org>2012-07-15 16:16:57 +0200
commit3ab9e38d4473a7a34b820d80cc442ba6c3e30564 (patch)
treea2390c60dd00cda81c86f18fd4f29103124dc17e
parent77583ce01023073fec1cbce468c05b6e44097aa0 (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.xml4
-rw-r--r--jni/Android.mk24
-rw-r--r--jni/jbcrypto.cpp67
-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.mk21
-rw-r--r--src/de/blinkt/openvpn/OpenVpnManagementThread.java66
-rw-r--r--src/de/blinkt/openvpn/VpnProfile.java3
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) {