android: Added a method to get the user's private key via JNI
authorTobias Brunner <tobias@strongswan.org>
Sun, 23 Sep 2012 07:00:34 +0000 (09:00 +0200)
committerTobias Brunner <tobias@strongswan.org>
Mon, 24 Sep 2012 15:12:18 +0000 (17:12 +0200)
src/frontends/android/jni/libandroidbridge/charonservice.c
src/frontends/android/jni/libandroidbridge/charonservice.h
src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java

index 59ec62f..ef4d42e 100644 (file)
@@ -25,6 +25,7 @@
 #include "android_jni.h"
 #include "backend/android_attr.h"
 #include "backend/android_creds.h"
 #include "android_jni.h"
 #include "backend/android_attr.h"
 #include "backend/android_creds.h"
+#include "backend/android_private_key.h"
 #include "backend/android_service.h"
 #include "kernel/android_ipsec.h"
 #include "kernel/android_net.h"
 #include "backend/android_service.h"
 #include "kernel/android_ipsec.h"
 #include "kernel/android_net.h"
@@ -275,7 +276,7 @@ METHOD(charonservice_t, get_user_certificate, linked_list_t*,
        {
                goto failed;
        }
        {
                goto failed;
        }
-       jencodings = (*env)->CallObjectMethod(env, this->vpn_service, method_id, NULL);
+       jencodings = (*env)->CallObjectMethod(env, this->vpn_service, method_id);
        if (!jencodings)
        {
                goto failed;
        if (!jencodings)
        {
                goto failed;
@@ -290,6 +291,39 @@ failed:
        return NULL;
 }
 
        return NULL;
 }
 
+METHOD(charonservice_t, get_user_key, private_key_t*,
+       private_charonservice_t *this, public_key_t *pubkey)
+{
+       JNIEnv *env;
+       jmethodID method_id;
+       private_key_t *key;
+       jobject jkey;
+
+       androidjni_attach_thread(&env);
+
+       method_id = (*env)->GetMethodID(env,
+                                               android_charonvpnservice_class,
+                                               "getUserKey", "()Ljava/security/PrivateKey;");
+       if (!method_id)
+       {
+               goto failed;
+       }
+       jkey = (*env)->CallObjectMethod(env, this->vpn_service, method_id);
+       if (!jkey)
+       {
+               goto failed;
+       }
+       key = android_private_key_create(jkey, pubkey);
+       androidjni_detach_thread();
+       return key;
+
+failed:
+       DESTROY_IF(pubkey);
+       androidjni_exception_occurred(env);
+       androidjni_detach_thread();
+       return NULL;
+}
+
 METHOD(charonservice_t, get_vpnservice_builder, vpnservice_builder_t*,
        private_charonservice_t *this)
 {
 METHOD(charonservice_t, get_vpnservice_builder, vpnservice_builder_t*,
        private_charonservice_t *this)
 {
@@ -364,6 +398,7 @@ static void charonservice_init(JNIEnv *env, jobject service, jobject builder)
                        .bypass_socket = _bypass_socket,
                        .get_trusted_certificates = _get_trusted_certificates,
                        .get_user_certificate = _get_user_certificate,
                        .bypass_socket = _bypass_socket,
                        .get_trusted_certificates = _get_trusted_certificates,
                        .get_user_certificate = _get_user_certificate,
+                       .get_user_key = _get_user_key,
                        .get_vpnservice_builder = _get_vpnservice_builder,
                },
                .attr = android_attr_create(),
                        .get_vpnservice_builder = _get_vpnservice_builder,
                },
                .attr = android_attr_create(),
index 507010b..367c76c 100644 (file)
@@ -97,6 +97,14 @@ struct charonservice_t {
        linked_list_t *(*get_user_certificate)(charonservice_t *this);
 
        /**
        linked_list_t *(*get_user_certificate)(charonservice_t *this);
 
        /**
+        * Get the configured private key via JNI
+        *
+        * @param pubkey                the public key as extracted from the certificate
+        * @return                              PrivateKey object, NULL on failure
+        */
+       private_key_t *(*get_user_key)(charonservice_t *this, public_key_t *pubkey);
+
+       /**
         * Get the current vpnservice_builder_t object
         *
         * @return                              VpnService.Builder instance
         * Get the current vpnservice_builder_t object
         *
         * @return                              VpnService.Builder instance
index 3a91c2f..966fdb9 100644 (file)
@@ -462,6 +462,23 @@ public class CharonVpnService extends VpnService implements Runnable
        }
 
        /**
        }
 
        /**
+        * Function called via JNI to get the private key the user selected.
+        *
+        * Since this method is called from a thread of charon's thread pool we are safe
+        * to call methods on KeyChain directly.
+        *
+        * @return the private key
+        * @throws InterruptedException
+        * @throws KeyChainException
+        * @throws CertificateEncodingException
+        */
+       private PrivateKey getUserKey() throws KeyChainException, InterruptedException
+       {
+               return KeyChain.getPrivateKey(getApplicationContext(), mCurrentUserCertificateAlias);
+
+       }
+
+       /**
         * Initialization of charon, provided by libandroidbridge.so
         *
         * @param builder BuilderAdapter for this connection
         * Initialization of charon, provided by libandroidbridge.so
         *
         * @param builder BuilderAdapter for this connection