diff options
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 Binary files differnew file mode 100644 index 00000000..a2f59082 --- /dev/null +++ b/tlsexternalcertprovider/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/tlsexternalcertprovider/src/main/res/mipmap-hdpi/ic_launcher_round.png b/tlsexternalcertprovider/src/main/res/mipmap-hdpi/ic_launcher_round.png Binary files differnew file mode 100644 index 00000000..1b523998 --- /dev/null +++ b/tlsexternalcertprovider/src/main/res/mipmap-hdpi/ic_launcher_round.png diff --git a/tlsexternalcertprovider/src/main/res/mipmap-mdpi/ic_launcher.png b/tlsexternalcertprovider/src/main/res/mipmap-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..ff10afd6 --- /dev/null +++ b/tlsexternalcertprovider/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/tlsexternalcertprovider/src/main/res/mipmap-mdpi/ic_launcher_round.png b/tlsexternalcertprovider/src/main/res/mipmap-mdpi/ic_launcher_round.png Binary files differnew file mode 100644 index 00000000..115a4c76 --- /dev/null +++ b/tlsexternalcertprovider/src/main/res/mipmap-mdpi/ic_launcher_round.png diff --git a/tlsexternalcertprovider/src/main/res/mipmap-xhdpi/ic_launcher.png b/tlsexternalcertprovider/src/main/res/mipmap-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..dcd3cd80 --- /dev/null +++ b/tlsexternalcertprovider/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/tlsexternalcertprovider/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/tlsexternalcertprovider/src/main/res/mipmap-xhdpi/ic_launcher_round.png Binary files differnew file mode 100644 index 00000000..459ca609 --- /dev/null +++ b/tlsexternalcertprovider/src/main/res/mipmap-xhdpi/ic_launcher_round.png diff --git a/tlsexternalcertprovider/src/main/res/mipmap-xxhdpi/ic_launcher.png b/tlsexternalcertprovider/src/main/res/mipmap-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..8ca12fe0 --- /dev/null +++ b/tlsexternalcertprovider/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/tlsexternalcertprovider/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/tlsexternalcertprovider/src/main/res/mipmap-xxhdpi/ic_launcher_round.png Binary files differnew file mode 100644 index 00000000..8e19b410 --- /dev/null +++ b/tlsexternalcertprovider/src/main/res/mipmap-xxhdpi/ic_launcher_round.png diff --git a/tlsexternalcertprovider/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/tlsexternalcertprovider/src/main/res/mipmap-xxxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..b824ebdd --- /dev/null +++ b/tlsexternalcertprovider/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/tlsexternalcertprovider/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/tlsexternalcertprovider/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png Binary files differnew file mode 100644 index 00000000..4c19a13c --- /dev/null +++ b/tlsexternalcertprovider/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png 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 |