summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2021-12-16 16:51:27 +0100
committerArne Schwabe <arne@rfc2549.org>2021-12-17 11:36:32 +0100
commit4466103d770c353cfb8d4ea08093560ba28d58b8 (patch)
treec796c52bccbd70ddf585239b5850837f5209c3e5
parentaa222c82c1bb3243817b74f6efce7cbc9676b4bc (diff)
Update OpenVPN and add support for the new xkey infrastructure in OpenVPN
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
-rw-r--r--main/src/main/cpp/CMakeLists.txt7
m---------main/src/main/cpp/openvpn0
-rw-r--r--main/src/main/cpp/openvpn-config/config.h4
-rw-r--r--main/src/main/cpp/ovpnutil/rsapss.cpp146
-rw-r--r--main/src/main/java/de/blinkt/openvpn/VpnProfile.java233
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/NativeUtils.java18
-rw-r--r--main/src/ui/java/de/blinkt/openvpn/fragments/Settings_Connections.kt4
7 files changed, 319 insertions, 93 deletions
diff --git a/main/src/main/cpp/CMakeLists.txt b/main/src/main/cpp/CMakeLists.txt
index 1a1176bd..04520267 100644
--- a/main/src/main/cpp/CMakeLists.txt
+++ b/main/src/main/cpp/CMakeLists.txt
@@ -104,6 +104,9 @@ target_compile_definitions(ovpnutil PRIVATE -DTARGET_ARCH_ABI=\"${ANDROID_ABI}\"
)
target_link_libraries(ovpnutil log)
+add_library(rsapss SHARED ovpnutil/rsapss.cpp)
+target_link_libraries(rsapss log crypto ssl)
+
if (NOT ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} MATCHES "build/intermediates/cmake/.*skeleton.*/")
add_library(osslspeedtest SHARED ovpnutil/sslspeed.c)
target_link_libraries(osslspeedtest log crypto ssl)
@@ -195,8 +198,8 @@ set(openvpn_srcs
src/openvpn/tls_crypt.c
src/openvpn/tun.c
src/openvpn/vlan.c
- #src/openvpn/xkey_helper.c
- #src/openvpn/xkey_provider.c
+ src/openvpn/xkey_helper.c
+ src/openvpn/xkey_provider.c
src/openvpn/comp-lz4.c
src/openvpn/comp.c
src/openvpn/compstub.c
diff --git a/main/src/main/cpp/openvpn b/main/src/main/cpp/openvpn
-Subproject e3831a62798d0324eb1e1badc1f199269a5baca
+Subproject cc43597350cb6f4ce89f23d2053dc58e0117456
diff --git a/main/src/main/cpp/openvpn-config/config.h b/main/src/main/cpp/openvpn-config/config.h
index 69ed58d3..7959c147 100644
--- a/main/src/main/cpp/openvpn-config/config.h
+++ b/main/src/main/cpp/openvpn-config/config.h
@@ -681,6 +681,4 @@ int res_init();
#define HAVE_EVP_CIPHER_CTX_RESET
-#define _SOCKLEN_T_DECLARED 1
-
-//#define HAVE_XKEY_PROVIDER 1 \ No newline at end of file
+#define _SOCKLEN_T_DECLARED 1 \ No newline at end of file
diff --git a/main/src/main/cpp/ovpnutil/rsapss.cpp b/main/src/main/cpp/ovpnutil/rsapss.cpp
new file mode 100644
index 00000000..d6346811
--- /dev/null
+++ b/main/src/main/cpp/ovpnutil/rsapss.cpp
@@ -0,0 +1,146 @@
+/* Adapted from OpenSSL's rsa_pss.c from OpenSSL 3.0.1 */
+
+/*
+ * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+#include "jni.h"
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/rsa.h>
+
+#include <array>
+
+static const unsigned char zeroes[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+static char opensslerr[1024];
+extern "C" jbyteArray Java_de_blinkt_openvpn_core_NativeUtils_rsapss(JNIEnv *env,
+ jclass,
+ jint hashtype,
+ jint MSBits,
+ jint rsa_size,
+ jbyteArray from) {
+
+ /*
+ unsigned char *EM,
+ const unsigned char *mHash,
+ const EVP_MD *Hash, const EVP_MD *mgf1Hash,
+ int sLen)
+*/
+
+ jbyte *data = env->GetByteArrayElements(from, NULL);
+ int datalen = env->GetArrayLength(from);
+
+ const auto *mHash = reinterpret_cast<const unsigned char *>(data);
+
+ const EVP_MD *Hash;
+
+ if (hashtype == 0) {
+ Hash = EVP_md5();
+ } else if (hashtype == 1) {
+ Hash = EVP_sha1();
+ } else if (hashtype == 2) {
+ Hash = EVP_sha224();
+ } else if (hashtype == 3) {
+ Hash = EVP_sha256();
+ } else if (hashtype == 4) {
+ Hash = EVP_sha384();
+ } else if (hashtype == 5) {
+ Hash = EVP_sha512();
+ }
+
+ const EVP_MD *mgf1Hash = Hash;
+
+ int ret = 0;
+ int maskedDBLen, emLen;
+ unsigned char *H, *salt = nullptr, *p;
+ EVP_MD_CTX *ctx = nullptr;
+
+ int hLen = EVP_MD_get_size(Hash);
+ int sLen = hLen; /* RSA_PSS_SALTLEN_DIGEST */
+
+ std::array<unsigned char, 2048> buf{};
+ unsigned char *EM = buf.data();
+
+ if (hLen < 0)
+ goto err;
+
+ emLen = rsa_size;
+ if (MSBits == 0) {
+ *EM++ = 0;
+ emLen--;
+ }
+ if (emLen < hLen + 2) {
+ goto err;
+ }
+ if (sLen == RSA_PSS_SALTLEN_MAX) {
+ sLen = emLen - hLen - 2;
+ } else if (sLen > emLen - hLen - 2) {
+ goto err;
+ }
+
+ if (sLen > 0) {
+ salt = (unsigned char *) OPENSSL_malloc(sLen);
+ if (salt == nullptr) {
+ goto err;
+ }
+ if (RAND_bytes_ex(nullptr, salt, sLen, 0) <= 0)
+ goto err;
+ }
+ maskedDBLen = emLen - hLen - 1;
+ H = EM + maskedDBLen;
+ ctx = EVP_MD_CTX_new();
+ if (ctx == nullptr)
+ goto err;
+ if (!EVP_DigestInit_ex(ctx, Hash, nullptr)
+ || !EVP_DigestUpdate(ctx, zeroes, sizeof(zeroes))
+ || !EVP_DigestUpdate(ctx, mHash, hLen))
+ goto err;
+ if (sLen && !EVP_DigestUpdate(ctx, salt, sLen))
+ goto err;
+ if (!EVP_DigestFinal_ex(ctx, H, nullptr))
+ goto err;
+
+ /* Generate dbMask in place then perform XOR on it */
+ if (PKCS1_MGF1(EM, maskedDBLen, H, hLen, mgf1Hash))
+ goto err;
+
+ p = EM;
+
+ /*
+ * Initial PS XORs with all zeroes which is a NOP so just update pointer.
+ * Note from a test above this value is guaranteed to be non-negative.
+ */
+ p += emLen - sLen - hLen - 2;
+ *p++ ^= 0x1;
+ if (sLen > 0) {
+ for (int i = 0; i < sLen; i++)
+ *p++ ^= salt[i];
+ }
+ if (MSBits)
+ EM[0] &= 0xFF >> (8 - MSBits);
+
+ /* H is already in place so just set final 0xbc */
+
+ EM[emLen - 1] = 0xbc;
+
+ ret = 1;
+
+ err:
+ EVP_MD_CTX_free(ctx);
+ OPENSSL_clear_free(salt, (size_t) sLen); /* salt != NULL implies sLen > 0 */
+
+
+ jbyteArray jb;
+
+ jb = env->NewByteArray(emLen);
+
+ env->SetByteArrayRegion(jb, 0, emLen, (jbyte *) EM);
+
+ return jb;
+} \ No newline at end of file
diff --git a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java
index bac5939d..af85eeb1 100644
--- a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java
+++ b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java
@@ -41,6 +41,8 @@ import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PSSParameterSpec;
import java.util.Collection;
@@ -89,6 +91,9 @@ public class VpnProfile implements Serializable, Cloneable {
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";
+ private static final String EXTRA_SALTLEN = "de.blinkt.openvpn.api.SALTLEN";
+ private static final String EXTRA_NEEDS_DIGEST = "de.blinkt.openvpn.api.NEEDS_DIGEST";
+ private static final String EXTRA_DIGEST = "de.blinkt.openvpn.api.DIGEST";
public static String DEFAULT_DNS1 = "9.9.9.9";
public static String DEFAULT_DNS2 = "2620:fe::fe";
// variable named wrong and should haven beeen transient
@@ -302,7 +307,7 @@ public class VpnProfile implements Serializable, Cloneable {
public void upgradeProfile() {
/* Fallthrough is intended here */
- switch(mProfileVersion) {
+ switch (mProfileVersion) {
case 0:
case 1:
/* default to the behaviour the OS used */
@@ -335,8 +340,7 @@ public class VpnProfile implements Serializable, Cloneable {
}
case 9:
if (!TextUtils.isEmpty(mDataCiphers) &&
- mDataCiphers.toUpperCase(Locale.ROOT).contains("BF-CBC"))
- {
+ mDataCiphers.toUpperCase(Locale.ROOT).contains("BF-CBC")) {
mUseLegacyProvider = true;
}
default:
@@ -507,8 +511,7 @@ public class VpnProfile implements Serializable, Cloneable {
if (!TextUtils.isEmpty(ks[1]))
cfg.append("<extra-certs>\n").append(ks[1]).append("\n</extra-certs>\n");
cfg.append("<cert>\n").append(ks[2]).append("\n</cert>\n");
- cfg.append("management-external-key nopadding pkcs1\n");
- // for xkey branch:" management-external-key pss digest
+ cfg.append("management-external-key nopadding pkcs1 pss digest\n");
} else {
cfg.append(context.getString(R.string.keychain_access)).append("\n");
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN)
@@ -527,8 +530,7 @@ public class VpnProfile implements Serializable, Cloneable {
}
}
- if (mCheckPeerFingerprint)
- {
+ if (mCheckPeerFingerprint) {
cfg.append("<peer-fingerprint>\n").append(mPeerFingerPrints).append("\n</peer-fingerprint>\n");
}
@@ -672,10 +674,9 @@ public class VpnProfile implements Serializable, Cloneable {
cfg.append("data-ciphers ").append(mDataCiphers).append("\n");
}
- if (mCompatMode > 0)
- {
- int major = mCompatMode/10000;
- int minor = mCompatMode % 10000/100;
+ if (mCompatMode > 0) {
+ int major = mCompatMode / 10000;
+ int minor = mCompatMode % 10000 / 100;
int patch = mCompatMode % 100;
cfg.append(String.format(Locale.US, "compat-mode %d.%d.%d\n", major, minor, patch));
@@ -1067,9 +1068,8 @@ public class VpnProfile implements Serializable, Cloneable {
if (!mUseLegacyProvider &&
(dataciphers.contains("BF-CBC")
- || (mCompatMode > 0 && mCompatMode < 20500)
- && cipher.equals("BF-CBC")))
- {
+ || (mCompatMode > 0 && mCompatMode < 20500)
+ && cipher.equals("BF-CBC"))) {
return R.string.bf_cbc_requires_legacy;
}
@@ -1198,12 +1198,7 @@ public class VpnProfile implements Serializable, Cloneable {
byte[] data = Base64.decode(b64data, Base64.DEFAULT);
byte[] signed_bytes;
if (mAuthenticationType == TYPE_EXTERNAL_APP) {
- /* TODO: FIXME */
- RsaPaddingType paddingType = (padding == OpenVPNManagement.SignaturePadding.RSA_PKCS1_PADDING) ? RsaPaddingType.PKCS1_PADDING : RsaPaddingType.NO_PADDING;
- Bundle extra = new Bundle();
- extra.putInt(EXTRA_RSA_PADDING_TYPE, paddingType.ordinal());
-
- signed_bytes = getExtAppSignedData(c, data, extra);
+ signed_bytes = getExtAppSignedData(c, data, padding, saltlen, hashalg, needDigest);
} else {
signed_bytes = getKeyChainSignedData(data, padding, saltlen, hashalg, needDigest);
}
@@ -1214,7 +1209,30 @@ public class VpnProfile implements Serializable, Cloneable {
return null;
}
- private byte[] getExtAppSignedData(Context c, byte[] data, Bundle extra) {
+ private byte[] getExtAppSignedData(Context c, byte[] data, OpenVPNManagement.SignaturePadding padding, String saltlen, String hashalg, boolean needDigest)
+ {
+
+ Bundle extra = new Bundle();
+ RsaPaddingType paddingType;
+ switch (padding) {
+ case RSA_PKCS1_PADDING:
+ paddingType = RsaPaddingType.PKCS1_PADDING;
+ break;
+ case NO_PADDING:
+ paddingType = RsaPaddingType.NO_PADDING;
+ break;
+ case RSA_PKCS1_PSS_PADDING:
+ paddingType = RsaPaddingType.RSAPSS_PADDING;
+ break;
+ default:
+ paddingType = RsaPaddingType.NO_PADDING;
+ }
+
+ extra.putInt(EXTRA_RSA_PADDING_TYPE, paddingType.ordinal());
+ extra.putString(EXTRA_SALTLEN, saltlen);
+ extra.putString(EXTRA_DIGEST, hashalg);
+ extra.putBoolean(EXTRA_NEEDS_DIGEST, needDigest);
+
if (TextUtils.isEmpty(mExternalAuthenticator))
return null;
try {
@@ -1227,12 +1245,6 @@ public class VpnProfile implements Serializable, Cloneable {
private byte[] getKeyChainSignedData(byte[] data, OpenVPNManagement.SignaturePadding padding, String saltlen, String hashalg, boolean needDigest) {
PrivateKey privkey = getKeystoreKey();
- // The Jelly Bean *evil* Hack
- // 4.2 implements the RSA/ECB/PKCS1PADDING in the OpenSSLprovider
- if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN) {
- /* TODO: really fix this?! */
- return processSignJellyBeans(privkey, data, padding);
- }
try {
@@ -1243,17 +1255,25 @@ public class VpnProfile implements Serializable, Cloneable {
if (needDigest || keyalgorithm.equals("EC")) {
return doDigestSign(privkey, data, padding, hashalg, saltlen);
} else {
- /* ECB is perfectly fine in this special case, since we are using it for
- the public/private part in the TLS exchange
- */
- Cipher signer;
- if (padding == OpenVPNManagement.SignaturePadding.RSA_PKCS1_PADDING)
- signer = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
- else if (padding == OpenVPNManagement.SignaturePadding.NO_PADDING)
- signer = Cipher.getInstance("RSA/ECB/NoPadding");
+ // The Jelly Bean *evil* Hack
+ // 4.2 implements the RSA/ECB/PKCS1PADDING in the OpenSSLprovider
+ if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN) {
+ return processSignJellyBeans(privkey, data, padding);
+ }
- else
- throw new NoSuchPaddingException("Unknown padding used for signature");
+ /* ECB is perfectly fine in this special case, since we are using it for
+ the public/private part in the TLS exchange */
+ Cipher signer = null;
+ switch (padding) {
+ case RSA_PKCS1_PADDING:
+ signer = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
+ break;
+ case NO_PADDING:
+ signer = Cipher.getInstance("RSA/ECB/NoPadding");
+ break;
+ case RSA_PKCS1_PSS_PADDING:
+ throw new NoSuchPaddingException("Cannot do PKCS1 PSS padding without also doing the digest");
+ }
signer.init(Cipher.ENCRYPT_MODE, privkey);
@@ -1261,13 +1281,52 @@ public class VpnProfile implements Serializable, Cloneable {
return signed_bytes;
}
- } catch
- (NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException | SignatureException | InvalidAlgorithmParameterException
- e){
- VpnStatus.logError(R.string.error_rsa_sign, e.getClass().toString(), e.getLocalizedMessage());
- return null;
- }
+ } catch
+ (NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException | SignatureException | InvalidAlgorithmParameterException
+ e) {
+ VpnStatus.logError(R.string.error_rsa_sign, e.getClass().toString(), e.getLocalizedMessage());
+ return null;
}
+ }
+
+ private byte[] addPSSPadding(PrivateKey privkey, String digest, byte[] data) throws NoSuchAlgorithmException {
+ /* For < API 23, add padding ourselves */
+ int hashtype = getHashtype(digest);
+
+ MessageDigest msgDigest = MessageDigest.getInstance(digest);
+ byte[] hash = msgDigest.digest(data);
+
+ /* MSBits = (BN_num_bits(rsa->n) - 1) & 0x7; */
+ int numbits = ((RSAPrivateKey) privkey).getModulus().bitLength();
+
+ int MSBits = (numbits - 1) & 0x7;
+
+ return NativeUtils.addRssPssPadding(hashtype, MSBits, numbits/8, hash);
+ }
+
+ private int getHashtype(String digest) throws NoSuchAlgorithmException {
+ int hashtype = 0;
+ switch (digest) {
+ case "SHA1":
+ hashtype = 1;
+ break;
+ case "SHA224":
+ hashtype = 2;
+ break;
+ case "SHA256":
+ hashtype = 3;
+ break;
+ case "SHA384":
+ hashtype = 4;
+ break;
+ case "SHA512":
+ hashtype = 5;
+ break;
+ default:
+ throw new NoSuchAlgorithmException("Unknown digest algorithm: " + digest);
+ }
+ return hashtype;
+ }
private byte[] doDigestSign(PrivateKey privkey, byte[] data, OpenVPNManagement.SignaturePadding padding, String hashalg, String saltlen) throws SignatureException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException {
/* RSA */
@@ -1284,6 +1343,11 @@ public class VpnProfile implements Serializable, Cloneable {
if (!"digest".equals(saltlen))
throw new SignatureException("PSS signing requires saltlen=digest");
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+ data = addPSSPadding(privkey, hashalg, data);
+ return getKeyChainSignedData(data, OpenVPNManagement.SignaturePadding.NO_PADDING, "none", "none", false);
+ }
+
sig = Signature.getInstance(hashalg + "withRSA/PSS");
PSSParameterSpec pssspec = null;
@@ -1308,62 +1372,63 @@ public class VpnProfile implements Serializable, Cloneable {
return sig.sign();
}
- private byte[] processSignJellyBeans (PrivateKey privkey, byte[] data, OpenVPNManagement.SignaturePadding padding){
- try {
- boolean pkcs1padding=false;
- if (padding == OpenVPNManagement.SignaturePadding.RSA_PKCS1_PADDING)
- pkcs1padding = true;
- else if (padding != OpenVPNManagement.SignaturePadding.NO_PADDING)
- throw new IllegalAccessException("Unsuppoirted padding for jelly bean native signing");
+ private byte[] processSignJellyBeans(PrivateKey privkey, byte[] data, OpenVPNManagement.SignaturePadding padding) {
+ try {
+ boolean pkcs1padding = false;
+ if (padding == OpenVPNManagement.SignaturePadding.RSA_PKCS1_PADDING)
+ pkcs1padding = true;
+ else if (padding != OpenVPNManagement.SignaturePadding.NO_PADDING)
+ throw new IllegalAccessException("Unsuppoirted padding for jelly bean native signing");
- Method getKey = privkey.getClass().getSuperclass().getDeclaredMethod("getOpenSSLKey");
- getKey.setAccessible(true);
+ Method getKey = privkey.getClass().getSuperclass().getDeclaredMethod("getOpenSSLKey");
+ getKey.setAccessible(true);
- // Real object type is OpenSSLKey
- Object opensslkey = getKey.invoke(privkey);
+ // Real object type is OpenSSLKey
+ Object opensslkey = getKey.invoke(privkey);
- getKey.setAccessible(false);
+ getKey.setAccessible(false);
- Method getPkeyContext = opensslkey.getClass().getDeclaredMethod("getPkeyContext");
+ Method getPkeyContext = opensslkey.getClass().getDeclaredMethod("getPkeyContext");
- // integer pointer to EVP_pkey
- getPkeyContext.setAccessible(true);
- int pkey = (Integer) getPkeyContext.invoke(opensslkey);
- getPkeyContext.setAccessible(false);
+ // integer pointer to EVP_pkey
+ getPkeyContext.setAccessible(true);
+ int pkey = (Integer) getPkeyContext.invoke(opensslkey);
+ getPkeyContext.setAccessible(false);
- // 112 with TLS 1.2 (172 back with 4.3), 36 with TLS 1.0
- return NativeUtils.rsasign(data, pkey, pkcs1padding);
+ // 112 with TLS 1.2 (172 back with 4.3), 36 with TLS 1.0
+ return NativeUtils.rsasign(data, pkey, pkcs1padding);
- } catch (NoSuchMethodException | InvalidKeyException | InvocationTargetException | IllegalAccessException | IllegalArgumentException e) {
- VpnStatus.logError(R.string.error_rsa_sign, e.getClass().toString(), e.getLocalizedMessage());
- return null;
- }
+ } catch (NoSuchMethodException | InvalidKeyException | InvocationTargetException | IllegalAccessException | IllegalArgumentException e) {
+ VpnStatus.logError(R.string.error_rsa_sign, e.getClass().toString(), e.getLocalizedMessage());
+ return null;
}
+ }
- private boolean usesExtraProxyOptions () {
- if (mUseCustomConfig && mCustomConfigOptions != null && mCustomConfigOptions.contains("http-proxy-option "))
+ private boolean usesExtraProxyOptions() {
+ if (mUseCustomConfig && mCustomConfigOptions != null && mCustomConfigOptions.contains("http-proxy-option "))
+ return true;
+ for (Connection c : mConnections)
+ if (c.usesExtraProxyOptions())
return true;
- for (Connection c : mConnections)
- if (c.usesExtraProxyOptions())
- return true;
- return false;
- }
+ return false;
+ }
- /**
- * The order of elements is important!
- */
- private enum RsaPaddingType {
- NO_PADDING,
- PKCS1_PADDING
- }
+ /**
+ * The order of elements is important!
+ */
+ private enum RsaPaddingType {
+ NO_PADDING,
+ PKCS1_PADDING,
+ RSAPSS_PADDING
+ }
- static class NoCertReturnedException extends Exception {
- public NoCertReturnedException(String msg) {
- super(msg);
- }
+ static class NoCertReturnedException extends Exception {
+ public NoCertReturnedException(String msg) {
+ super(msg);
}
}
+}
diff --git a/main/src/main/java/de/blinkt/openvpn/core/NativeUtils.java b/main/src/main/java/de/blinkt/openvpn/core/NativeUtils.java
index ecfa86ff..470ec6d6 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/NativeUtils.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/NativeUtils.java
@@ -17,8 +17,7 @@ public class NativeUtils {
static native void jniclose(int fdint);
- public static String getNativeAPI()
- {
+ public static String getNativeAPI() {
if (isRoboUnitTest())
return "ROBO";
else
@@ -31,6 +30,20 @@ public class NativeUtils {
public static native String getOpenVPN3GitVersion();
+ static boolean rsspssloaded = false;
+
+ public static byte[] addRssPssPadding(int hashtype, int MSBits, int rsa_size, byte[] from)
+ {
+ if (!rsspssloaded) {
+ rsspssloaded = true;
+ System.loadLibrary("rsapss");
+ }
+
+ return rsapss(hashtype, MSBits, rsa_size, from);
+ }
+
+ private static native byte[] rsapss(int hashtype, int MSBits, int rsa_size, byte[] from);
+
public final static int[] openSSLlengths = {
16, 64, 256, 1024, 1500, 8 * 1024, 16 * 1024
};
@@ -43,6 +56,7 @@ public class NativeUtils {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN)
System.loadLibrary("jbcrypto");
+
if (!BuildConfig.FLAVOR.equals("skeleton")) {
System.loadLibrary("osslspeedtest");
}
diff --git a/main/src/ui/java/de/blinkt/openvpn/fragments/Settings_Connections.kt b/main/src/ui/java/de/blinkt/openvpn/fragments/Settings_Connections.kt
index 75b87157..8ed9d9ef 100644
--- a/main/src/ui/java/de/blinkt/openvpn/fragments/Settings_Connections.kt
+++ b/main/src/ui/java/de/blinkt/openvpn/fragments/Settings_Connections.kt
@@ -50,8 +50,8 @@ class Settings_Connections : Settings_Fragment(), View.OnClickListener {
mRecyclerView.layoutManager =
LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
mRecyclerView.adapter = mConnectionsAdapter
- val fab_button = v.findViewById<View>(R.id.add_new_remote) as ImageButton
- fab_button.setOnClickListener(this)
+ val fab_button = v.findViewById<View>(R.id.add_new_remote) as ImageButton?
+ fab_button?.setOnClickListener(this)
mUseRandomRemote = v.findViewById<View>(R.id.remote_random) as Checkable
mUseRandomRemote.isChecked = mProfile.mRemoteRandom
mConnectionsAdapter.displayWarningIfNoneEnabled()