Merge changes from topic "sdk-level"
* changes:
Add methods to return supported algorithms
Support getting IPsec algorithm name for a given IKE algorithm ID
diff --git a/Android.bp b/Android.bp
index 3ac8f3e..c5adaf4 100644
--- a/Android.bp
+++ b/Android.bp
@@ -85,8 +85,10 @@
"com.android.ipsec",
"test_com.android.ipsec",
],
- static_libs: ["bouncycastle_ike_digests"],
- sdk_version: "core_current",
+ static_libs: [
+ "bouncycastle_ike_digests",
+ "modules-utils-build",],
+ sdk_version: "module_current",
}
java_library {
diff --git a/jarjar-rules-shared.txt b/jarjar-rules-shared.txt
index 1548696..7d3bea4 100644
--- a/jarjar-rules-shared.txt
+++ b/jarjar-rules-shared.txt
@@ -3,4 +3,5 @@
rule android.telephony.Annotation* com.android.internal.net.eap.telephony.Annotation@1
rule com.android.server.vcn.util.PersistableBundleUtils* com.android.internal.net.vcn.util.PersistableBundleUtils@1
rule com.android.internal.util.** com.android.internal.net.ipsec.ike.utils.@1
+rule com.android.modules.utils.** com.android.internal.net.utils.@1
rule org.bouncycastle.** com.android.internal.net.org.bouncycastle.@1
diff --git a/src/java/android/net/ipsec/ike/ChildSaProposal.java b/src/java/android/net/ipsec/ike/ChildSaProposal.java
index 1e3af9a..212c5d4 100644
--- a/src/java/android/net/ipsec/ike/ChildSaProposal.java
+++ b/src/java/android/net/ipsec/ike/ChildSaProposal.java
@@ -20,19 +20,25 @@
import android.annotation.NonNull;
import android.annotation.SuppressLint;
+import android.net.IpSecAlgorithm;
import android.os.PersistableBundle;
+import android.util.ArraySet;
+import com.android.internal.net.ipsec.ike.crypto.IkeCipher;
+import com.android.internal.net.ipsec.ike.crypto.IkeMacIntegrity;
import com.android.internal.net.ipsec.ike.message.IkePayload;
import com.android.internal.net.ipsec.ike.message.IkeSaPayload.DhGroupTransform;
import com.android.internal.net.ipsec.ike.message.IkeSaPayload.EncryptionTransform;
import com.android.internal.net.ipsec.ike.message.IkeSaPayload.EsnTransform;
import com.android.internal.net.ipsec.ike.message.IkeSaPayload.IntegrityTransform;
import com.android.internal.net.ipsec.ike.message.IkeSaPayload.Transform;
+import com.android.modules.utils.build.SdkLevel;
import com.android.server.vcn.util.PersistableBundleUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
* ChildSaProposal represents a proposed configuration to negotiate a Child SA.
@@ -46,6 +52,25 @@
* Protocol Version 2 (IKEv2)</a>
*/
public final class ChildSaProposal extends SaProposal {
+ // Before SDK S, there is no API in IpSecAlgorithm to retrieve supported algorithms. Thus hard
+ // coded these algorithms here.
+ private static final Set<Integer> SUPPORTED_IPSEC_ENCRYPTION_BEFORE_SDK_S;
+ private static final Set<Integer> SUPPORTED_IPSEC_INTEGRITY_BEFORE_SDK_S;
+
+ static {
+ SUPPORTED_IPSEC_ENCRYPTION_BEFORE_SDK_S = new ArraySet<>();
+ SUPPORTED_IPSEC_ENCRYPTION_BEFORE_SDK_S.add(ENCRYPTION_ALGORITHM_AES_CBC);
+ SUPPORTED_IPSEC_ENCRYPTION_BEFORE_SDK_S.add(ENCRYPTION_ALGORITHM_AES_GCM_8);
+ SUPPORTED_IPSEC_ENCRYPTION_BEFORE_SDK_S.add(ENCRYPTION_ALGORITHM_AES_GCM_12);
+ SUPPORTED_IPSEC_ENCRYPTION_BEFORE_SDK_S.add(ENCRYPTION_ALGORITHM_AES_GCM_16);
+
+ SUPPORTED_IPSEC_INTEGRITY_BEFORE_SDK_S = new ArraySet<>();
+ SUPPORTED_IPSEC_INTEGRITY_BEFORE_SDK_S.add(INTEGRITY_ALGORITHM_HMAC_SHA1_96);
+ SUPPORTED_IPSEC_INTEGRITY_BEFORE_SDK_S.add(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128);
+ SUPPORTED_IPSEC_INTEGRITY_BEFORE_SDK_S.add(INTEGRITY_ALGORITHM_HMAC_SHA2_384_192);
+ SUPPORTED_IPSEC_INTEGRITY_BEFORE_SDK_S.add(INTEGRITY_ALGORITHM_HMAC_SHA2_512_256);
+ }
+
private static final String ESN_KEY = "mEsns";
private final EsnTransform[] mEsns;
@@ -139,6 +164,61 @@
}
/**
+ * Returns supported encryption algorithms for Child SA proposal negotiation.
+ *
+ * <p>Some algorithms may not be supported on old devices. Callers MUST check if an algorithm is
+ * supported before using it.
+ *
+ * @hide
+ */
+ @NonNull
+ public static Set<Integer> getSupportedEncryptionAlgorithms() {
+ if (SdkLevel.isAtLeastS()) {
+ Set<Integer> algoIds = new ArraySet<>();
+ for (int i = 0; i < SUPPORTED_ENCRYPTION_ALGO_TO_STR.size(); i++) {
+ int ikeAlgoId = SUPPORTED_ENCRYPTION_ALGO_TO_STR.keyAt(i);
+ String ipSecAlgoName = IkeCipher.getIpSecAlgorithmName(ikeAlgoId);
+ if (IpSecAlgorithm.getSupportedAlgorithms().contains(ipSecAlgoName)) {
+ algoIds.add(ikeAlgoId);
+ }
+ }
+ return algoIds;
+ } else {
+ return SUPPORTED_IPSEC_ENCRYPTION_BEFORE_SDK_S;
+ }
+ }
+
+ /**
+ * Returns supported integrity algorithms for Child SA proposal negotiation.
+ *
+ * <p>Some algorithms may not be supported on old devices. Callers MUST check if an algorithm is
+ * supported before using it.
+ *
+ * @hide
+ */
+ @NonNull
+ public static Set<Integer> getSupportedIntegrityAlgorithms() {
+ Set<Integer> algoIds = new ArraySet<>();
+
+ // Although IpSecAlgorithm does not support INTEGRITY_ALGORITHM_NONE, IKE supports
+ // negotiating it and won't build IpSecAlgorithm with it.
+ algoIds.add(INTEGRITY_ALGORITHM_NONE);
+
+ if (SdkLevel.isAtLeastS()) {
+ for (int i = 0; i < SUPPORTED_INTEGRITY_ALGO_TO_STR.size(); i++) {
+ int ikeAlgoId = SUPPORTED_INTEGRITY_ALGO_TO_STR.keyAt(i);
+ String ipSecAlgoName = IkeMacIntegrity.getIpSecAlgorithmName(ikeAlgoId);
+ if (IpSecAlgorithm.getSupportedAlgorithms().contains(ipSecAlgoName)) {
+ algoIds.add(ikeAlgoId);
+ }
+ }
+ } else {
+ algoIds.addAll(SUPPORTED_IPSEC_INTEGRITY_BEFORE_SDK_S);
+ }
+ return algoIds;
+ }
+
+ /**
* Gets all ESN policies.
*
* @hide
diff --git a/src/java/android/net/ipsec/ike/IkeSaProposal.java b/src/java/android/net/ipsec/ike/IkeSaProposal.java
index 7b93963..277cdd5 100644
--- a/src/java/android/net/ipsec/ike/IkeSaProposal.java
+++ b/src/java/android/net/ipsec/ike/IkeSaProposal.java
@@ -132,6 +132,36 @@
}
/**
+ * Returns supported encryption algorithms for IKE SA proposal negotiation.
+ *
+ * @hide
+ */
+ @NonNull
+ public static Set<Integer> getSupportedEncryptionAlgorithms() {
+ return getKeySet(SUPPORTED_ENCRYPTION_ALGO_TO_STR);
+ }
+
+ /**
+ * Returns supported integrity algorithms for IKE SA proposal negotiation.
+ *
+ * @hide
+ */
+ @NonNull
+ public static Set<Integer> getSupportedIntegrityAlgorithms() {
+ return getKeySet(SUPPORTED_INTEGRITY_ALGO_TO_STR);
+ }
+
+ /**
+ * Returns supported pseudorandom functions for IKE SA proposal negotiation.
+ *
+ * @hide
+ */
+ @NonNull
+ public static Set<Integer> getSupportedPseudorandomFunctions() {
+ return getKeySet(SUPPORTED_PRF_TO_STR);
+ }
+
+ /**
* Gets all proposed Pseudorandom Functions
*
* @return A list of the IANA-defined IDs for the proposed Pseudorandom Functions
diff --git a/src/java/android/net/ipsec/ike/SaProposal.java b/src/java/android/net/ipsec/ike/SaProposal.java
index 2669d68..4cc3338 100644
--- a/src/java/android/net/ipsec/ike/SaProposal.java
+++ b/src/java/android/net/ipsec/ike/SaProposal.java
@@ -34,10 +34,12 @@
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
* SaProposal represents a proposed configuration to negotiate an IKE or Child SA.
@@ -91,7 +93,8 @@
*/
public static final int ENCRYPTION_ALGORITHM_CHACHA20_POLY1305 = 28;
- private static final SparseArray<String> SUPPORTED_ENCRYPTION_ALGO_TO_STR;
+ /** @hide */
+ protected static final SparseArray<String> SUPPORTED_ENCRYPTION_ALGO_TO_STR;
static {
SUPPORTED_ENCRYPTION_ALGO_TO_STR = new SparseArray<>();
@@ -141,7 +144,8 @@
/** HMAC-SHA2-384 Pseudorandom Function. */
public static final int PSEUDORANDOM_FUNCTION_SHA2_512 = 7;
- private static final SparseArray<String> SUPPORTED_PRF_TO_STR;
+ /** @hide */
+ protected static final SparseArray<String> SUPPORTED_PRF_TO_STR;
static {
SUPPORTED_PRF_TO_STR = new SparseArray<>();
@@ -177,7 +181,8 @@
/** HMAC-SHA512 Authentication/Integrity Algorithm with 256-bit truncation. */
public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 = 14;
- private static final SparseArray<String> SUPPORTED_INTEGRITY_ALGO_TO_STR;
+ /** @hide */
+ protected static final SparseArray<String> SUPPORTED_INTEGRITY_ALGO_TO_STR;
static {
SUPPORTED_INTEGRITY_ALGO_TO_STR = new SparseArray<>();
@@ -586,48 +591,24 @@
&& Arrays.equals(mDhGroups, other.mDhGroups);
}
- /**
- * Check if the provided algorithm is a supported encryption algorithm.
- *
- * @param algorithm IKE standard encryption algorithm id.
- * @return true if the provided algorithm is a supported encryption algorithm.
- * @hide
- */
- public static boolean isSupportedEncryptionAlgorithm(@EncryptionAlgorithm int algorithm) {
- return SUPPORTED_ENCRYPTION_ALGO_TO_STR.get(algorithm) != null;
+ /** @hide */
+ protected static Set<Integer> getKeySet(SparseArray array) {
+ Set<Integer> result = new HashSet<>();
+ for (int i = 0; i < array.size(); i++) {
+ result.add(array.keyAt(i));
+ }
+
+ return result;
}
/**
- * Check if the provided algorithm is a supported pseudorandom function.
+ * Returns supported DH groups for IKE and Child SA proposal negotiation.
*
- * @param algorithm IKE standard pseudorandom function id.
- * @return true if the provided algorithm is a supported pseudorandom function.
* @hide
*/
- public static boolean isSupportedPseudorandomFunction(@PseudorandomFunction int algorithm) {
- return SUPPORTED_PRF_TO_STR.get(algorithm) != null;
- }
-
- /**
- * Check if the provided algorithm is a supported integrity algorithm.
- *
- * @param algorithm IKE standard integrity algorithm id.
- * @return true if the provided algorithm is a supported integrity algorithm.
- * @hide
- */
- public static boolean isSupportedIntegrityAlgorithm(@IntegrityAlgorithm int algorithm) {
- return SUPPORTED_INTEGRITY_ALGO_TO_STR.get(algorithm) != null;
- }
-
- /**
- * Check if the provided group number is for a supported Diffie-Hellman Group.
- *
- * @param dhGroup IKE standard DH Group id.
- * @return true if the provided number is for a supported Diffie-Hellman Group.
- * @hide
- */
- public static boolean isSupportedDhGroup(@DhGroup int dhGroup) {
- return SUPPORTED_DH_GROUP_TO_STR.get(dhGroup) != null;
+ @NonNull
+ public static Set<Integer> getSupportedDhGroups() {
+ return getKeySet(SUPPORTED_DH_GROUP_TO_STR);
}
/**
@@ -636,7 +617,7 @@
* @hide
*/
public static String getEncryptionAlgorithmString(int algorithm) {
- if (isSupportedEncryptionAlgorithm(algorithm)) {
+ if (SUPPORTED_ENCRYPTION_ALGO_TO_STR.contains(algorithm)) {
return SUPPORTED_ENCRYPTION_ALGO_TO_STR.get(algorithm);
}
return "ENC_Unknown_" + algorithm;
@@ -648,7 +629,7 @@
* @hide
*/
public static String getPseudorandomFunctionString(int algorithm) {
- if (isSupportedPseudorandomFunction(algorithm)) {
+ if (SUPPORTED_PRF_TO_STR.contains(algorithm)) {
return SUPPORTED_PRF_TO_STR.get(algorithm);
}
return "PRF_Unknown_" + algorithm;
@@ -660,7 +641,7 @@
* @hide
*/
public static String getIntegrityAlgorithmString(int algorithm) {
- if (isSupportedIntegrityAlgorithm(algorithm)) {
+ if (SUPPORTED_PRF_TO_STR.contains(algorithm)) {
return SUPPORTED_INTEGRITY_ALGO_TO_STR.get(algorithm);
}
return "AUTH_Unknown_" + algorithm;
@@ -672,7 +653,7 @@
* @hide
*/
public static String getDhGroupString(int dhGroup) {
- if (isSupportedDhGroup(dhGroup)) {
+ if (SUPPORTED_DH_GROUP_TO_STR.contains(dhGroup)) {
return SUPPORTED_DH_GROUP_TO_STR.get(dhGroup);
}
return "DH_Unknown_" + dhGroup;
diff --git a/src/java/com/android/internal/net/ipsec/ike/crypto/IkeCipher.java b/src/java/com/android/internal/net/ipsec/ike/crypto/IkeCipher.java
index d0e55af..23220be 100644
--- a/src/java/com/android/internal/net/ipsec/ike/crypto/IkeCipher.java
+++ b/src/java/com/android/internal/net/ipsec/ike/crypto/IkeCipher.java
@@ -16,8 +16,10 @@
package com.android.internal.net.ipsec.ike.crypto;
+import android.annotation.Nullable;
import android.net.IpSecAlgorithm;
import android.net.ipsec.ike.SaProposal;
+import android.util.SparseArray;
import com.android.internal.net.ipsec.ike.message.IkeSaPayload.EncryptionTransform;
@@ -52,6 +54,26 @@
protected static final int SALT_LEN_NOT_INCLUDED = 0;
protected static final int BLOCK_SIZE_NOT_SPECIFIED = 0;
+ // Map IKE algorithm numbers to IPsec algorithm names
+ private static final SparseArray<String> IKE_ALGO_TO_IPSEC_ALGO;
+
+ static {
+ IKE_ALGO_TO_IPSEC_ALGO = new SparseArray<>();
+ IKE_ALGO_TO_IPSEC_ALGO.put(
+ SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, IpSecAlgorithm.CRYPT_AES_CBC);
+ IKE_ALGO_TO_IPSEC_ALGO.put(
+ SaProposal.ENCRYPTION_ALGORITHM_AES_CTR, IpSecAlgorithm.CRYPT_AES_CTR);
+ IKE_ALGO_TO_IPSEC_ALGO.put(
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8, IpSecAlgorithm.AUTH_CRYPT_AES_GCM);
+ IKE_ALGO_TO_IPSEC_ALGO.put(
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12, IpSecAlgorithm.AUTH_CRYPT_AES_GCM);
+ IKE_ALGO_TO_IPSEC_ALGO.put(
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16, IpSecAlgorithm.AUTH_CRYPT_AES_GCM);
+ IKE_ALGO_TO_IPSEC_ALGO.put(
+ SaProposal.ENCRYPTION_ALGORITHM_CHACHA20_POLY1305,
+ IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305);
+ }
+
private final boolean mIsAead;
private final int mIvLen;
private final int mBlockSize;
@@ -188,6 +210,19 @@
}
/**
+ * Returns the IPsec algorithm name defined in {@link IpSecAlgorithm} given the IKE algorithm
+ * ID.
+ *
+ * <p>Returns null if there is no corresponding IPsec algorithm given the IKE algorithm ID.
+ */
+ @Nullable
+ public static String getIpSecAlgorithmName(int ikeAlgoId) {
+ return IKE_ALGO_TO_IPSEC_ALGO.get(ikeAlgoId);
+ }
+
+ protected abstract IpSecAlgorithm buildIpSecAlgorithmWithKeyImpl(byte[] key);
+
+ /**
* Build IpSecAlgorithm from this IkeCipher.
*
* <p>Build IpSecAlgorithm that represents the same encryption algorithm with this IkeCipher
@@ -196,7 +231,14 @@
* @param key the encryption key in byte array.
* @return the IpSecAlgorithm.
*/
- public abstract IpSecAlgorithm buildIpSecAlgorithmWithKey(byte[] key);
+ public IpSecAlgorithm buildIpSecAlgorithmWithKey(byte[] key) {
+ validateKeyLenOrThrow(key);
+ if (getIpSecAlgorithmName(getAlgorithmId()) == null) {
+ throw new IllegalStateException(
+ "Unsupported algorithm " + getAlgorithmId() + " in IPsec");
+ }
+ return buildIpSecAlgorithmWithKeyImpl(key);
+ }
/**
* Returns algorithm type as a String.
diff --git a/src/java/com/android/internal/net/ipsec/ike/crypto/IkeCombinedModeCipher.java b/src/java/com/android/internal/net/ipsec/ike/crypto/IkeCombinedModeCipher.java
index 3a27752..a59e566 100644
--- a/src/java/com/android/internal/net/ipsec/ike/crypto/IkeCombinedModeCipher.java
+++ b/src/java/com/android/internal/net/ipsec/ike/crypto/IkeCombinedModeCipher.java
@@ -202,21 +202,7 @@
}
@Override
- public IpSecAlgorithm buildIpSecAlgorithmWithKey(byte[] key) {
- validateKeyLenOrThrow(key);
- switch (getAlgorithmId()) {
- case SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8:
- // Fall through
- case SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12:
- // Fall through
- case SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16:
- return new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, key, mChecksumLen * 8);
- case SaProposal.ENCRYPTION_ALGORITHM_CHACHA20_POLY1305:
- return new IpSecAlgorithm(
- IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305, key, mChecksumLen * 8);
- default:
- throw new IllegalArgumentException(
- "Unrecognized Encryption Algorithm ID: " + getAlgorithmId());
- }
+ protected IpSecAlgorithm buildIpSecAlgorithmWithKeyImpl(byte[] key) {
+ return new IpSecAlgorithm(getIpSecAlgorithmName(getAlgorithmId()), key, mChecksumLen * 8);
}
}
diff --git a/src/java/com/android/internal/net/ipsec/ike/crypto/IkeMacIntegrity.java b/src/java/com/android/internal/net/ipsec/ike/crypto/IkeMacIntegrity.java
index cb2aca7..16a5309 100644
--- a/src/java/com/android/internal/net/ipsec/ike/crypto/IkeMacIntegrity.java
+++ b/src/java/com/android/internal/net/ipsec/ike/crypto/IkeMacIntegrity.java
@@ -18,8 +18,10 @@
import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96;
+import android.annotation.Nullable;
import android.net.IpSecAlgorithm;
import android.net.ipsec.ike.SaProposal;
+import android.util.SparseArray;
import com.android.internal.net.ipsec.ike.message.IkeSaPayload.IntegrityTransform;
@@ -39,7 +41,23 @@
* Exchange Protocol Version 2 (IKEv2)</a>
*/
public class IkeMacIntegrity extends IkeMac {
- // STOPSHIP: b/130190639 Catch unchecked exceptions, notify users and close the IKE session.
+ // Map IKE algorithm numbers to IPsec algorithm names
+ private static final SparseArray<String> IKE_ALGO_TO_IPSEC_ALGO;
+
+ static {
+ IKE_ALGO_TO_IPSEC_ALGO = new SparseArray<>();
+ IKE_ALGO_TO_IPSEC_ALGO.put(
+ SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96, IpSecAlgorithm.AUTH_HMAC_SHA1);
+ IKE_ALGO_TO_IPSEC_ALGO.put(
+ SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96, IpSecAlgorithm.AUTH_AES_XCBC);
+ IKE_ALGO_TO_IPSEC_ALGO.put(
+ SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128, IpSecAlgorithm.AUTH_HMAC_SHA256);
+ IKE_ALGO_TO_IPSEC_ALGO.put(
+ SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192, IpSecAlgorithm.AUTH_HMAC_SHA384);
+ IKE_ALGO_TO_IPSEC_ALGO.put(
+ SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256, IpSecAlgorithm.AUTH_HMAC_SHA512);
+ }
+
private final int mChecksumLength;
private IkeMacIntegrity(
@@ -149,6 +167,17 @@
}
/**
+ * Returns the IPsec algorithm name defined in {@link IpSecAlgorithm} given the IKE algorithm
+ * ID.
+ *
+ * <p>Returns null if there is no corresponding IPsec algorithm given the IKE algorithm ID.
+ */
+ @Nullable
+ public static String getIpSecAlgorithmName(int ikeAlgoId) {
+ return IKE_ALGO_TO_IPSEC_ALGO.get(ikeAlgoId);
+ }
+
+ /**
* Build IpSecAlgorithm from this IkeMacIntegrity.
*
* <p>Build IpSecAlgorithm that represents the same integrity algorithm with this
@@ -165,25 +194,12 @@
+ " Received key with length of : "
+ key.length);
}
-
- switch (getAlgorithmId()) {
- case SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96:
- return new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, key, mChecksumLength * 8);
- case SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96:
- return new IpSecAlgorithm(IpSecAlgorithm.AUTH_AES_XCBC, key, mChecksumLength * 8);
- case SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128:
- return new IpSecAlgorithm(
- IpSecAlgorithm.AUTH_HMAC_SHA256, key, mChecksumLength * 8);
- case SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192:
- return new IpSecAlgorithm(
- IpSecAlgorithm.AUTH_HMAC_SHA384, key, mChecksumLength * 8);
- case SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256:
- return new IpSecAlgorithm(
- IpSecAlgorithm.AUTH_HMAC_SHA512, key, mChecksumLength * 8);
- default:
- throw new IllegalArgumentException(
- "Unrecognized Integrity Algorithm ID: " + getAlgorithmId());
+ if (getIpSecAlgorithmName(getAlgorithmId()) == null) {
+ throw new IllegalStateException(
+ "Unsupported algorithm " + getAlgorithmId() + " in IPsec");
}
+ return new IpSecAlgorithm(
+ getIpSecAlgorithmName(getAlgorithmId()), key, mChecksumLength * 8);
}
/**
diff --git a/src/java/com/android/internal/net/ipsec/ike/crypto/IkeNormalModeCipher.java b/src/java/com/android/internal/net/ipsec/ike/crypto/IkeNormalModeCipher.java
index f932e14..7fc18ed 100644
--- a/src/java/com/android/internal/net/ipsec/ike/crypto/IkeNormalModeCipher.java
+++ b/src/java/com/android/internal/net/ipsec/ike/crypto/IkeNormalModeCipher.java
@@ -130,21 +130,8 @@
}
@Override
- public IpSecAlgorithm buildIpSecAlgorithmWithKey(byte[] key) {
- validateKeyLenOrThrow(key);
-
- switch (getAlgorithmId()) {
- case SaProposal.ENCRYPTION_ALGORITHM_3DES:
- // TODO: Consider supporting 3DES in IpSecTransform.
- throw new UnsupportedOperationException("Do not support 3Des encryption.");
- case SaProposal.ENCRYPTION_ALGORITHM_AES_CBC:
- return new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, key);
- case SaProposal.ENCRYPTION_ALGORITHM_AES_CTR:
- return new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CTR, key);
- default:
- throw new IllegalArgumentException(
- "Unrecognized Encryption Algorithm ID: " + getAlgorithmId());
- }
+ protected IpSecAlgorithm buildIpSecAlgorithmWithKeyImpl(byte[] key) {
+ return new IpSecAlgorithm(getIpSecAlgorithmName(getAlgorithmId()), key);
}
private static byte[] concatenateByteArray(byte[] left, byte[] right) {
diff --git a/src/java/com/android/internal/net/ipsec/ike/message/IkeSaPayload.java b/src/java/com/android/internal/net/ipsec/ike/message/IkeSaPayload.java
index 277d248..7f3529a 100644
--- a/src/java/com/android/internal/net/ipsec/ike/message/IkeSaPayload.java
+++ b/src/java/com/android/internal/net/ipsec/ike/message/IkeSaPayload.java
@@ -1224,7 +1224,8 @@
@Override
protected boolean isSupportedTransformId(int id) {
- return SaProposal.isSupportedEncryptionAlgorithm(id);
+ return IkeSaProposal.getSupportedEncryptionAlgorithms().contains(id)
+ || ChildSaProposal.getSupportedEncryptionAlgorithms().contains(id);
}
@Override
@@ -1374,7 +1375,7 @@
@Override
protected boolean isSupportedTransformId(int id) {
- return SaProposal.isSupportedPseudorandomFunction(id);
+ return IkeSaProposal.getSupportedPseudorandomFunctions().contains(id);
}
@Override
@@ -1455,7 +1456,8 @@
@Override
protected boolean isSupportedTransformId(int id) {
- return SaProposal.isSupportedIntegrityAlgorithm(id);
+ return IkeSaProposal.getSupportedIntegrityAlgorithms().contains(id)
+ || ChildSaProposal.getSupportedIntegrityAlgorithms().contains(id);
}
@Override
@@ -1536,7 +1538,7 @@
@Override
protected boolean isSupportedTransformId(int id) {
- return SaProposal.isSupportedDhGroup(id);
+ return SaProposal.getSupportedDhGroups().contains(id);
}
@Override
diff --git a/tests/iketests/src/java/android/net/ipsec/ike/SaProposalTest.java b/tests/iketests/src/java/android/net/ipsec/ike/SaProposalTest.java
index 89d7343..1e91d5e 100644
--- a/tests/iketests/src/java/android/net/ipsec/ike/SaProposalTest.java
+++ b/tests/iketests/src/java/android/net/ipsec/ike/SaProposalTest.java
@@ -17,32 +17,58 @@
package android.net.ipsec.ike;
import static android.net.ipsec.ike.SaProposal.DH_GROUP_1024_BIT_MODP;
+import static android.net.ipsec.ike.SaProposal.DH_GROUP_1536_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_NONE;
+import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_3DES;
+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_16;
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_XCBC_96;
+import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_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_384_192;
+import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256;
import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_NONE;
import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_128;
import static android.net.ipsec.ike.SaProposal.KEY_LEN_UNUSED;
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_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 static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+import android.net.IpSecAlgorithm;
import android.os.PersistableBundle;
+import com.android.internal.net.ipsec.ike.crypto.IkeCipher;
+import com.android.internal.net.ipsec.ike.crypto.IkeMacIntegrity;
import com.android.internal.net.ipsec.ike.message.IkePayload;
import com.android.internal.net.ipsec.ike.message.IkeSaPayload.DhGroupTransform;
import com.android.internal.net.ipsec.ike.message.IkeSaPayload.EncryptionTransform;
import com.android.internal.net.ipsec.ike.message.IkeSaPayload.IntegrityTransform;
import com.android.internal.net.ipsec.ike.message.IkeSaPayload.PrfTransform;
import com.android.internal.net.ipsec.ike.message.IkeSaPayload.Transform;
+import com.android.internal.net.utils.build.SdkLevel;
import org.junit.Test;
+import java.util.HashSet;
+import java.util.Set;
+
public final class SaProposalTest {
private final EncryptionTransform mEncryption3DesTransform;
private final EncryptionTransform mEncryptionAesGcm8Transform;
@@ -52,6 +78,23 @@
private final PrfTransform mPrfAes128XCbcTransform;
private final DhGroupTransform mDhGroup1024Transform;
+ private static final Set<Integer> SUPPORTED_IPSEC_ENCRYPTION_BEFORE_SDK_S;
+ private static final Set<Integer> SUPPORTED_IPSEC_INTEGRITY_BEFORE_SDK_S;
+
+ static {
+ SUPPORTED_IPSEC_ENCRYPTION_BEFORE_SDK_S = new HashSet<>();
+ SUPPORTED_IPSEC_ENCRYPTION_BEFORE_SDK_S.add(ENCRYPTION_ALGORITHM_AES_CBC);
+ SUPPORTED_IPSEC_ENCRYPTION_BEFORE_SDK_S.add(ENCRYPTION_ALGORITHM_AES_GCM_8);
+ SUPPORTED_IPSEC_ENCRYPTION_BEFORE_SDK_S.add(ENCRYPTION_ALGORITHM_AES_GCM_12);
+ SUPPORTED_IPSEC_ENCRYPTION_BEFORE_SDK_S.add(ENCRYPTION_ALGORITHM_AES_GCM_16);
+
+ SUPPORTED_IPSEC_INTEGRITY_BEFORE_SDK_S = new HashSet<>();
+ SUPPORTED_IPSEC_INTEGRITY_BEFORE_SDK_S.add(INTEGRITY_ALGORITHM_HMAC_SHA1_96);
+ SUPPORTED_IPSEC_INTEGRITY_BEFORE_SDK_S.add(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128);
+ SUPPORTED_IPSEC_INTEGRITY_BEFORE_SDK_S.add(INTEGRITY_ALGORITHM_HMAC_SHA2_384_192);
+ SUPPORTED_IPSEC_INTEGRITY_BEFORE_SDK_S.add(INTEGRITY_ALGORITHM_HMAC_SHA2_512_256);
+ }
+
public SaProposalTest() {
mEncryption3DesTransform =
new EncryptionTransform(SaProposal.ENCRYPTION_ALGORITHM_3DES, KEY_LEN_UNUSED);
@@ -387,4 +430,112 @@
assertTrue(respProposal.isNegotiatedFrom(reqProposal));
}
+
+ @Test
+ public void testGetChildSupportedEncryptionAlgorithmsBeforeSdkS() {
+ assumeFalse(SdkLevel.isAtLeastS());
+
+ assertEquals(
+ SUPPORTED_IPSEC_ENCRYPTION_BEFORE_SDK_S,
+ ChildSaProposal.getSupportedEncryptionAlgorithms());
+ }
+
+ @Test
+ public void testGetChildSupportedEncryptionAlgorithmsAtLeastSdkS() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ // It is not feasible to have a hard coded expected supported algorithm set because
+ // supported IPsec algorithms vary on different devices
+ for (int ikeAlgoId : ChildSaProposal.getSupportedEncryptionAlgorithms()) {
+ String ipSecAlgoName = IkeCipher.getIpSecAlgorithmName(ikeAlgoId);
+ assertTrue(IpSecAlgorithm.getSupportedAlgorithms().contains(ipSecAlgoName));
+ }
+
+ assertTrue(
+ ChildSaProposal.getSupportedEncryptionAlgorithms()
+ .containsAll(SUPPORTED_IPSEC_ENCRYPTION_BEFORE_SDK_S));
+ }
+
+ @Test
+ public void testGetChildSupportedIntegrityAlgorithmsBeforeSdkS() {
+ assumeFalse(SdkLevel.isAtLeastS());
+
+ assertEquals(
+ SUPPORTED_IPSEC_INTEGRITY_BEFORE_SDK_S,
+ ChildSaProposal.getSupportedIntegrityAlgorithms());
+ }
+
+ @Test
+ public void testGetChildSupportedIntegrityAlgorithmsAtLeastSdkS() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ // It is not feasible to have a hard coded expected supported algorithm set because
+ // supported IPsec algorithms vary on different devices
+ for (int ikeAlgoId : ChildSaProposal.getSupportedIntegrityAlgorithms()) {
+ if (ikeAlgoId != INTEGRITY_ALGORITHM_NONE) {
+ String ipSecAlgoName = IkeMacIntegrity.getIpSecAlgorithmName(ikeAlgoId);
+ assertTrue(IpSecAlgorithm.getSupportedAlgorithms().contains(ipSecAlgoName));
+ }
+ }
+
+ assertTrue(
+ ChildSaProposal.getSupportedIntegrityAlgorithms()
+ .containsAll(SUPPORTED_IPSEC_INTEGRITY_BEFORE_SDK_S));
+ }
+
+ @Test
+ public void testGetIkeSupportedEncryptionAlgorithms() {
+ HashSet<Integer> expectedSet = new HashSet<>();
+ expectedSet = new HashSet<>();
+ expectedSet.add(ENCRYPTION_ALGORITHM_3DES);
+ expectedSet.add(ENCRYPTION_ALGORITHM_AES_CBC);
+ expectedSet.add(ENCRYPTION_ALGORITHM_AES_CTR);
+ expectedSet.add(ENCRYPTION_ALGORITHM_AES_GCM_8);
+ expectedSet.add(ENCRYPTION_ALGORITHM_AES_GCM_12);
+ expectedSet.add(ENCRYPTION_ALGORITHM_AES_GCM_16);
+ expectedSet.add(ENCRYPTION_ALGORITHM_CHACHA20_POLY1305);
+
+ assertEquals(expectedSet, IkeSaProposal.getSupportedEncryptionAlgorithms());
+ }
+
+ @Test
+ public void testGetIkeSupportedIntegrityAlgorithms() {
+ HashSet<Integer> expectedSet = new HashSet<>();
+ expectedSet = new HashSet<>();
+ expectedSet.add(INTEGRITY_ALGORITHM_NONE);
+ expectedSet.add(INTEGRITY_ALGORITHM_HMAC_SHA1_96);
+ expectedSet.add(INTEGRITY_ALGORITHM_AES_XCBC_96);
+ expectedSet.add(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128);
+ expectedSet.add(INTEGRITY_ALGORITHM_HMAC_SHA2_384_192);
+ expectedSet.add(INTEGRITY_ALGORITHM_HMAC_SHA2_512_256);
+
+ assertEquals(expectedSet, IkeSaProposal.getSupportedIntegrityAlgorithms());
+ }
+
+ @Test
+ public void testGetIkeSupportedPrfs() {
+ HashSet<Integer> expectedSet = new HashSet<>();
+ expectedSet = new HashSet<>();
+ expectedSet.add(PSEUDORANDOM_FUNCTION_HMAC_SHA1);
+ expectedSet.add(PSEUDORANDOM_FUNCTION_AES128_XCBC);
+ expectedSet.add(PSEUDORANDOM_FUNCTION_SHA2_256);
+ expectedSet.add(PSEUDORANDOM_FUNCTION_SHA2_384);
+ expectedSet.add(PSEUDORANDOM_FUNCTION_SHA2_512);
+
+ assertEquals(expectedSet, IkeSaProposal.getSupportedPseudorandomFunctions());
+ }
+
+ @Test
+ public void testGetSupportedDhGroups() {
+ HashSet<Integer> expectedSet = new HashSet<>();
+ expectedSet = new HashSet<>();
+ expectedSet.add(DH_GROUP_NONE);
+ expectedSet.add(DH_GROUP_1024_BIT_MODP);
+ expectedSet.add(DH_GROUP_1536_BIT_MODP);
+ expectedSet.add(DH_GROUP_2048_BIT_MODP);
+ expectedSet.add(DH_GROUP_3072_BIT_MODP);
+ expectedSet.add(DH_GROUP_4096_BIT_MODP);
+
+ assertEquals(expectedSet, IkeSaProposal.getSupportedDhGroups());
+ }
}
diff --git a/tests/iketests/src/java/com/android/internal/net/ipsec/ike/crypto/IkeMacIntegrityTest.java b/tests/iketests/src/java/com/android/internal/net/ipsec/ike/crypto/IkeMacIntegrityTest.java
index fc322bb..946d844 100644
--- a/tests/iketests/src/java/com/android/internal/net/ipsec/ike/crypto/IkeMacIntegrityTest.java
+++ b/tests/iketests/src/java/com/android/internal/net/ipsec/ike/crypto/IkeMacIntegrityTest.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -185,4 +186,27 @@
}
}
}
+
+ @Test
+ public void testGetIpSecAlgorithmName() throws Exception {
+ assertEquals(
+ IpSecAlgorithm.AUTH_HMAC_SHA1,
+ IkeMacIntegrity.getIpSecAlgorithmName(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96));
+ assertEquals(
+ IpSecAlgorithm.AUTH_AES_XCBC,
+ IkeMacIntegrity.getIpSecAlgorithmName(SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96));
+ assertEquals(
+ IpSecAlgorithm.AUTH_HMAC_SHA256,
+ IkeMacIntegrity.getIpSecAlgorithmName(
+ SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128));
+ assertEquals(
+ IpSecAlgorithm.AUTH_HMAC_SHA384,
+ IkeMacIntegrity.getIpSecAlgorithmName(
+ SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192));
+ assertEquals(
+ IpSecAlgorithm.AUTH_HMAC_SHA512,
+ IkeMacIntegrity.getIpSecAlgorithmName(
+ SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256));
+ assertNull(IkeMacIntegrity.getIpSecAlgorithmName(SaProposal.INTEGRITY_ALGORITHM_NONE));
+ }
}
diff --git a/tests/iketests/src/java/com/android/internal/net/ipsec/ike/crypto/IkeNormalModeCipherTest.java b/tests/iketests/src/java/com/android/internal/net/ipsec/ike/crypto/IkeNormalModeCipherTest.java
index 9837ac7..15d0092 100644
--- a/tests/iketests/src/java/com/android/internal/net/ipsec/ike/crypto/IkeNormalModeCipherTest.java
+++ b/tests/iketests/src/java/com/android/internal/net/ipsec/ike/crypto/IkeNormalModeCipherTest.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -184,7 +185,7 @@
}
@Test
- public void buildIpSecAlgorithmWithInvalidKey() throws Exception {
+ public void testBuildIpSecAlgorithmWithInvalidKey() throws Exception {
byte[] encryptionKey = TestUtils.hexStringToByteArray(ENCR_KEY_FROM_INIT_TO_RESP + "00");
try {
@@ -195,4 +196,27 @@
}
}
+
+ @Test
+ public void testGetIpSecAlgorithmName() throws Exception {
+ assertEquals(
+ IpSecAlgorithm.CRYPT_AES_CBC,
+ IkeCipher.getIpSecAlgorithmName(SaProposal.ENCRYPTION_ALGORITHM_AES_CBC));
+ assertEquals(
+ IpSecAlgorithm.CRYPT_AES_CTR,
+ IkeCipher.getIpSecAlgorithmName(SaProposal.ENCRYPTION_ALGORITHM_AES_CTR));
+ assertEquals(
+ IpSecAlgorithm.AUTH_CRYPT_AES_GCM,
+ IkeCipher.getIpSecAlgorithmName(SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8));
+ assertEquals(
+ IpSecAlgorithm.AUTH_CRYPT_AES_GCM,
+ IkeCipher.getIpSecAlgorithmName(SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12));
+ assertEquals(
+ IpSecAlgorithm.AUTH_CRYPT_AES_GCM,
+ IkeCipher.getIpSecAlgorithmName(SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16));
+ assertEquals(
+ IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305,
+ IkeCipher.getIpSecAlgorithmName(SaProposal.ENCRYPTION_ALGORITHM_CHACHA20_POLY1305));
+ assertNull(IkeCipher.getIpSecAlgorithmName(SaProposal.ENCRYPTION_ALGORITHM_3DES));
+ }
}