summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2018-06-28 15:21:18 +0200
committerArne Schwabe <arne@rfc2549.org>2018-07-27 12:53:11 +0200
commit7b7940186fafcdf4bb15ea8e087b8cf345cd53c8 (patch)
treed11cb5bc887ace20d14ef42daf778709e7eb5e79
parentd8ee68b5d912933f36e0fc9edc63a2e7eb7f819f (diff)
First draft of an external TLS provider app.
-rw-r--r--build.gradle4
-rw-r--r--main/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl28
-rw-r--r--main/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl2
-rw-r--r--settings.gradle1
-rw-r--r--tlsexternalcertprovider/.gitignore1
-rw-r--r--tlsexternalcertprovider/build.gradle54
-rw-r--r--tlsexternalcertprovider/proguard-rules.pro21
-rw-r--r--tlsexternalcertprovider/src/androidTest/java/de/blinkt/externalcertprovider/ExampleInstrumentedTest.java31
-rw-r--r--tlsexternalcertprovider/src/main/AndroidManifest.xml43
-rw-r--r--tlsexternalcertprovider/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl28
-rw-r--r--tlsexternalcertprovider/src/main/java/de/blinkt/externalcertprovider/ExternalCertService.java196
-rw-r--r--tlsexternalcertprovider/src/main/java/de/blinkt/externalcertprovider/SelectCertificateActivity.java26
-rw-r--r--tlsexternalcertprovider/src/main/res/drawable-v24/ic_launcher_foreground.xml39
-rw-r--r--tlsexternalcertprovider/src/main/res/drawable/ic_launcher_background.xml79
-rw-r--r--tlsexternalcertprovider/src/main/res/layout/activity_main.xml27
-rw-r--r--tlsexternalcertprovider/src/main/res/mipmap-anydpi-v26/ic_launcher.xml10
-rw-r--r--tlsexternalcertprovider/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml10
-rw-r--r--tlsexternalcertprovider/src/main/res/mipmap-hdpi/ic_launcher.pngbin0 -> 3056 bytes
-rw-r--r--tlsexternalcertprovider/src/main/res/mipmap-hdpi/ic_launcher_round.pngbin0 -> 5024 bytes
-rw-r--r--tlsexternalcertprovider/src/main/res/mipmap-mdpi/ic_launcher.pngbin0 -> 2096 bytes
-rw-r--r--tlsexternalcertprovider/src/main/res/mipmap-mdpi/ic_launcher_round.pngbin0 -> 2858 bytes
-rw-r--r--tlsexternalcertprovider/src/main/res/mipmap-xhdpi/ic_launcher.pngbin0 -> 4569 bytes
-rw-r--r--tlsexternalcertprovider/src/main/res/mipmap-xhdpi/ic_launcher_round.pngbin0 -> 7098 bytes
-rw-r--r--tlsexternalcertprovider/src/main/res/mipmap-xxhdpi/ic_launcher.pngbin0 -> 6464 bytes
-rw-r--r--tlsexternalcertprovider/src/main/res/mipmap-xxhdpi/ic_launcher_round.pngbin0 -> 10676 bytes
-rw-r--r--tlsexternalcertprovider/src/main/res/mipmap-xxxhdpi/ic_launcher.pngbin0 -> 9250 bytes
-rw-r--r--tlsexternalcertprovider/src/main/res/mipmap-xxxhdpi/ic_launcher_round.pngbin0 -> 15523 bytes
-rw-r--r--tlsexternalcertprovider/src/main/res/values/strings.xml8
-rw-r--r--tlsexternalcertprovider/src/main/res/values/styles.xml10
-rw-r--r--tlsexternalcertprovider/src/test/java/de/blinkt/externalcertprovider/ExampleUnitTest.java22
30 files changed, 639 insertions, 1 deletions
diff --git a/build.gradle b/build.gradle
index d0913ea8..9d0ff8bd 100644
--- a/build.gradle
+++ b/build.gradle
@@ -16,3 +16,7 @@ buildscript {
}
}
+
+repositories {
+ google()
+} \ No newline at end of file
diff --git a/main/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl b/main/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl
new file mode 100644
index 00000000..d1e1a4bf
--- /dev/null
+++ b/main/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl
@@ -0,0 +1,28 @@
+// ExternalCertificateProvider.aidl
+package de.blinkt.openvpn.api;
+
+
+/*
+ * This is very simple interface that is specialised to have only the minimal set of crypto
+ * operation that are needed for OpenVPN to authenticate with an external certificate
+ */
+interface ExternalCertificateProvider {
+ /**
+ * Requests signing the data with RSA/ECB/PKCS1PADDING
+ * for RSA certficate and with NONEwithECDSA for EC certificates
+ * @parm alias the parameter that
+ */
+ byte[] getSignedData(String alias, in byte[] data);
+
+ /**
+ * Requests a
+ */
+ String[] getCertificateChain(in String alias);
+
+ /**
+ * request an Intent that should be started when user uses the select certificate box
+ * the already selected alias will be provided in the extra android.security.extra.KEY_ALIAS
+ * if applicable
+ */
+
+}
diff --git a/main/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl b/main/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl
index c0108a90..ac731b56 100644
--- a/main/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl
+++ b/main/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl
@@ -18,7 +18,7 @@ interface IOpenVPNAPIService {
boolean addVPNProfile (String name, String config);
/** start a profile using a config as inline string. Make sure that all needed data is inlined,
- * e.g., using <ca>...</ca> or <auth-user-data>...</auth-user-data>
+ * e.g., using <ca>...</ca> or <auth-user-pass>...</auth-user-pass>
* See the OpenVPN manual page for more on inlining files */
void startVPN (in String inlineconfig);
diff --git a/settings.gradle b/settings.gradle
index 46cb21bf..0c651b1c 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -4,4 +4,5 @@
*/
include ':main'
+include ':tlsexternalcertprovider'
include ':remoteExample'
diff --git a/tlsexternalcertprovider/.gitignore b/tlsexternalcertprovider/.gitignore
new file mode 100644
index 00000000..796b96d1
--- /dev/null
+++ b/tlsexternalcertprovider/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/tlsexternalcertprovider/build.gradle b/tlsexternalcertprovider/build.gradle
new file mode 100644
index 00000000..945bfef5
--- /dev/null
+++ b/tlsexternalcertprovider/build.gradle
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012-2018 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
+apply plugin: 'com.android.application'
+
+repositories {
+ jcenter()
+}
+
+ext {
+ bouncycastleVersion = '1.49'
+}
+
+android {
+ compileSdkVersion 27
+
+
+ defaultConfig {
+ applicationId "de.blinkt.externalcertprovider"
+ minSdkVersion 16
+ targetSdkVersion 27
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ compileOptions {
+ targetCompatibility 1.8
+ sourceCompatibility 1.8
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation (
+ 'org.bouncycastle:bcprov-jdk15on:' + bouncycastleVersion,
+ 'org.bouncycastle:bcprov-ext-jdk15on:' + bouncycastleVersion,
+ 'org.bouncycastle:bcpkix-jdk15on:' + bouncycastleVersion,
+ 'org.bouncycastle:bcmail-jdk15on:' + bouncycastleVersion,
+ 'org.bouncycastle:bcpg-jdk15on:' + bouncycastleVersion
+ )
+
+}
diff --git a/tlsexternalcertprovider/proguard-rules.pro b/tlsexternalcertprovider/proguard-rules.pro
new file mode 100644
index 00000000..f1b42451
--- /dev/null
+++ b/tlsexternalcertprovider/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/tlsexternalcertprovider/src/androidTest/java/de/blinkt/externalcertprovider/ExampleInstrumentedTest.java b/tlsexternalcertprovider/src/androidTest/java/de/blinkt/externalcertprovider/ExampleInstrumentedTest.java
new file mode 100644
index 00000000..8d3a21f1
--- /dev/null
+++ b/tlsexternalcertprovider/src/androidTest/java/de/blinkt/externalcertprovider/ExampleInstrumentedTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012-2018 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
+package de.blinkt.externalcertprovider;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
+
+ assertEquals("de.blinkt.externalcertprovider", appContext.getPackageName());
+ }
+}
diff --git a/tlsexternalcertprovider/src/main/AndroidManifest.xml b/tlsexternalcertprovider/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..3ca07874
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (c) 2012-2018 Arne Schwabe
+ ~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
+ package="de.blinkt.externalcertprovider">
+
+
+ <application
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:roundIcon="@mipmap/ic_launcher_round"
+ android:supportsRtl="true"
+ >
+
+ <!--
+ OpenVPN for android will search for all application that have a activity that fulfils this
+ intent. It will be called when the user presses the select button and should return the selected
+ alias in the android.security.extra.KEY_ALIAS extra on setResult.
+
+ the already selected alias will be provided in the extra android.security.extra.KEY_ALIAS
+ if applicable
+ -->
+ <activity android:name=".SelectCertificateActivity">
+ <intent-filter>
+ <category android:name="de.blinkt.openvpn.CertProviderSelect"/>
+ </intent-filter>
+ </activity>
+
+
+ <service
+ android:name=".ExternalCertService"
+ tools:ignore="ExportedService">
+ <intent-filter>
+ <action android:name="de.blinkt.openvpn.api.ExternalCertificateProvider" />
+ </intent-filter>
+ </service>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/tlsexternalcertprovider/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl b/tlsexternalcertprovider/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl
new file mode 100644
index 00000000..d1e1a4bf
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl
@@ -0,0 +1,28 @@
+// ExternalCertificateProvider.aidl
+package de.blinkt.openvpn.api;
+
+
+/*
+ * This is very simple interface that is specialised to have only the minimal set of crypto
+ * operation that are needed for OpenVPN to authenticate with an external certificate
+ */
+interface ExternalCertificateProvider {
+ /**
+ * Requests signing the data with RSA/ECB/PKCS1PADDING
+ * for RSA certficate and with NONEwithECDSA for EC certificates
+ * @parm alias the parameter that
+ */
+ byte[] getSignedData(String alias, in byte[] data);
+
+ /**
+ * Requests a
+ */
+ String[] getCertificateChain(in String alias);
+
+ /**
+ * request an Intent that should be started when user uses the select certificate box
+ * the already selected alias will be provided in the extra android.security.extra.KEY_ALIAS
+ * if applicable
+ */
+
+}
diff --git a/tlsexternalcertprovider/src/main/java/de/blinkt/externalcertprovider/ExternalCertService.java b/tlsexternalcertprovider/src/main/java/de/blinkt/externalcertprovider/ExternalCertService.java
new file mode 100644
index 00000000..5948a2b2
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/java/de/blinkt/externalcertprovider/ExternalCertService.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2012-2018 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
+package de.blinkt.externalcertprovider;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import de.blinkt.openvpn.api.ExternalCertificateProvider;
+import org.bouncycastle.openssl.PEMKeyPair;
+import org.bouncycastle.openssl.PEMParser;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.io.IOException;
+import java.io.StringReader;
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+
+/**
+ * This is a VERY basic implementation.
+ * It does not even check if the service is even allowed to use the API
+ * see ExternalOpenVPNService for an example of checking caller's creditionals
+ */
+public class ExternalCertService extends Service {
+
+ String pemkey = "-----BEGIN PRIVATE KEY-----\n" +
+ "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDsZY/pEsIaW+ZW\n" +
+ "KgipgjotRHijADuwn+cnEECT7/HMPqCqBKKAGxOp5v6B1nCQqNjU3jDYNQDSvmLw\n" +
+ "SNr8FY3Exm0LmfErgwAK0yojC+XN+TXfQ2EVcq2VmPZzIUFeoN1HJ6DVmtRBqBwd\n" +
+ "VyBxF4/3KJ4+B87s1Q5CTx50R45HndIUKCcsFBD10Za1k3SE7/kE3o1Kb993q+rR\n" +
+ "WNNE/loEAf8Gepf3/eNXSOHw30ATn2YjWuNVVD1UOe4A+RLx0t90LrrX8I3G3RhY\n" +
+ "HJMiC3X6qNbgtS8tudT+uU+G4nVIFmD7P8m0MEIp+zuzK7lZgWpG80WDv/3VGv83\n" +
+ "DG9b/WHxAgMBAAECggEBAIOdaCpUD02trOh8LqZxowJhBOl7z7/ex0uweMPk67LT\n" +
+ "i5AdVHwOlzwZJ8oSIknoOBEMRBWcLQEojt1JMuL2/R95emzjIKshHHzqZKNulFvB\n" +
+ "TIUpdnwChTKtH0mqUkLlPU3Ienty4IpNlpmfUKimfbkWHERdBJBHbtDsTABhdo3X\n" +
+ "9pCF/yRKqJS2Fy/Mkl3gv1y/NB1OL4Jhl7vQbf+kmgfQN2qdOVe2BOKQ8NlPUDmE\n" +
+ "/1XNIDaE3s6uvUaoFfwowzsCCwN2/8QrRMMKkjvV+lEVtNmQdYxj5Xj5IwS0vkK0\n" +
+ "6icsngW87cpZxxc1zsRWcSTloy5ohub4FgKhlolmigECgYEA+cBlxzLvaMzMlBQY\n" +
+ "kCac9KQMvVL+DIFHlZA5i5L/9pRVp4JJwj3GUoehFJoFhsxnKr8HZyLwBKlCmUVm\n" +
+ "VxnshRWiAU18emUmeAtSGawlAS3QXhikVZDdd/L20YusLT+DXV81wlKR97/r9+17\n" +
+ "klQOLkSdPm9wcMDOWMNHX8bUg8kCgYEA8k+hQv6+TR/+Beao2IIctFtw/EauaJiJ\n" +
+ "wW5ql1cpCLPMAOQUvjs0Km3zqctfBF8mUjdkcyJ4uhL9FZtfywY22EtRIXOJ/8VR\n" +
+ "we65mVo6RLR8YVM54sihanuFOnlyF9LIBWB+9pUfh1/Y7DSebh7W73uxhAxQhi3Y\n" +
+ "QwfIQIFd8OkCgYBalH4VXhLYhpaYCiXSej6ot6rrK2N6c5Tb2MAWMA1nh+r84tMP\n" +
+ "gMoh+pDgYPAqMI4mQbxUmqZEeoLuBe6VHpDav7rPECRaW781AJ4ZM4cEQ3Jz/inz\n" +
+ "4qOAMn10CF081/Ez9ykPPlU0bsYNWHNd4eB2xWnmUBKOwk7UgJatVPaUiQKBgQCI\n" +
+ "f18CVGpzG9CHFnaK8FCnMNOm6VIaTcNcGY0mD81nv5Dt943P054BQMsAHTY7SjZW\n" +
+ "HioRyZtkhonXAB2oSqnekh7zzxgv4sG5k3ct8evdBCcE1FNJc2eqikZ0uDETRoOy\n" +
+ "s7cRxNNr+QxDkyikM+80HOPU1PMPgwfOSrX90GJQ8QKBgEBKohGMV/sNa4t14Iau\n" +
+ "qO8aagoqh/68K9GFXljsl3/iCSa964HIEREtW09Qz1w3dotEgp2w8bsDa+OwWrLy\n" +
+ "0SY7T5jRViM3cDWRlUBLrGGiL0FiwsfqiRiji60y19erJgrgyGVIb1kIgIBRkgFM\n" +
+ "2MMweASzTmZcri4PA/5C0HYb\n" +
+ "-----END PRIVATE KEY-----\n";
+
+ String[] certchain = new String[]{"-----BEGIN CERTIFICATE-----\n" +
+ "MIIFFDCCAvygAwIBAgIBAjANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJLRzEL\n" +
+ "MAkGA1UECBMCTkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNVBAoTDE9wZW5WUE4t\n" +
+ "VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTE0MTAy\n" +
+ "MjIxNTk1M1oXDTI0MTAxOTIxNTk1M1owajELMAkGA1UEBhMCS0cxCzAJBgNVBAgT\n" +
+ "Ak5BMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxFDASBgNVBAMTC1Rlc3QtQ2xpZW50\n" +
+ "MSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4wggEiMA0GCSqGSIb3\n" +
+ "DQEBAQUAA4IBDwAwggEKAoIBAQDsZY/pEsIaW+ZWKgipgjotRHijADuwn+cnEECT\n" +
+ "7/HMPqCqBKKAGxOp5v6B1nCQqNjU3jDYNQDSvmLwSNr8FY3Exm0LmfErgwAK0yoj\n" +
+ "C+XN+TXfQ2EVcq2VmPZzIUFeoN1HJ6DVmtRBqBwdVyBxF4/3KJ4+B87s1Q5CTx50\n" +
+ "R45HndIUKCcsFBD10Za1k3SE7/kE3o1Kb993q+rRWNNE/loEAf8Gepf3/eNXSOHw\n" +
+ "30ATn2YjWuNVVD1UOe4A+RLx0t90LrrX8I3G3RhYHJMiC3X6qNbgtS8tudT+uU+G\n" +
+ "4nVIFmD7P8m0MEIp+zuzK7lZgWpG80WDv/3VGv83DG9b/WHxAgMBAAGjgcgwgcUw\n" +
+ "CQYDVR0TBAIwADAdBgNVHQ4EFgQU0rQ2D7H83aXqKvfHI4n64/p6RB0wgZgGA1Ud\n" +
+ "IwSBkDCBjYAUK0DlyX319JY46S/jL9lAZMmOBZuhaqRoMGYxCzAJBgNVBAYTAktH\n" +
+ "MQswCQYDVQQIEwJOQTEQMA4GA1UEBxMHQklTSEtFSzEVMBMGA1UEChMMT3BlblZQ\n" +
+ "Ti1URVNUMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW6CCQChTt76\n" +
+ "kPKugTANBgkqhkiG9w0BAQsFAAOCAgEAf+D+hKfs32KlzTzB5kKxMRLwudqnnj+9\n" +
+ "llK2/FV0ZD7k/36q9z4GGF9zhfjI4GcbTZfKBdA3BzNkm+Z4dxSaVbsqrMN/yRUI\n" +
+ "g1zIwmHTcUwFCyvLo4dtoDLtsLMnl0pVjQEqMFZoq/LaXBBzyaoKnEtMoFtRbgp+\n" +
+ "bFOAsADhHppMCjeeIIm8xeV5WLdF/9PEof3ZeD1FFnTfgkQdHYFQWrkyTOJPPw46\n" +
+ "ZVpkgzspMcSZiLzFhDnyGRLhZtDq+3Wx0ie+kVmjKwnVXL9GjtZn1gvs2qvwgBmH\n" +
+ "ZAepd7FeDOLFHWqsXSPzMHU2TsrDTrBNjCzOUmFj3tX17+8KayMlJjw68sPCFhk/\n" +
+ "qTK6aPnJEjw+xh//m070kLBj9dEzADBa6CT6NUSbaoDzpsx7PHNfUMQwcdh0kCcK\n" +
+ "AU6lXrH42sJhgRGuKaOP+n5MTmKxAN6S449qLtrZOF1rfA3kAarIxm2LzcDIbuRX\n" +
+ "IYr2RjDZrVGhh5amU8kexrvD61X+jNZc1cbzyrBg0tQqH4iU00wa2gyU/sFdDSrb\n" +
+ "mSld9t0WxMhNdJ6A2dCq7XvjMORH2PUVwXG4xv3u/J6yX7W3ku3/yjf2x4K0VBOb\n" +
+ "g82Hi35k9i5UOiKxxcH0pSVTmk2oD+c1S4nfGYNmZNnb0WErJBsdRET7STCHt0kj\n" +
+ "CAKK4CXz9EM=\n" +
+ "-----END CERTIFICATE-----\n"
+ ,
+ "-----BEGIN CERTIFICATE-----\n" +
+ "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\n" +
+ "-----END CERTIFICATE-----\n"};
+ private final ExternalCertificateProvider.Stub mBinder = new ExternalCertificateProvider.Stub() {
+
+ @Override
+ public byte[] getSignedData(String alias, byte[] data) throws RemoteException {
+ try {
+
+ // This is more or less code that has been just modified long enough that it works
+ // Don't take it as good example how to get a Privatekey
+ StringReader keyreader = new StringReader(certchain + pemkey);
+ PEMParser pemparser = new PEMParser(keyreader);
+
+ PEMKeyPair bcKeyPair = (PEMKeyPair) pemparser.readObject();
+
+ PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bcKeyPair.getPrivateKeyInfo().getEncoded());
+ KeyFactory kf = KeyFactory.getInstance("RSA");
+ PrivateKey key = kf.generatePrivate(keySpec);
+
+ // The actual signing
+
+ Cipher signer;
+ signer = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
+
+
+ signer.init(Cipher.ENCRYPT_MODE, key);
+
+ byte[] signed_bytes = signer.doFinal(data);
+ return signed_bytes;
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (NoSuchPaddingException e) {
+ e.printStackTrace();
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ } catch (IllegalBlockSizeException e) {
+ e.printStackTrace();
+ } catch (BadPaddingException e) {
+ e.printStackTrace();
+ } catch (InvalidKeySpecException e) {
+ e.printStackTrace();
+ } catch (InvalidKeyException e) {
+ e.printStackTrace();
+ }
+ // Something failed, return null
+ return null;
+
+ }
+
+ @Override
+ public String[] getCertificateChain(String alias) throws RemoteException {
+
+ return certchain;
+ }
+ };
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ }
+
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+} \ No newline at end of file
diff --git a/tlsexternalcertprovider/src/main/java/de/blinkt/externalcertprovider/SelectCertificateActivity.java b/tlsexternalcertprovider/src/main/java/de/blinkt/externalcertprovider/SelectCertificateActivity.java
new file mode 100644
index 00000000..8d465aa4
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/java/de/blinkt/externalcertprovider/SelectCertificateActivity.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2012-2018 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
+package de.blinkt.externalcertprovider;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.security.KeyChain;
+import android.os.Bundle;
+
+public class SelectCertificateActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ findViewById(R.id.nicecert).setOnClickListener((v) ->
+ {
+ Intent intent = new Intent();
+ intent.putExtra(KeyChain.EXTRA_KEY_ALIAS, "mynicecert");
+ setResult(RESULT_OK);
+ });
+ }
+}
diff --git a/tlsexternalcertprovider/src/main/res/drawable-v24/ic_launcher_foreground.xml b/tlsexternalcertprovider/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 00000000..5b4df428
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,39 @@
+<!--
+ ~ Copyright (c) 2012-2018 Arne Schwabe
+ ~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportHeight="108"
+ android:viewportWidth="108">
+ <path
+ android:fillType="evenOdd"
+ android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
+ android:strokeColor="#00000000"
+ android:strokeWidth="1">
+ <aapt:attr name="android:fillColor">
+ <gradient
+ android:endX="78.5885"
+ android:endY="90.9159"
+ android:startX="48.7653"
+ android:startY="61.0927"
+ android:type="linear">
+ <item
+ android:color="#44000000"
+ android:offset="0.0"/>
+ <item
+ android:color="#00000000"
+ android:offset="1.0"/>
+ </gradient>
+ </aapt:attr>
+ </path>
+ <path
+ android:fillColor="#FFFFFF"
+ android:fillType="nonZero"
+ android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
+ android:strokeColor="#00000000"
+ android:strokeWidth="1"/>
+</vector>
diff --git a/tlsexternalcertprovider/src/main/res/drawable/ic_launcher_background.xml b/tlsexternalcertprovider/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 00000000..79fe24be
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (c) 2012-2018 Arne Schwabe
+ ~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ -->
+
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="108dp"
+ android:width="108dp"
+ android:viewportHeight="108"
+ android:viewportWidth="108">
+ <path android:fillColor="#26A69A"
+ android:pathData="M0,0h108v108h-108z"/>
+ <path android:fillColor="#00000000" android:pathData="M9,0L9,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M19,0L19,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M29,0L29,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M39,0L39,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M49,0L49,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M59,0L59,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M69,0L69,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M79,0L79,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M89,0L89,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M99,0L99,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,9L108,9"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,19L108,19"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,29L108,29"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,39L108,39"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,49L108,49"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,59L108,59"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,69L108,69"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,79L108,79"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,89L108,89"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,99L108,99"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M19,29L89,29"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M19,39L89,39"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M19,49L89,49"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M19,59L89,59"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M19,69L89,69"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M19,79L89,79"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M29,19L29,89"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M39,19L39,89"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M49,19L49,89"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M59,19L59,89"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M69,19L69,89"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M79,19L79,89"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+</vector>
diff --git a/tlsexternalcertprovider/src/main/res/layout/activity_main.xml b/tlsexternalcertprovider/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..3a1bf2f1
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/layout/activity_main.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (c) 2012-2018 Arne Schwabe
+ ~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ -->
+
+<LinearLayout android:orientation="vertical"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".SelectCertificateActivity">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="This demo app has no sophisticated selection!"
+ />
+
+ <Button
+ android:id="@+id/nicecert"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Send mynicecert as string back to app"
+
+ />
+</LinearLayout> \ No newline at end of file
diff --git a/tlsexternalcertprovider/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/tlsexternalcertprovider/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 00000000..72310419
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (c) 2012-2018 Arne Schwabe
+ ~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ -->
+
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/ic_launcher_background"/>
+ <foreground android:drawable="@drawable/ic_launcher_foreground"/>
+</adaptive-icon> \ No newline at end of file
diff --git a/tlsexternalcertprovider/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/tlsexternalcertprovider/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 00000000..72310419
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (c) 2012-2018 Arne Schwabe
+ ~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ -->
+
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/ic_launcher_background"/>
+ <foreground android:drawable="@drawable/ic_launcher_foreground"/>
+</adaptive-icon> \ No newline at end of file
diff --git a/tlsexternalcertprovider/src/main/res/mipmap-hdpi/ic_launcher.png b/tlsexternalcertprovider/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 00000000..a2f59082
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/tlsexternalcertprovider/src/main/res/mipmap-hdpi/ic_launcher_round.png b/tlsexternalcertprovider/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 00000000..1b523998
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/mipmap-hdpi/ic_launcher_round.png
Binary files differ
diff --git a/tlsexternalcertprovider/src/main/res/mipmap-mdpi/ic_launcher.png b/tlsexternalcertprovider/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 00000000..ff10afd6
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/tlsexternalcertprovider/src/main/res/mipmap-mdpi/ic_launcher_round.png b/tlsexternalcertprovider/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 00000000..115a4c76
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/mipmap-mdpi/ic_launcher_round.png
Binary files differ
diff --git a/tlsexternalcertprovider/src/main/res/mipmap-xhdpi/ic_launcher.png b/tlsexternalcertprovider/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..dcd3cd80
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/tlsexternalcertprovider/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/tlsexternalcertprovider/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..459ca609
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Binary files differ
diff --git a/tlsexternalcertprovider/src/main/res/mipmap-xxhdpi/ic_launcher.png b/tlsexternalcertprovider/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..8ca12fe0
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/tlsexternalcertprovider/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/tlsexternalcertprovider/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..8e19b410
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/tlsexternalcertprovider/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/tlsexternalcertprovider/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 00000000..b824ebdd
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/tlsexternalcertprovider/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/tlsexternalcertprovider/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..4c19a13c
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/tlsexternalcertprovider/src/main/res/values/strings.xml b/tlsexternalcertprovider/src/main/res/values/strings.xml
new file mode 100644
index 00000000..dca6fe10
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/values/strings.xml
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2012-2018 Arne Schwabe
+ ~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ -->
+
+<resources>
+ <string name="app_name">ExternalCertProvider</string>
+</resources>
diff --git a/tlsexternalcertprovider/src/main/res/values/styles.xml b/tlsexternalcertprovider/src/main/res/values/styles.xml
new file mode 100644
index 00000000..9b963769
--- /dev/null
+++ b/tlsexternalcertprovider/src/main/res/values/styles.xml
@@ -0,0 +1,10 @@
+<!--
+ ~ Copyright (c) 2012-2018 Arne Schwabe
+ ~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ -->
+
+<resources>
+
+
+
+</resources>
diff --git a/tlsexternalcertprovider/src/test/java/de/blinkt/externalcertprovider/ExampleUnitTest.java b/tlsexternalcertprovider/src/test/java/de/blinkt/externalcertprovider/ExampleUnitTest.java
new file mode 100644
index 00000000..785f56a9
--- /dev/null
+++ b/tlsexternalcertprovider/src/test/java/de/blinkt/externalcertprovider/ExampleUnitTest.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2012-2018 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
+package de.blinkt.externalcertprovider;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+} \ No newline at end of file