summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgenii Potapov <potapov@rutoken.ru>2020-11-12 09:23:34 +0300
committerArne Schwabe <arne@rfc2549.org>2020-11-23 10:53:22 +0100
commita6de5a9e4d8d757414c5e2f94eb806be9216dda3 (patch)
tree4fe085c140e4e3824a9cbfb2b1b59f99d190934d
parentdd6d365fb67ca992617e87a04ab61b17feffdecd (diff)
Provide a padding type for externalCertificateProvider
Based on server-side OpenSSL behaviour the data to be signed by externalCertificateProvider may be or may be not padded already. To choose the proper signing mechanism we need to pass external info.
-rw-r--r--main/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl21
-rw-r--r--main/src/main/java/de/blinkt/openvpn/VpnProfile.java26
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/ExtAuthHelper.java14
3 files changed, 50 insertions, 11 deletions
diff --git a/main/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl b/main/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl
index c6db965b..951cff96 100644
--- a/main/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl
+++ b/main/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl
@@ -1,16 +1,16 @@
// 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 {
/**
+ * @deprecated use {@link #getSignedDataWithExtra} instead
* Requests signing the data with RSA/ECB/PKCS1PADDING
* for RSA certficate and with NONEwithECDSA for EC certificates
- * @parm alias the parameter that
+ * @param alias user certificate identifier
*/
byte[] getSignedData(in String alias, in byte[] data);
@@ -36,4 +36,21 @@ interface ExternalCertificateProvider {
*
*/
Bundle getCertificateMetaData(in String alias);
+
+ /**
+ * Requests signing the data with RSA/ECB/PKCS1PADDING or RSA/ECB/nopadding
+ * for RSA certficate and with NONEwithECDSA for EC certificates
+ * @param alias user certificate identifier
+ * @param data the data to be signed
+ * @param extra additional information.
+ * Should contain the following keys:
+ * <p><ul>
+ * <li>int key "de.blinkt.openvpn.api.RSA_PADDING_TYPE", may be set as:
+ * <p><ul>
+ * <li>0 - for RSA/ECB/nopadding
+ * <li>1 - for RSA/ECB/PKCS1PADDING
+ * </ul><p>
+ * </ul><p>
+ */
+ byte[] getSignedDataWithExtra(in String alias, in byte[] data, in Bundle extra);
}
diff --git a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java
index 2cb12296..2ccff18b 100644
--- a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java
+++ b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java
@@ -12,6 +12,7 @@ import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
+import android.os.Bundle;
import android.preference.PreferenceManager;
import android.security.KeyChain;
import android.security.KeyChainException;
@@ -82,6 +83,7 @@ public class VpnProfile implements Serializable, Cloneable {
private static final long serialVersionUID = 7085688938959334563L;
private static final int AUTH_RETRY_NONE_KEEP = 1;
private static final int AUTH_RETRY_INTERACT = 3;
+ private static final String EXTRA_RSA_PADDING_TYPE = "de.blinkt.openvpn.api.RSA_PADDING_TYPE";
public static String DEFAULT_DNS1 = "8.8.8.8";
public static String DEFAULT_DNS2 = "8.8.4.4";
// variable named wrong and should haven beeen transient
@@ -1148,10 +1150,16 @@ public class VpnProfile implements Serializable, Cloneable {
public String getSignedData(Context c, String b64data, boolean pkcs1padding) {
byte[] data = Base64.decode(b64data, Base64.DEFAULT);
byte[] signed_bytes;
- if (mAuthenticationType == TYPE_EXTERNAL_APP)
- signed_bytes = getExtAppSignedData(c, data);
- else
+ if (mAuthenticationType == TYPE_EXTERNAL_APP) {
+ RsaPaddingType paddingType = pkcs1padding ? RsaPaddingType.PKCS1_PADDING : RsaPaddingType.NO_PADDING;
+ Bundle extra = new Bundle();
+ extra.putInt(EXTRA_RSA_PADDING_TYPE, paddingType.ordinal());
+
+ signed_bytes = getExtAppSignedData(c, data, extra);
+ }
+ else {
signed_bytes = getKeyChainSignedData(data, pkcs1padding);
+ }
if (signed_bytes != null)
return Base64.encodeToString(signed_bytes, Base64.NO_WRAP);
@@ -1159,11 +1167,11 @@ public class VpnProfile implements Serializable, Cloneable {
return null;
}
- private byte[] getExtAppSignedData(Context c, byte[] data) {
+ private byte[] getExtAppSignedData(Context c, byte[] data, Bundle extra) {
if (TextUtils.isEmpty(mExternalAuthenticator))
return null;
try {
- return ExtAuthHelper.signData(c, mExternalAuthenticator, mAlias, data);
+ return ExtAuthHelper.signData(c, mExternalAuthenticator, mAlias, data, extra);
} catch (KeyChainException | InterruptedException e) {
VpnStatus.logError(R.string.error_extapp_sign, mExternalAuthenticator, e.getClass().toString(), e.getLocalizedMessage());
return null;
@@ -1257,7 +1265,13 @@ public class VpnProfile implements Serializable, Cloneable {
}
}
-
+ /**
+ * The order of elements is important!
+ */
+ private enum RsaPaddingType {
+ NO_PADDING,
+ PKCS1_PADDING
+ }
}
diff --git a/main/src/main/java/de/blinkt/openvpn/core/ExtAuthHelper.java b/main/src/main/java/de/blinkt/openvpn/core/ExtAuthHelper.java
index a62a4c62..d102dce2 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/ExtAuthHelper.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/ExtAuthHelper.java
@@ -108,15 +108,23 @@ public class ExtAuthHelper {
public static byte[] signData(@NonNull Context context,
@NonNull String extAuthPackageName,
@NonNull String alias,
- @NonNull byte[] data
+ @NonNull byte[] data,
+ @NonNull Bundle extra
) throws KeyChainException, InterruptedException
{
- try (ExternalAuthProviderConnection authProviderConnection = bindToExtAuthProvider(context.getApplicationContext(), extAuthPackageName)) {
+ try (ExternalAuthProviderConnection authProviderConnection =
+ bindToExtAuthProvider(context.getApplicationContext(), extAuthPackageName)) {
ExternalCertificateProvider externalAuthProvider = authProviderConnection.getService();
- return externalAuthProvider.getSignedData(alias, data);
+
+ byte[] result = externalAuthProvider.getSignedDataWithExtra(alias, data, extra);
+ // When the desired method is not implemented, a default implementation is called, returning null
+ if (result == null)
+ result = externalAuthProvider.getSignedData(alias, data);
+
+ return result;
} catch (RemoteException e) {
throw new KeyChainException(e);