Merge changes I1de322c9,Id0983d4b into sc-dev
* changes: Improve IKEv2/IPsec VPN by proposing more IPsec algorithms Improve IKEv2/IPsec VPN by proposing more IKE algorithms
This commit is contained in:
committed by
Android (Google) Code Review
commit
453acbbf29
@@ -16,6 +16,16 @@
|
|||||||
|
|
||||||
package android.net;
|
package android.net;
|
||||||
|
|
||||||
|
import static android.net.IpSecAlgorithm.AUTH_AES_CMAC;
|
||||||
|
import static android.net.IpSecAlgorithm.AUTH_AES_XCBC;
|
||||||
|
import static android.net.IpSecAlgorithm.AUTH_CRYPT_AES_GCM;
|
||||||
|
import static android.net.IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305;
|
||||||
|
import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA256;
|
||||||
|
import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA384;
|
||||||
|
import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512;
|
||||||
|
import static android.net.IpSecAlgorithm.CRYPT_AES_CBC;
|
||||||
|
import static android.net.IpSecAlgorithm.CRYPT_AES_CTR;
|
||||||
|
|
||||||
import static com.android.internal.annotations.VisibleForTesting.Visibility;
|
import static com.android.internal.annotations.VisibleForTesting.Visibility;
|
||||||
import static com.android.internal.util.Preconditions.checkStringNotEmpty;
|
import static com.android.internal.util.Preconditions.checkStringNotEmpty;
|
||||||
import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU;
|
import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU;
|
||||||
@@ -70,13 +80,28 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
|
|||||||
private static final String EMPTY_CERT = "";
|
private static final String EMPTY_CERT = "";
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public static final List<String> DEFAULT_ALGORITHMS =
|
public static final List<String> DEFAULT_ALGORITHMS;
|
||||||
Collections.unmodifiableList(Arrays.asList(
|
|
||||||
IpSecAlgorithm.CRYPT_AES_CBC,
|
private static void addAlgorithmIfSupported(List<String> algorithms, String ipSecAlgoName) {
|
||||||
IpSecAlgorithm.AUTH_HMAC_SHA256,
|
if (IpSecAlgorithm.getSupportedAlgorithms().contains(ipSecAlgoName)) {
|
||||||
IpSecAlgorithm.AUTH_HMAC_SHA384,
|
algorithms.add(ipSecAlgoName);
|
||||||
IpSecAlgorithm.AUTH_HMAC_SHA512,
|
}
|
||||||
IpSecAlgorithm.AUTH_CRYPT_AES_GCM));
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
final List<String> algorithms = new ArrayList<>();
|
||||||
|
addAlgorithmIfSupported(algorithms, CRYPT_AES_CBC);
|
||||||
|
addAlgorithmIfSupported(algorithms, CRYPT_AES_CTR);
|
||||||
|
addAlgorithmIfSupported(algorithms, AUTH_HMAC_SHA256);
|
||||||
|
addAlgorithmIfSupported(algorithms, AUTH_HMAC_SHA384);
|
||||||
|
addAlgorithmIfSupported(algorithms, AUTH_HMAC_SHA512);
|
||||||
|
addAlgorithmIfSupported(algorithms, AUTH_AES_XCBC);
|
||||||
|
addAlgorithmIfSupported(algorithms, AUTH_AES_CMAC);
|
||||||
|
addAlgorithmIfSupported(algorithms, AUTH_CRYPT_AES_GCM);
|
||||||
|
addAlgorithmIfSupported(algorithms, AUTH_CRYPT_CHACHA20_POLY1305);
|
||||||
|
|
||||||
|
DEFAULT_ALGORITHMS = Collections.unmodifiableList(algorithms);
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull private final String mServerAddr;
|
@NonNull private final String mServerAddr;
|
||||||
@NonNull private final String mUserIdentity;
|
@NonNull private final String mUserIdentity;
|
||||||
@@ -195,8 +220,6 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
|
|||||||
* @param allowedAlgorithms The list to be validated
|
* @param allowedAlgorithms The list to be validated
|
||||||
*/
|
*/
|
||||||
private static void validateAllowedAlgorithms(@NonNull List<String> algorithmNames) {
|
private static void validateAllowedAlgorithms(@NonNull List<String> algorithmNames) {
|
||||||
VpnProfile.validateAllowedAlgorithms(algorithmNames);
|
|
||||||
|
|
||||||
// First, make sure no insecure algorithms were proposed.
|
// First, make sure no insecure algorithms were proposed.
|
||||||
if (algorithmNames.contains(IpSecAlgorithm.AUTH_HMAC_MD5)
|
if (algorithmNames.contains(IpSecAlgorithm.AUTH_HMAC_MD5)
|
||||||
|| algorithmNames.contains(IpSecAlgorithm.AUTH_HMAC_SHA1)) {
|
|| algorithmNames.contains(IpSecAlgorithm.AUTH_HMAC_SHA1)) {
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ import android.text.TextUtils;
|
|||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.net.module.util.ProxyUtils;
|
import com.android.net.module.util.ProxyUtils;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -74,6 +77,9 @@ public final class VpnProfile implements Cloneable, Parcelable {
|
|||||||
|
|
||||||
private static final String ENCODED_NULL_PROXY_INFO = "\0\0\0\0";
|
private static final String ENCODED_NULL_PROXY_INFO = "\0\0\0\0";
|
||||||
|
|
||||||
|
/** Default URL encoding. */
|
||||||
|
private static final String DEFAULT_ENCODING = StandardCharsets.UTF_8.name();
|
||||||
|
|
||||||
// Entity fields.
|
// Entity fields.
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public final String key; // -1
|
public final String key; // -1
|
||||||
@@ -129,9 +135,6 @@ public final class VpnProfile implements Cloneable, Parcelable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of allowable algorithms.
|
* The list of allowable algorithms.
|
||||||
*
|
|
||||||
* <p>This list is validated in the setter to ensure that encoding characters (list, value
|
|
||||||
* delimiters) are not present in the algorithm names. See {@link #validateAllowedAlgorithms()}
|
|
||||||
*/
|
*/
|
||||||
private List<String> mAllowedAlgorithms = new ArrayList<>(); // 19
|
private List<String> mAllowedAlgorithms = new ArrayList<>(); // 19
|
||||||
public boolean isBypassable = false; // 20
|
public boolean isBypassable = false; // 20
|
||||||
@@ -196,11 +199,8 @@ public final class VpnProfile implements Cloneable, Parcelable {
|
|||||||
*
|
*
|
||||||
* @param allowedAlgorithms the list of allowable algorithms, as listed in {@link
|
* @param allowedAlgorithms the list of allowable algorithms, as listed in {@link
|
||||||
* IpSecAlgorithm}.
|
* IpSecAlgorithm}.
|
||||||
* @throws IllegalArgumentException if any delimiters are used in algorithm names. See {@link
|
|
||||||
* #VALUE_DELIMITER} and {@link LIST_DELIMITER}.
|
|
||||||
*/
|
*/
|
||||||
public void setAllowedAlgorithms(List<String> allowedAlgorithms) {
|
public void setAllowedAlgorithms(List<String> allowedAlgorithms) {
|
||||||
validateAllowedAlgorithms(allowedAlgorithms);
|
|
||||||
mAllowedAlgorithms = allowedAlgorithms;
|
mAllowedAlgorithms = allowedAlgorithms;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,7 +297,11 @@ public final class VpnProfile implements Cloneable, Parcelable {
|
|||||||
|
|
||||||
// Either all must be present, or none must be.
|
// Either all must be present, or none must be.
|
||||||
if (values.length >= 24) {
|
if (values.length >= 24) {
|
||||||
profile.mAllowedAlgorithms = Arrays.asList(values[19].split(LIST_DELIMITER));
|
profile.mAllowedAlgorithms = new ArrayList<>();
|
||||||
|
for (String algo : Arrays.asList(values[19].split(LIST_DELIMITER))) {
|
||||||
|
profile.mAllowedAlgorithms.add(URLDecoder.decode(algo, DEFAULT_ENCODING));
|
||||||
|
}
|
||||||
|
|
||||||
profile.isBypassable = Boolean.parseBoolean(values[20]);
|
profile.isBypassable = Boolean.parseBoolean(values[20]);
|
||||||
profile.isMetered = Boolean.parseBoolean(values[21]);
|
profile.isMetered = Boolean.parseBoolean(values[21]);
|
||||||
profile.maxMtu = Integer.parseInt(values[22]);
|
profile.maxMtu = Integer.parseInt(values[22]);
|
||||||
@@ -348,7 +352,19 @@ public final class VpnProfile implements Cloneable, Parcelable {
|
|||||||
builder.append(ENCODED_NULL_PROXY_INFO);
|
builder.append(ENCODED_NULL_PROXY_INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.append(VALUE_DELIMITER).append(String.join(LIST_DELIMITER, mAllowedAlgorithms));
|
final List<String> encodedAlgoNames = new ArrayList<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (String algo : mAllowedAlgorithms) {
|
||||||
|
encodedAlgoNames.add(URLEncoder.encode(algo, DEFAULT_ENCODING));
|
||||||
|
}
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
// Unexpected error
|
||||||
|
throw new IllegalStateException("Failed to encode algorithms.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append(VALUE_DELIMITER).append(String.join(LIST_DELIMITER, encodedAlgoNames));
|
||||||
|
|
||||||
builder.append(VALUE_DELIMITER).append(isBypassable);
|
builder.append(VALUE_DELIMITER).append(isBypassable);
|
||||||
builder.append(VALUE_DELIMITER).append(isMetered);
|
builder.append(VALUE_DELIMITER).append(isMetered);
|
||||||
builder.append(VALUE_DELIMITER).append(maxMtu);
|
builder.append(VALUE_DELIMITER).append(maxMtu);
|
||||||
@@ -425,20 +441,6 @@ public final class VpnProfile implements Cloneable, Parcelable {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates that the provided list of algorithms does not contain illegal characters.
|
|
||||||
*
|
|
||||||
* @param allowedAlgorithms The list to be validated
|
|
||||||
*/
|
|
||||||
public static void validateAllowedAlgorithms(List<String> allowedAlgorithms) {
|
|
||||||
for (final String alg : allowedAlgorithms) {
|
|
||||||
if (alg.contains(VALUE_DELIMITER) || alg.contains(LIST_DELIMITER)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Algorithm contained illegal ('\0' or ',') character");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Generates a hashcode over the VpnProfile. */
|
/** Generates a hashcode over the VpnProfile. */
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ import androidx.test.filters.SmallTest;
|
|||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
import com.android.internal.net.VpnProfile;
|
import com.android.internal.net.VpnProfile;
|
||||||
import com.android.net.module.util.ProxyUtils;
|
|
||||||
import com.android.internal.org.bouncycastle.x509.X509V1CertificateGenerator;
|
import com.android.internal.org.bouncycastle.x509.X509V1CertificateGenerator;
|
||||||
|
import com.android.net.module.util.ProxyUtils;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -170,7 +170,10 @@ public class Ikev2VpnProfileTest {
|
|||||||
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
||||||
builder.setAuthPsk(PSK_BYTES);
|
builder.setAuthPsk(PSK_BYTES);
|
||||||
|
|
||||||
List<String> allowedAlgorithms = Arrays.asList(IpSecAlgorithm.AUTH_CRYPT_AES_GCM);
|
List<String> allowedAlgorithms =
|
||||||
|
Arrays.asList(
|
||||||
|
IpSecAlgorithm.AUTH_CRYPT_AES_GCM,
|
||||||
|
IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305);
|
||||||
builder.setAllowedAlgorithms(allowedAlgorithms);
|
builder.setAllowedAlgorithms(allowedAlgorithms);
|
||||||
|
|
||||||
final Ikev2VpnProfile profile = builder.build();
|
final Ikev2VpnProfile profile = builder.build();
|
||||||
@@ -183,7 +186,12 @@ public class Ikev2VpnProfileTest {
|
|||||||
builder.setAuthPsk(PSK_BYTES);
|
builder.setAuthPsk(PSK_BYTES);
|
||||||
|
|
||||||
List<String> allowedAlgorithms =
|
List<String> allowedAlgorithms =
|
||||||
Arrays.asList(IpSecAlgorithm.AUTH_HMAC_SHA512, IpSecAlgorithm.CRYPT_AES_CBC);
|
Arrays.asList(
|
||||||
|
IpSecAlgorithm.AUTH_HMAC_SHA512,
|
||||||
|
IpSecAlgorithm.AUTH_AES_XCBC,
|
||||||
|
IpSecAlgorithm.AUTH_AES_CMAC,
|
||||||
|
IpSecAlgorithm.CRYPT_AES_CBC,
|
||||||
|
IpSecAlgorithm.CRYPT_AES_CTR);
|
||||||
builder.setAllowedAlgorithms(allowedAlgorithms);
|
builder.setAllowedAlgorithms(allowedAlgorithms);
|
||||||
|
|
||||||
final Ikev2VpnProfile profile = builder.build();
|
final Ikev2VpnProfile profile = builder.build();
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import static org.junit.Assert.assertFalse;
|
|||||||
import static org.junit.Assert.assertNotEquals;
|
import static org.junit.Assert.assertNotEquals;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
import android.net.IpSecAlgorithm;
|
import android.net.IpSecAlgorithm;
|
||||||
|
|
||||||
@@ -97,6 +96,7 @@ public class VpnProfileTest {
|
|||||||
p.setAllowedAlgorithms(
|
p.setAllowedAlgorithms(
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
IpSecAlgorithm.AUTH_CRYPT_AES_GCM,
|
IpSecAlgorithm.AUTH_CRYPT_AES_GCM,
|
||||||
|
IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305,
|
||||||
IpSecAlgorithm.AUTH_HMAC_SHA512,
|
IpSecAlgorithm.AUTH_HMAC_SHA512,
|
||||||
IpSecAlgorithm.CRYPT_AES_CBC));
|
IpSecAlgorithm.CRYPT_AES_CBC));
|
||||||
p.isBypassable = true;
|
p.isBypassable = true;
|
||||||
@@ -125,30 +125,6 @@ public class VpnProfileTest {
|
|||||||
assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 23);
|
assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 23);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSetInvalidAlgorithmValueDelimiter() {
|
|
||||||
final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
|
|
||||||
|
|
||||||
try {
|
|
||||||
profile.setAllowedAlgorithms(
|
|
||||||
Arrays.asList("test" + VpnProfile.VALUE_DELIMITER + "test"));
|
|
||||||
fail("Expected failure due to value separator in algorithm name");
|
|
||||||
} catch (IllegalArgumentException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSetInvalidAlgorithmListDelimiter() {
|
|
||||||
final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
|
|
||||||
|
|
||||||
try {
|
|
||||||
profile.setAllowedAlgorithms(
|
|
||||||
Arrays.asList("test" + VpnProfile.LIST_DELIMITER + "test"));
|
|
||||||
fail("Expected failure due to value separator in algorithm name");
|
|
||||||
} catch (IllegalArgumentException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeDecode() {
|
public void testEncodeDecode() {
|
||||||
final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
|
final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
|
||||||
|
|||||||
@@ -18,10 +18,16 @@ package com.android.server.connectivity;
|
|||||||
|
|
||||||
import static android.net.ConnectivityManager.NetworkCallback;
|
import static android.net.ConnectivityManager.NetworkCallback;
|
||||||
import static android.net.ipsec.ike.SaProposal.DH_GROUP_2048_BIT_MODP;
|
import static android.net.ipsec.ike.SaProposal.DH_GROUP_2048_BIT_MODP;
|
||||||
|
import static android.net.ipsec.ike.SaProposal.DH_GROUP_3072_BIT_MODP;
|
||||||
|
import static android.net.ipsec.ike.SaProposal.DH_GROUP_4096_BIT_MODP;
|
||||||
|
import static android.net.ipsec.ike.SaProposal.DH_GROUP_CURVE_25519;
|
||||||
import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_CBC;
|
import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_CBC;
|
||||||
|
import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_CTR;
|
||||||
import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12;
|
import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12;
|
||||||
import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16;
|
import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16;
|
||||||
import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8;
|
import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8;
|
||||||
|
import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_CHACHA20_POLY1305;
|
||||||
|
import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_AES_CMAC_96;
|
||||||
import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96;
|
import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96;
|
||||||
import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128;
|
import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128;
|
||||||
import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192;
|
import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192;
|
||||||
@@ -29,8 +35,13 @@ import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512
|
|||||||
import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_128;
|
import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_128;
|
||||||
import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_192;
|
import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_192;
|
||||||
import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_256;
|
import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_256;
|
||||||
|
import static android.net.ipsec.ike.SaProposal.KEY_LEN_UNUSED;
|
||||||
|
import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_AES128_CMAC;
|
||||||
import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC;
|
import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC;
|
||||||
import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1;
|
import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1;
|
||||||
|
import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_SHA2_256;
|
||||||
|
import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_SHA2_384;
|
||||||
|
import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_SHA2_512;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -84,12 +95,6 @@ import java.util.List;
|
|||||||
public class VpnIkev2Utils {
|
public class VpnIkev2Utils {
|
||||||
private static final String TAG = VpnIkev2Utils.class.getSimpleName();
|
private static final String TAG = VpnIkev2Utils.class.getSimpleName();
|
||||||
|
|
||||||
// TODO: Use IKE library exposed constants when @SystemApi is updated.
|
|
||||||
/** IANA-defined 3072 group for use in IKEv2 */
|
|
||||||
private static final int DH_GROUP_3072_BIT_MODP = 15;
|
|
||||||
/** IANA-defined 4096 group for use in IKEv2 */
|
|
||||||
private static final int DH_GROUP_4096_BIT_MODP = 16;
|
|
||||||
|
|
||||||
static IkeSessionParams buildIkeSessionParams(
|
static IkeSessionParams buildIkeSessionParams(
|
||||||
@NonNull Context context, @NonNull Ikev2VpnProfile profile, @NonNull Network network) {
|
@NonNull Context context, @NonNull Ikev2VpnProfile profile, @NonNull Network network) {
|
||||||
final IkeIdentification localId = parseIkeIdentification(profile.getUserIdentity());
|
final IkeIdentification localId = parseIkeIdentification(profile.getUserIdentity());
|
||||||
@@ -154,12 +159,14 @@ public class VpnIkev2Utils {
|
|||||||
// TODO: Add ability to filter this when IKEv2 API is made Public API
|
// TODO: Add ability to filter this when IKEv2 API is made Public API
|
||||||
final List<IkeSaProposal> proposals = new ArrayList<>();
|
final List<IkeSaProposal> proposals = new ArrayList<>();
|
||||||
|
|
||||||
// Encryption Algorithms: Currently only AES_CBC is supported.
|
|
||||||
final IkeSaProposal.Builder normalModeBuilder = new IkeSaProposal.Builder();
|
final IkeSaProposal.Builder normalModeBuilder = new IkeSaProposal.Builder();
|
||||||
|
|
||||||
// Currently only AES_CBC is supported.
|
// Add normal mode encryption algorithms
|
||||||
|
normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CTR, KEY_LEN_AES_256);
|
||||||
normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_256);
|
normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_256);
|
||||||
|
normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CTR, KEY_LEN_AES_192);
|
||||||
normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_192);
|
normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_192);
|
||||||
|
normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CTR, KEY_LEN_AES_128);
|
||||||
normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_128);
|
normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_128);
|
||||||
|
|
||||||
// Authentication/Integrity Algorithms
|
// Authentication/Integrity Algorithms
|
||||||
@@ -167,9 +174,11 @@ public class VpnIkev2Utils {
|
|||||||
normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_384_192);
|
normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_384_192);
|
||||||
normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128);
|
normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128);
|
||||||
normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_AES_XCBC_96);
|
normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_AES_XCBC_96);
|
||||||
|
normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_AES_CMAC_96);
|
||||||
|
|
||||||
// Add AEAD options
|
// Add AEAD options
|
||||||
final IkeSaProposal.Builder aeadBuilder = new IkeSaProposal.Builder();
|
final IkeSaProposal.Builder aeadBuilder = new IkeSaProposal.Builder();
|
||||||
|
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_CHACHA20_POLY1305, KEY_LEN_UNUSED);
|
||||||
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_256);
|
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_256);
|
||||||
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_256);
|
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_256);
|
||||||
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_256);
|
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_256);
|
||||||
@@ -183,9 +192,17 @@ public class VpnIkev2Utils {
|
|||||||
// Add dh, prf for both builders
|
// Add dh, prf for both builders
|
||||||
for (final IkeSaProposal.Builder builder : Arrays.asList(normalModeBuilder, aeadBuilder)) {
|
for (final IkeSaProposal.Builder builder : Arrays.asList(normalModeBuilder, aeadBuilder)) {
|
||||||
builder.addDhGroup(DH_GROUP_4096_BIT_MODP);
|
builder.addDhGroup(DH_GROUP_4096_BIT_MODP);
|
||||||
|
|
||||||
|
// Curve25519 has the same security strength as MODP 3072 and cost less bytes
|
||||||
|
builder.addDhGroup(DH_GROUP_CURVE_25519);
|
||||||
|
|
||||||
builder.addDhGroup(DH_GROUP_3072_BIT_MODP);
|
builder.addDhGroup(DH_GROUP_3072_BIT_MODP);
|
||||||
builder.addDhGroup(DH_GROUP_2048_BIT_MODP);
|
builder.addDhGroup(DH_GROUP_2048_BIT_MODP);
|
||||||
|
builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_SHA2_512);
|
||||||
|
builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_SHA2_384);
|
||||||
|
builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_SHA2_256);
|
||||||
builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_AES128_XCBC);
|
builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_AES128_XCBC);
|
||||||
|
builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_AES128_CMAC);
|
||||||
builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_HMAC_SHA1);
|
builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_HMAC_SHA1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,15 +215,23 @@ public class VpnIkev2Utils {
|
|||||||
private static List<ChildSaProposal> getChildSaProposals(List<String> allowedAlgorithms) {
|
private static List<ChildSaProposal> getChildSaProposals(List<String> allowedAlgorithms) {
|
||||||
final List<ChildSaProposal> proposals = new ArrayList<>();
|
final List<ChildSaProposal> proposals = new ArrayList<>();
|
||||||
|
|
||||||
|
final List<Integer> aesKeyLenOptions =
|
||||||
|
Arrays.asList(KEY_LEN_AES_256, KEY_LEN_AES_192, KEY_LEN_AES_128);
|
||||||
|
|
||||||
// Add non-AEAD options
|
// Add non-AEAD options
|
||||||
if (Ikev2VpnProfile.hasNormalModeAlgorithms(allowedAlgorithms)) {
|
if (Ikev2VpnProfile.hasNormalModeAlgorithms(allowedAlgorithms)) {
|
||||||
final ChildSaProposal.Builder normalModeBuilder = new ChildSaProposal.Builder();
|
final ChildSaProposal.Builder normalModeBuilder = new ChildSaProposal.Builder();
|
||||||
|
|
||||||
// Encryption Algorithms:
|
// Encryption Algorithms:
|
||||||
// AES-CBC is currently the only supported encryption algorithm.
|
// AES-CBC and AES_CTR are currently the only supported encryption algorithms.
|
||||||
normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_256);
|
for (int len : aesKeyLenOptions) {
|
||||||
normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_192);
|
if (allowedAlgorithms.contains(IpSecAlgorithm.CRYPT_AES_CTR)) {
|
||||||
normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_128);
|
normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CTR, len);
|
||||||
|
}
|
||||||
|
if (allowedAlgorithms.contains(IpSecAlgorithm.CRYPT_AES_CBC)) {
|
||||||
|
normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Authentication/Integrity Algorithms:
|
// Authentication/Integrity Algorithms:
|
||||||
// Guaranteed by Ikev2VpnProfile constructor to contain at least one of these.
|
// Guaranteed by Ikev2VpnProfile constructor to contain at least one of these.
|
||||||
@@ -219,6 +244,12 @@ public class VpnIkev2Utils {
|
|||||||
if (allowedAlgorithms.contains(IpSecAlgorithm.AUTH_HMAC_SHA256)) {
|
if (allowedAlgorithms.contains(IpSecAlgorithm.AUTH_HMAC_SHA256)) {
|
||||||
normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128);
|
normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128);
|
||||||
}
|
}
|
||||||
|
if (allowedAlgorithms.contains(IpSecAlgorithm.AUTH_AES_XCBC)) {
|
||||||
|
normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_AES_XCBC_96);
|
||||||
|
}
|
||||||
|
if (allowedAlgorithms.contains(IpSecAlgorithm.AUTH_AES_CMAC)) {
|
||||||
|
normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_AES_CMAC_96);
|
||||||
|
}
|
||||||
|
|
||||||
ChildSaProposal proposal = normalModeBuilder.build();
|
ChildSaProposal proposal = normalModeBuilder.build();
|
||||||
if (proposal.getIntegrityAlgorithms().isEmpty()) {
|
if (proposal.getIntegrityAlgorithms().isEmpty()) {
|
||||||
@@ -233,16 +264,27 @@ public class VpnIkev2Utils {
|
|||||||
if (Ikev2VpnProfile.hasAeadAlgorithms(allowedAlgorithms)) {
|
if (Ikev2VpnProfile.hasAeadAlgorithms(allowedAlgorithms)) {
|
||||||
final ChildSaProposal.Builder aeadBuilder = new ChildSaProposal.Builder();
|
final ChildSaProposal.Builder aeadBuilder = new ChildSaProposal.Builder();
|
||||||
|
|
||||||
// AES-GCM is currently the only supported AEAD algorithm
|
if (allowedAlgorithms.contains(IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305)) {
|
||||||
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_256);
|
aeadBuilder.addEncryptionAlgorithm(
|
||||||
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_256);
|
ENCRYPTION_ALGORITHM_CHACHA20_POLY1305, KEY_LEN_UNUSED);
|
||||||
|
}
|
||||||
|
if (allowedAlgorithms.contains(IpSecAlgorithm.AUTH_CRYPT_AES_GCM)) {
|
||||||
|
aeadBuilder.addEncryptionAlgorithm(
|
||||||
|
ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_256);
|
||||||
|
aeadBuilder.addEncryptionAlgorithm(
|
||||||
|
ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_256);
|
||||||
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_256);
|
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_256);
|
||||||
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_192);
|
aeadBuilder.addEncryptionAlgorithm(
|
||||||
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_192);
|
ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_192);
|
||||||
|
aeadBuilder.addEncryptionAlgorithm(
|
||||||
|
ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_192);
|
||||||
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_192);
|
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_192);
|
||||||
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_128);
|
aeadBuilder.addEncryptionAlgorithm(
|
||||||
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_128);
|
ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_128);
|
||||||
|
aeadBuilder.addEncryptionAlgorithm(
|
||||||
|
ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_128);
|
||||||
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_128);
|
aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_128);
|
||||||
|
}
|
||||||
|
|
||||||
proposals.add(aeadBuilder.build());
|
proposals.add(aeadBuilder.build());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user