summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yan Yan <evitayan@google.com> 2020-10-16 23:07:31 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2020-10-16 23:07:31 +0000
commit4cddef19b10bdcebe1e53c42fc2912f19e22e5e4 (patch)
tree777ffab2be381cbd7639ba7d617f5273f36c7a16
parent93a785bd6b25ba2c5f58c5624e68fbdfcb5b519f (diff)
parentcb5aed6518265b15a23b2b552d942f1a3a30cfb6 (diff)
Merge changes from topic "new-ipsec-api" am: a80fb3bbe6 am: cb5aed6518
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1398433 Change-Id: I45530694608909ddbb21d037cc3302130d8140c7
-rw-r--r--api/current.txt4
-rw-r--r--core/java/android/net/IpSecAlgorithm.java178
-rw-r--r--core/res/res/values/config.xml15
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--non-updatable-api/current.txt4
-rw-r--r--tests/net/java/android/net/IpSecAlgorithmTest.java99
6 files changed, 295 insertions, 8 deletions
diff --git a/api/current.txt b/api/current.txt
index 3e64cf3f6bba..22b8c456f655 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -30051,9 +30051,12 @@ package android.net {
method public int describeContents();
method @NonNull public byte[] getKey();
method @NonNull public String getName();
+ method @NonNull public static java.util.Set<java.lang.String> getSupportedAlgorithms();
method public int getTruncationLengthBits();
method public void writeToParcel(android.os.Parcel, int);
+ field public static final String AUTH_AES_XCBC = "xcbc(aes)";
field public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))";
+ field public static final String AUTH_CRYPT_CHACHA20_POLY1305 = "rfc7539esp(chacha20,poly1305)";
field public static final String AUTH_HMAC_MD5 = "hmac(md5)";
field public static final String AUTH_HMAC_SHA1 = "hmac(sha1)";
field public static final String AUTH_HMAC_SHA256 = "hmac(sha256)";
@@ -30061,6 +30064,7 @@ package android.net {
field public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
field @NonNull public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR;
field public static final String CRYPT_AES_CBC = "cbc(aes)";
+ field public static final String CRYPT_AES_CTR = "rfc3686(ctr(aes))";
}
public final class IpSecManager {
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index 38d9883f0003..a4f7b7454bd9 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -17,6 +17,7 @@ package android.net;
import android.annotation.NonNull;
import android.annotation.StringDef;
+import android.content.res.Resources;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,6 +28,12 @@ import com.android.internal.util.HexDump;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
/**
* This class represents a single algorithm that can be used by an {@link IpSecTransform}.
@@ -52,6 +59,27 @@ public final class IpSecAlgorithm implements Parcelable {
public static final String CRYPT_AES_CBC = "cbc(aes)";
/**
+ * AES-CTR Encryption/Ciphering Algorithm.
+ *
+ * <p>Valid lengths for keying material are {160, 224, 288}.
+ *
+ * <p>As per <a href="https://tools.ietf.org/html/rfc3686#section-5.1">RFC3686 (Section
+ * 5.1)</a>, keying material consists of a 128, 192, or 256 bit AES key followed by a 32-bit
+ * nonce. RFC compliance requires that the nonce must be unique per security association.
+ *
+ * <p>This algorithm may be available on the device. Caller MUST check if it is supported before
+ * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
+ * included in the returned algorithm set. The returned algorithm set will not change unless the
+ * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
+ * requested on an unsupported device.
+ *
+ * <p>@see {@link #getSupportedAlgorithms()}
+ */
+ // This algorithm may be available on devices released before Android 12, and is guaranteed
+ // to be available on devices first shipped with Android 12 or later.
+ public static final String CRYPT_AES_CTR = "rfc3686(ctr(aes))";
+
+ /**
* MD5 HMAC Authentication/Integrity Algorithm. <b>This algorithm is not recommended for use in
* new applications and is provided for legacy compatibility with 3gpp infrastructure.</b>
*
@@ -99,6 +127,25 @@ public final class IpSecAlgorithm implements Parcelable {
public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
/**
+ * AES-XCBC Authentication/Integrity Algorithm.
+ *
+ * <p>Keys for this algorithm must be 128 bits in length.
+ *
+ * <p>The only valid truncation length is 96 bits.
+ *
+ * <p>This algorithm may be available on the device. Caller MUST check if it is supported before
+ * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
+ * included in the returned algorithm set. The returned algorithm set will not change unless the
+ * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
+ * requested on an unsupported device.
+ *
+ * <p>@see {@link #getSupportedAlgorithms()}
+ */
+ // This algorithm may be available on devices released before Android 12, and is guaranteed
+ // to be available on devices first shipped with Android 12 or later.
+ public static final String AUTH_AES_XCBC = "xcbc(aes)";
+
+ /**
* AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm.
*
* <p>Valid lengths for keying material are {160, 224, 288}.
@@ -111,19 +158,67 @@ public final class IpSecAlgorithm implements Parcelable {
*/
public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))";
+ /**
+ * ChaCha20-Poly1305 Authentication/Integrity + Encryption/Ciphering Algorithm.
+ *
+ * <p>Keys for this algorithm must be 288 bits in length.
+ *
+ * <p>As per <a href="https://tools.ietf.org/html/rfc7634#section-2">RFC7634 (Section 2)</a>,
+ * keying material consists of a 256 bit key followed by a 32-bit salt. The salt is fixed per
+ * security association.
+ *
+ * <p>The only valid ICV (truncation) length is 128 bits.
+ *
+ * <p>This algorithm may be available on the device. Caller MUST check if it is supported before
+ * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
+ * included in the returned algorithm set. The returned algorithm set will not change unless the
+ * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
+ * requested on an unsupported device.
+ *
+ * <p>@see {@link #getSupportedAlgorithms()}
+ */
+ // This algorithm may be available on devices released before Android 12, and is guaranteed
+ // to be available on devices first shipped with Android 12 or later.
+ public static final String AUTH_CRYPT_CHACHA20_POLY1305 = "rfc7539esp(chacha20,poly1305)";
+
/** @hide */
@StringDef({
CRYPT_AES_CBC,
+ CRYPT_AES_CTR,
AUTH_HMAC_MD5,
AUTH_HMAC_SHA1,
AUTH_HMAC_SHA256,
AUTH_HMAC_SHA384,
AUTH_HMAC_SHA512,
- AUTH_CRYPT_AES_GCM
+ AUTH_AES_XCBC,
+ AUTH_CRYPT_AES_GCM,
+ AUTH_CRYPT_CHACHA20_POLY1305
})
@Retention(RetentionPolicy.SOURCE)
public @interface AlgorithmName {}
+ /** @hide */
+ @VisibleForTesting
+ public static final Map<String, Integer> ALGO_TO_REQUIRED_FIRST_SDK = new HashMap<>();
+
+ static {
+ ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CBC, Build.VERSION_CODES.P);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_MD5, Build.VERSION_CODES.P);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA1, Build.VERSION_CODES.P);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA256, Build.VERSION_CODES.P);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA384, Build.VERSION_CODES.P);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA512, Build.VERSION_CODES.P);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_AES_GCM, Build.VERSION_CODES.P);
+
+ // STOPSHIP: b/170424293 Use Build.VERSION_CODES.S when it is defined
+ ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.R + 1);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.R + 1);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.R + 1);
+ }
+
+ private static final Set<String> ENABLED_ALGOS =
+ Collections.unmodifiableSet(loadAlgos(Resources.getSystem()));
+
private final String mName;
private final byte[] mKey;
private final int mTruncLenBits;
@@ -137,6 +232,7 @@ public final class IpSecAlgorithm implements Parcelable {
*
* @param algorithm name of the algorithm.
* @param key key padded to a multiple of 8 bits.
+ * @throws IllegalArgumentException if algorithm or key length is invalid.
*/
public IpSecAlgorithm(@NonNull @AlgorithmName String algorithm, @NonNull byte[] key) {
this(algorithm, key, 0);
@@ -152,6 +248,7 @@ public final class IpSecAlgorithm implements Parcelable {
* @param algorithm name of the algorithm.
* @param key key padded to a multiple of 8 bits.
* @param truncLenBits number of bits of output hash to use.
+ * @throws IllegalArgumentException if algorithm, key length or truncation length is invalid.
*/
public IpSecAlgorithm(
@NonNull @AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) {
@@ -206,13 +303,59 @@ public final class IpSecAlgorithm implements Parcelable {
}
};
+ /**
+ * Returns supported IPsec algorithms for the current device.
+ *
+ * <p>Some algorithms may not be supported on old devices. Callers MUST check if an algorithm is
+ * supported before using it.
+ */
+ @NonNull
+ public static Set<String> getSupportedAlgorithms() {
+ return ENABLED_ALGOS;
+ }
+
+ /** @hide */
+ @VisibleForTesting
+ public static Set<String> loadAlgos(Resources systemResources) {
+ final Set<String> enabledAlgos = new HashSet<>();
+
+ // Load and validate the optional algorithm resource. Undefined or duplicate algorithms in
+ // the resource are not allowed.
+ final String[] resourceAlgos = systemResources.getStringArray(
+ com.android.internal.R.array.config_optionalIpSecAlgorithms);
+ for (String str : resourceAlgos) {
+ if (!ALGO_TO_REQUIRED_FIRST_SDK.containsKey(str) || !enabledAlgos.add(str)) {
+ // This error should be caught by CTS and never be thrown to API callers
+ throw new IllegalArgumentException("Invalid or repeated algorithm " + str);
+ }
+ }
+
+ for (Entry<String, Integer> entry : ALGO_TO_REQUIRED_FIRST_SDK.entrySet()) {
+ if (Build.VERSION.FIRST_SDK_INT >= entry.getValue()) {
+ enabledAlgos.add(entry.getKey());
+ }
+ }
+
+ return enabledAlgos;
+ }
+
private static void checkValidOrThrow(String name, int keyLen, int truncLen) {
- boolean isValidLen = true;
- boolean isValidTruncLen = true;
+ final boolean isValidLen;
+ final boolean isValidTruncLen;
+
+ if (!getSupportedAlgorithms().contains(name)) {
+ throw new IllegalArgumentException("Unsupported algorithm: " + name);
+ }
- switch(name) {
+ switch (name) {
case CRYPT_AES_CBC:
isValidLen = keyLen == 128 || keyLen == 192 || keyLen == 256;
+ isValidTruncLen = true;
+ break;
+ case CRYPT_AES_CTR:
+ // The keying material for AES-CTR is a key plus a 32-bit salt
+ isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32;
+ isValidTruncLen = true;
break;
case AUTH_HMAC_MD5:
isValidLen = keyLen == 128;
@@ -234,12 +377,22 @@ public final class IpSecAlgorithm implements Parcelable {
isValidLen = keyLen == 512;
isValidTruncLen = truncLen >= 256 && truncLen <= 512;
break;
+ case AUTH_AES_XCBC:
+ isValidLen = keyLen == 128;
+ isValidTruncLen = truncLen == 96;
+ break;
case AUTH_CRYPT_AES_GCM:
// The keying material for GCM is a key plus a 32-bit salt
isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32;
isValidTruncLen = truncLen == 64 || truncLen == 96 || truncLen == 128;
break;
+ case AUTH_CRYPT_CHACHA20_POLY1305:
+ // The keying material for ChaCha20Poly1305 is a key plus a 32-bit salt
+ isValidLen = keyLen == 256 + 32;
+ isValidTruncLen = truncLen == 128;
+ break;
default:
+ // Should never hit here.
throw new IllegalArgumentException("Couldn't find an algorithm: " + name);
}
@@ -260,6 +413,7 @@ public final class IpSecAlgorithm implements Parcelable {
case AUTH_HMAC_SHA256:
case AUTH_HMAC_SHA384:
case AUTH_HMAC_SHA512:
+ case AUTH_AES_XCBC:
return true;
default:
return false;
@@ -268,12 +422,24 @@ public final class IpSecAlgorithm implements Parcelable {
/** @hide */
public boolean isEncryption() {
- return getName().equals(CRYPT_AES_CBC);
+ switch (getName()) {
+ case CRYPT_AES_CBC: // fallthrough
+ case CRYPT_AES_CTR:
+ return true;
+ default:
+ return false;
+ }
}
/** @hide */
public boolean isAead() {
- return getName().equals(AUTH_CRYPT_AES_GCM);
+ switch (getName()) {
+ case AUTH_CRYPT_AES_GCM: // fallthrough
+ case AUTH_CRYPT_CHACHA20_POLY1305:
+ return true;
+ default:
+ return false;
+ }
}
// Because encryption keys are sensitive and userdebug builds are used by large user pools
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index fe49a9cbec64..28e2eb076549 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1663,6 +1663,21 @@
-->
</string-array>
+ <!-- Optional IPsec algorithms enabled by this device, defaulting to empty. OEMs can override
+ it by providing a list of algorithm names in an overlay config.xml file.
+
+ As Android releases new versions, more algorithms are becoming mandatory. Mandatory
+ algorithms will be automatically enabled on the device. Optional algorithms need
+ to be explicitly declared in this resource to be enabled.
+ * SDK level 28 makes the following algorithms mandatory : "cbc(aes)", "hmac(md5)",
+ "hmac(sha1)", "hmac(sha256)", "hmac(sha384)", "hmac(sha512)", "rfc4106(gcm(aes))"
+ * SDK level 30 makes the following algorithms mandatory : "rfc3686(ctr(aes))",
+ "xcbc(aes)", "rfc7539esp(chacha20,poly1305)"
+ -->
+ <string-array name="config_optionalIpSecAlgorithms" translatable="false">
+ <!-- Add algorithm here -->
+ </string-array>
+
<!-- Boolean indicating if current platform supports bluetooth SCO for off call
use cases -->
<bool name="config_bluetooth_sco_off_call">true</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 86d957dc3f18..c51dca17411e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3186,6 +3186,9 @@
<!-- Network Recommendation -->
<java-symbol type="string" name="config_defaultNetworkRecommendationProviderPackage" />
+ <!-- Optional IPsec algorithms -->
+ <java-symbol type="array" name="config_optionalIpSecAlgorithms" />
+
<!-- Whether allow 3rd party apps on internal storage. -->
<java-symbol type="bool" name="config_allow3rdPartyAppOnInternal" />
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index f82aefa6d472..da3d0f7ff059 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -29830,9 +29830,12 @@ package android.net {
method public int describeContents();
method @NonNull public byte[] getKey();
method @NonNull public String getName();
+ method @NonNull public static java.util.Set<java.lang.String> getSupportedAlgorithms();
method public int getTruncationLengthBits();
method public void writeToParcel(android.os.Parcel, int);
+ field public static final String AUTH_AES_XCBC = "xcbc(aes)";
field public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))";
+ field public static final String AUTH_CRYPT_CHACHA20_POLY1305 = "rfc7539esp(chacha20,poly1305)";
field public static final String AUTH_HMAC_MD5 = "hmac(md5)";
field public static final String AUTH_HMAC_SHA1 = "hmac(sha1)";
field public static final String AUTH_HMAC_SHA256 = "hmac(sha256)";
@@ -29840,6 +29843,7 @@ package android.net {
field public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
field @NonNull public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR;
field public static final String CRYPT_AES_CBC = "cbc(aes)";
+ field public static final String CRYPT_AES_CTR = "rfc3686(ctr(aes))";
}
public final class IpSecManager {
diff --git a/tests/net/java/android/net/IpSecAlgorithmTest.java b/tests/net/java/android/net/IpSecAlgorithmTest.java
index 8e9d08c705f3..2e1c29a2e405 100644
--- a/tests/net/java/android/net/IpSecAlgorithmTest.java
+++ b/tests/net/java/android/net/IpSecAlgorithmTest.java
@@ -16,34 +16,50 @@
package android.net;
+import static android.net.IpSecAlgorithm.ALGO_TO_REQUIRED_FIRST_SDK;
+
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import android.content.res.Resources;
+import android.os.Build;
import android.os.Parcel;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.util.CollectionUtils;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.AbstractMap.SimpleEntry;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Random;
+import java.util.Set;
/** Unit tests for {@link IpSecAlgorithm}. */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class IpSecAlgorithmTest {
-
private static final byte[] KEY_MATERIAL;
+ private final Resources mMockResources = mock(Resources.class);
+
static {
KEY_MATERIAL = new byte[128];
new Random().nextBytes(KEY_MATERIAL);
};
+ private static byte[] generateKey(int keyLenInBits) {
+ return Arrays.copyOf(KEY_MATERIAL, keyLenInBits / 8);
+ }
+
@Test
public void testNoTruncLen() throws Exception {
Entry<String, Integer>[] authAndAeadList =
@@ -53,7 +69,7 @@ public class IpSecAlgorithmTest {
new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA256, 256),
new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA384, 384),
new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA512, 512),
- new SimpleEntry<>(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, 224)
+ new SimpleEntry<>(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, 224),
};
// Expect auth and aead algorithms to throw errors if trunclen is omitted.
@@ -70,6 +86,52 @@ public class IpSecAlgorithmTest {
new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, Arrays.copyOf(KEY_MATERIAL, 256 / 8));
}
+ private void checkAuthKeyAndTruncLenValidation(String algoName, int keyLen, int truncLen)
+ throws Exception {
+ new IpSecAlgorithm(algoName, generateKey(keyLen), truncLen);
+
+ try {
+ new IpSecAlgorithm(algoName, generateKey(keyLen));
+ fail("Expected exception on unprovided auth trunclen");
+ } catch (IllegalArgumentException pass) {
+ }
+
+ try {
+ new IpSecAlgorithm(algoName, generateKey(keyLen + 8), truncLen);
+ fail("Invalid key length not validated");
+ } catch (IllegalArgumentException pass) {
+ }
+
+ try {
+ new IpSecAlgorithm(algoName, generateKey(keyLen), truncLen + 1);
+ fail("Invalid truncation length not validated");
+ } catch (IllegalArgumentException pass) {
+ }
+ }
+
+ private void checkCryptKeyLenValidation(String algoName, int keyLen) throws Exception {
+ new IpSecAlgorithm(algoName, generateKey(keyLen));
+
+ try {
+ new IpSecAlgorithm(algoName, generateKey(keyLen + 8));
+ fail("Invalid key length not validated");
+ } catch (IllegalArgumentException pass) {
+ }
+ }
+
+ @Test
+ public void testValidationForAlgosAddedInS() throws Exception {
+ if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.R) {
+ return;
+ }
+
+ for (int len : new int[] {160, 224, 288}) {
+ checkCryptKeyLenValidation(IpSecAlgorithm.CRYPT_AES_CTR, len);
+ }
+ checkAuthKeyAndTruncLenValidation(IpSecAlgorithm.AUTH_AES_XCBC, 128, 96);
+ checkAuthKeyAndTruncLenValidation(IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305, 288, 128);
+ }
+
@Test
public void testTruncLenValidation() throws Exception {
for (int truncLen : new int[] {256, 512}) {
@@ -127,4 +189,37 @@ public class IpSecAlgorithmTest {
assertTrue("Parcel/Unparcel failed!", IpSecAlgorithm.equals(init, fin));
p.recycle();
}
+
+ private static Set<String> getMandatoryAlgos() {
+ return CollectionUtils.filter(
+ ALGO_TO_REQUIRED_FIRST_SDK.keySet(),
+ i -> Build.VERSION.FIRST_SDK_INT >= ALGO_TO_REQUIRED_FIRST_SDK.get(i));
+ }
+
+ private static Set<String> getOptionalAlgos() {
+ return CollectionUtils.filter(
+ ALGO_TO_REQUIRED_FIRST_SDK.keySet(),
+ i -> Build.VERSION.FIRST_SDK_INT < ALGO_TO_REQUIRED_FIRST_SDK.get(i));
+ }
+
+ @Test
+ public void testGetSupportedAlgorithms() throws Exception {
+ assertTrue(IpSecAlgorithm.getSupportedAlgorithms().containsAll(getMandatoryAlgos()));
+ assertTrue(ALGO_TO_REQUIRED_FIRST_SDK.keySet().containsAll(
+ IpSecAlgorithm.getSupportedAlgorithms()));
+ }
+
+ @Test
+ public void testLoadAlgos() throws Exception {
+ final Set<String> optionalAlgoSet = getOptionalAlgos();
+ final String[] optionalAlgos = optionalAlgoSet.toArray(new String[0]);
+
+ doReturn(optionalAlgos).when(mMockResources)
+ .getStringArray(com.android.internal.R.array.config_optionalIpSecAlgorithms);
+
+ final Set<String> enabledAlgos = new HashSet<>(IpSecAlgorithm.loadAlgos(mMockResources));
+ final Set<String> expectedAlgos = ALGO_TO_REQUIRED_FIRST_SDK.keySet();
+
+ assertEquals(expectedAlgos, enabledAlgos);
+ }
}