diff options
author | Xin Li <delphij@google.com> | 2024-03-06 09:30:11 -0800 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2024-03-06 18:58:26 -0800 |
commit | 5f57fe08e747fcd1a412eb5c267d24ed72f57d2f (patch) | |
tree | 836b3110194878c625c0eb0e931c331cfba14d80 | |
parent | 792a63cc312aebbbb05d0dec01d71b0e003ecf7f (diff) | |
parent | 22c3b71cea50647ef284d96927f5cf6397e92b82 (diff) | |
download | Iwlan-5f57fe08e747fcd1a412eb5c267d24ed72f57d2f.tar.gz |
Merge Android 14 QPR2 to AOSP main
Bug: 319669529
Merged-In: I08485045eb01b813ca311adc8795f8d06a103c2f
Change-Id: I7d53385b8b55b492d6a0e838eafeb25f9f5522a2
-rw-r--r-- | flags/main.aconfig | 18 | ||||
-rw-r--r-- | src/com/google/android/iwlan/epdg/EpdgChildSaProposal.java | 79 | ||||
-rw-r--r-- | src/com/google/android/iwlan/epdg/EpdgIkeSaProposal.java | 117 | ||||
-rw-r--r-- | src/com/google/android/iwlan/epdg/EpdgSaProposal.java | 329 | ||||
-rw-r--r-- | src/com/google/android/iwlan/epdg/EpdgSelector.java | 3 | ||||
-rw-r--r-- | src/com/google/android/iwlan/epdg/EpdgTunnelManager.java | 289 | ||||
-rw-r--r-- | test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java | 204 |
7 files changed, 1037 insertions, 2 deletions
diff --git a/flags/main.aconfig b/flags/main.aconfig index 795ffbd..57b0527 100644 --- a/flags/main.aconfig +++ b/flags/main.aconfig @@ -8,6 +8,24 @@ flag { bug: "278788983" } flag { + name: "aead_algos_enabled" + namespace: "iwlan_telephony" + description: "Add AES_GCM algorithm support in IWLAN." + bug: "306119890" +} +flag { + name: "multiple_sa_proposals" + namespace: "iwlan_telephony" + description: "Add multiple proposals of IKE SA and Child SA" + bug: "287296642" +} +flag { + name: "high_secure_transforms_prioritized" + namespace: "iwlan_telephony" + description: "Reorder IKE and Child SA security transforms with high secured as prioritized" + bug: "306323917" +} +flag { name: "epdg_selection_exclude_failed_ip_address" namespace: "iwlan_telephony" description: "Exclude the failed ip address in epdg selection until tunnel establish successfully or all ip address candidates are failed" diff --git a/src/com/google/android/iwlan/epdg/EpdgChildSaProposal.java b/src/com/google/android/iwlan/epdg/EpdgChildSaProposal.java new file mode 100644 index 0000000..d85e322 --- /dev/null +++ b/src/com/google/android/iwlan/epdg/EpdgChildSaProposal.java @@ -0,0 +1,79 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.iwlan.epdg; + +import android.net.ipsec.ike.ChildSaProposal; +import android.util.Pair; + +public class EpdgChildSaProposal extends EpdgSaProposal { + /** + * Builds {@link ChildSaProposal} of carrier proposed encryption algorithms (non-AEAD) cipher + * suit. + */ + public ChildSaProposal buildProposedChildSaProposal() { + return buildProposal(false, true); + } + + /** Builds {@link ChildSaProposal} of carrier proposed AEAD algorithms cipher suit. */ + public ChildSaProposal buildProposedChildSaAeadProposal() { + return buildProposal(true, true); + } + + /** + * Builds {@link ChildSaProposal} of Iwlan supported encryption algorithms (non-AEAD) cipher + * suit. + */ + public ChildSaProposal buildSupportedChildSaProposal() { + return buildProposal(false, false); + } + + /** Builds {@link ChildSaProposal} of Iwlan supported AEAD algorithms cipher suit. */ + public ChildSaProposal buildSupportedChildSaAeadProposal() { + return buildProposal(true, false); + } + + private ChildSaProposal buildProposal(boolean isAead, boolean isProposed) { + ChildSaProposal.Builder saProposalBuilder = new ChildSaProposal.Builder(); + + int[] dhGroups = getDhGroups(); + for (int dhGroup : dhGroups) { + saProposalBuilder.addDhGroup(dhGroup); + } + + Pair<Integer, Integer>[] encrAlgos; + + if (isAead) { + encrAlgos = (isProposed) ? getAeadAlgos() : getSupportedAeadAlgos(); + } else { + encrAlgos = (isProposed) ? getEncryptionAlgos() : getSupportedEncryptionAlgos(); + } + + for (Pair<Integer, Integer> encrAlgo : encrAlgos) { + saProposalBuilder.addEncryptionAlgorithm(encrAlgo.first, encrAlgo.second); + } + + if (!isAead) { + int[] integrityAlgos = + (isProposed) ? getIntegrityAlgos() : getSupportedIntegrityAlgos(); + for (int integrityAlgo : integrityAlgos) { + saProposalBuilder.addIntegrityAlgorithm(integrityAlgo); + } + } + + return saProposalBuilder.build(); + } +} diff --git a/src/com/google/android/iwlan/epdg/EpdgIkeSaProposal.java b/src/com/google/android/iwlan/epdg/EpdgIkeSaProposal.java new file mode 100644 index 0000000..f4d6d56 --- /dev/null +++ b/src/com/google/android/iwlan/epdg/EpdgIkeSaProposal.java @@ -0,0 +1,117 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.iwlan.epdg; + +import android.net.ipsec.ike.IkeSaProposal; +import android.util.Pair; + +import java.util.LinkedHashSet; + +public class EpdgIkeSaProposal extends EpdgSaProposal { + protected final LinkedHashSet<Integer> mProposedPrfAlgos = new LinkedHashSet<>(); + + /** + * Add proposed PRF algorithms by the carrier. + * + * @param prfAlgos proposed PRF algorithms + */ + public void addProposedPrfAlgorithm(int[] prfAlgos) { + for (int prfAlgo : prfAlgos) { + if (validateConfig(prfAlgo, VALID_PRF_ALGOS, CONFIG_TYPE_PRF_ALGO)) { + mProposedPrfAlgos.add(prfAlgo); + } + } + } + + private int[] getPrfAlgos() { + if (isSaferProposalsPrioritized()) { + return mProposedPrfAlgos.stream() + .sorted( + (item1, item2) -> + compareTransformPriority(VALID_PRF_ALGOS, item1, item2)) + .mapToInt(Integer::intValue) + .toArray(); + } + + return mProposedPrfAlgos.stream().mapToInt(Integer::intValue).toArray(); + } + + private int[] getSupportedPrfAlgos() { + return VALID_PRF_ALGOS.stream().mapToInt(Integer::intValue).toArray(); + } + + /** + * Builds {@link IkeSaProposal} of carrier proposed encryption algorithms (non-AEAD) cipher + * suit. + */ + public IkeSaProposal buildProposedIkeSaProposal() { + return buildProposal(false, true); + } + + /** Builds {@link IkeSaProposal} of carrier proposed AEAD algorithms cipher suit. */ + public IkeSaProposal buildProposedIkeSaAeadProposal() { + return buildProposal(true, true); + } + + /** + * Builds {@link IkeSaProposal} of Iwlan supported encryption algorithms (non-AEAD) cipher suit. + */ + public IkeSaProposal buildSupportedIkeSaProposal() { + return buildProposal(false, false); + } + + /** Builds {@link IkeSaProposal} of Iwlan supported AEAD algorithms cipher suit. */ + public IkeSaProposal buildSupportedIkeSaAeadProposal() { + return buildProposal(true, false); + } + + private IkeSaProposal buildProposal(boolean isAead, boolean isProposed) { + IkeSaProposal.Builder saProposalBuilder = new IkeSaProposal.Builder(); + + int[] dhGroups = isProposed ? getDhGroups() : getSupportedDhGroups(); + for (int dhGroup : dhGroups) { + saProposalBuilder.addDhGroup(dhGroup); + } + + Pair<Integer, Integer>[] encrAlgos; + + if (isAead) { + encrAlgos = (isProposed) ? getAeadAlgos() : getSupportedAeadAlgos(); + } else { + encrAlgos = (isProposed) ? getEncryptionAlgos() : getSupportedEncryptionAlgos(); + } + + for (Pair<Integer, Integer> encrAlgo : encrAlgos) { + saProposalBuilder.addEncryptionAlgorithm(encrAlgo.first, encrAlgo.second); + } + + if (!isAead) { + int[] integrityAlgos = + (isProposed) ? getIntegrityAlgos() : getSupportedIntegrityAlgos(); + for (int integrityAlgo : integrityAlgos) { + saProposalBuilder.addIntegrityAlgorithm(integrityAlgo); + } + } + + int[] prfAlgos = (isProposed) ? getPrfAlgos() : getSupportedPrfAlgos(); + for (int prfAlgo : prfAlgos) { + saProposalBuilder.addPseudorandomFunction(prfAlgo); + } + + return saProposalBuilder.build(); + } +} diff --git a/src/com/google/android/iwlan/epdg/EpdgSaProposal.java b/src/com/google/android/iwlan/epdg/EpdgSaProposal.java new file mode 100644 index 0000000..871cc5c --- /dev/null +++ b/src/com/google/android/iwlan/epdg/EpdgSaProposal.java @@ -0,0 +1,329 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.iwlan.epdg; + +import android.net.ipsec.ike.SaProposal; +import android.util.Log; +import android.util.Pair; + +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +abstract class EpdgSaProposal { + private static final String TAG = EpdgSaProposal.class.getSimpleName(); + private static final Set<Integer> VALID_DH_GROUPS; + private static final Set<Integer> VALID_KEY_LENGTHS; + protected static final Set<Integer> VALID_PRF_ALGOS; + private static final Set<Integer> VALID_INTEGRITY_ALGOS; + private static final Set<Integer> VALID_ENCRYPTION_ALGOS; + private static final Set<Integer> VALID_AEAD_ALGOS; + + private static final String CONFIG_TYPE_DH_GROUP = "dh group"; + private static final String CONFIG_TYPE_KEY_LEN = "algorithm key length"; + protected static final String CONFIG_TYPE_PRF_ALGO = "prf algorithm"; + private static final String CONFIG_TYPE_INTEGRITY_ALGO = "integrity algorithm"; + private static final String CONFIG_TYPE_ENCRYPT_ALGO = "encryption algorithm"; + private static final String CONFIG_TYPE_AEAD_ALGO = "AEAD algorithm"; + + private boolean mSaferAlgosPrioritized = false; + + /* + * Each transform below filled with high secured order and index of each value + * represents the priority. + * Safer transform has high priority and proposals will be orders based on + * the priority order. + * For example, DH Group 4096 has more priority compare to 3072, and 3072 + * has more priority than 2048. + * With reference to 3GPP TS 33.210 and RFC 8221, high secured transforms + * are prioritized in IKE and CHILD SA proposals. + */ + static { + VALID_DH_GROUPS = + Collections.unmodifiableSet( + new LinkedHashSet<Integer>( + List.of( + SaProposal.DH_GROUP_4096_BIT_MODP, + SaProposal.DH_GROUP_3072_BIT_MODP, + SaProposal.DH_GROUP_2048_BIT_MODP, + SaProposal.DH_GROUP_1536_BIT_MODP, + SaProposal.DH_GROUP_1024_BIT_MODP))); + + VALID_KEY_LENGTHS = + Collections.unmodifiableSet( + new LinkedHashSet<Integer>( + List.of( + SaProposal.KEY_LEN_AES_256, + SaProposal.KEY_LEN_AES_192, + SaProposal.KEY_LEN_AES_128))); + + VALID_ENCRYPTION_ALGOS = + Collections.unmodifiableSet( + new LinkedHashSet<Integer>( + List.of( + SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, + SaProposal.ENCRYPTION_ALGORITHM_AES_CTR))); + + VALID_INTEGRITY_ALGOS = + Collections.unmodifiableSet( + new LinkedHashSet<Integer>( + List.of( + SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256, + SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192, + SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128, + SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96, + SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96))); + + VALID_AEAD_ALGOS = + Collections.unmodifiableSet( + new LinkedHashSet<Integer>( + List.of( + SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16, + SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12, + SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8))); + + VALID_PRF_ALGOS = + Collections.unmodifiableSet( + new LinkedHashSet<Integer>( + List.of( + SaProposal.PSEUDORANDOM_FUNCTION_SHA2_512, + SaProposal.PSEUDORANDOM_FUNCTION_SHA2_384, + SaProposal.PSEUDORANDOM_FUNCTION_SHA2_256, + SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1, + SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC))); + } + + protected final LinkedHashSet<Integer> mProposedDhGroups = new LinkedHashSet<>(); + protected final LinkedHashSet<Integer> mProposedIntegrityAlgos = new LinkedHashSet<>(); + protected final LinkedHashSet<Pair<Integer, Integer>> mProposedEncryptAlgos = + new LinkedHashSet<>(); + protected final LinkedHashSet<Pair<Integer, Integer>> mProposedAeadAlgos = + new LinkedHashSet<>(); + + /** + * Add proposed DH groups by the carrier. + * + * @param dhGroups proposed DH groups + */ + public void addProposedDhGroups(int[] dhGroups) { + for (int dhGroup : dhGroups) { + if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) { + mProposedDhGroups.add(dhGroup); + } + } + } + + /** + * Add proposed integrity algorithms by the carrier. + * + * @param integrityAlgos proposed integrity algorithms + */ + public void addProposedIntegrityAlgorithm(int[] integrityAlgos) { + for (int integrityAlgo : integrityAlgos) { + if (validateConfig(integrityAlgo, VALID_INTEGRITY_ALGOS, CONFIG_TYPE_INTEGRITY_ALGO)) { + mProposedIntegrityAlgos.add(integrityAlgo); + } + } + } + + /** + * Add proposed encryption algorithms and respective key lengths by the carrier. + * + * @param encryptionAlgo proposed encryption algorithm + * @param keyLens proposed key lengths for the encryption algorithm + */ + public void addProposedEncryptionAlgorithm(int encryptionAlgo, int[] keyLens) { + if (validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) { + for (int keyLen : keyLens) { + if (validateConfig(keyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { + mProposedEncryptAlgos.add(new Pair<Integer, Integer>(encryptionAlgo, keyLen)); + } + } + } + } + + /** + * Add proposed AEAD algorithms and respective key lengths by the carrier. + * + * @param aeadAlgo proposed AEAD algorithm + * @param keyLens proposed key lengths for the encryption algorithm + */ + public void addProposedAeadAlgorithm(int aeadAlgo, int[] keyLens) { + if (validateConfig(aeadAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_AEAD_ALGO)) { + for (int keyLen : keyLens) { + if (validateConfig(keyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { + mProposedAeadAlgos.add(new Pair<Integer, Integer>(aeadAlgo, keyLen)); + } + } + } + } + + /** Enable to reorder proposals with safer ciphers prioritized. */ + public void enableReorderingSaferProposals() { + mSaferAlgosPrioritized = true; + } + + /** + * Disable to reorder proposals with safer ciphers prioritized.Follows default configured order. + */ + public void disableReorderingSaferProposals() { + mSaferAlgosPrioritized = false; + } + + protected boolean isSaferProposalsPrioritized() { + return mSaferAlgosPrioritized; + } + + protected int getIndexOf(Set<Integer> set, int value) { + Iterator<Integer> itr = set.iterator(); + int index = 0; + + while (itr.hasNext()) { + if (itr.next().equals(value)) { + return index; + } + index++; + } + + return -1; + } + + /** + * Compares the priority of the transforms. + */ + protected int compareTransformPriority(Set<Integer> transformGroup, int item1, int item2) { + return getIndexOf(transformGroup, item1) - getIndexOf(transformGroup, item2); + } + + /** + * Compares the priority of the encryption/AEAD transforms. + * First value in pair is encryption/AEAD algorithm and + * second value in pair is key length of that algorithm. + * If Algorithms are same then compare the priotity of the key lengths else compare + * the priority of the algorithms. + */ + protected int compareEncryptionTransformPriority( + Set<Integer> algos, + Set<Integer> keyLens, + Pair<Integer, Integer> item1, + Pair<Integer, Integer> item2) { + return item1.first.equals(item2.first) + ? getIndexOf(keyLens, item1.second) - getIndexOf(keyLens, item2.second) + : getIndexOf(algos, item1.first) - getIndexOf(algos, item2.first); + } + + protected int[] getDhGroups() { + if (isSaferProposalsPrioritized()) { + return mProposedDhGroups.stream() + .sorted( + (item1, item2) -> + compareTransformPriority(VALID_DH_GROUPS, item1, item2)) + .mapToInt(Integer::intValue) + .toArray(); + } + + return mProposedDhGroups.stream().mapToInt(Integer::intValue).toArray(); + } + + protected int[] getSupportedDhGroups() { + return VALID_DH_GROUPS.stream().mapToInt(Integer::intValue).toArray(); + } + + protected int[] getIntegrityAlgos() { + if (isSaferProposalsPrioritized()) { + return mProposedIntegrityAlgos.stream() + .sorted( + (item1, item2) -> + compareTransformPriority(VALID_INTEGRITY_ALGOS, item1, item2)) + .mapToInt(Integer::intValue) + .toArray(); + } + + return mProposedIntegrityAlgos.stream().mapToInt(Integer::intValue).toArray(); + } + + protected int[] getSupportedIntegrityAlgos() { + return VALID_INTEGRITY_ALGOS.stream().mapToInt(Integer::intValue).toArray(); + } + + protected Pair<Integer, Integer>[] getEncryptionAlgos() { + if (isSaferProposalsPrioritized()) { + return mProposedEncryptAlgos.stream() + .sorted( + (item1, item2) -> + compareEncryptionTransformPriority( + VALID_ENCRYPTION_ALGOS, + VALID_KEY_LENGTHS, + item1, + item2)) + .toArray(Pair[]::new); + } + + return mProposedEncryptAlgos.toArray(new Pair[mProposedEncryptAlgos.size()]); + } + + protected Pair<Integer, Integer>[] getSupportedEncryptionAlgos() { + Pair<Integer, Integer>[] encrAlgos = + new Pair[VALID_ENCRYPTION_ALGOS.size() * VALID_KEY_LENGTHS.size()]; + int index = 0; + for (int algo : VALID_ENCRYPTION_ALGOS) { + for (int len : VALID_KEY_LENGTHS) { + encrAlgos[index++] = new Pair(algo, len); + } + } + + return encrAlgos; + } + + protected Pair<Integer, Integer>[] getAeadAlgos() { + if (isSaferProposalsPrioritized()) { + return mProposedAeadAlgos.stream() + .sorted( + (item1, item2) -> + compareEncryptionTransformPriority( + VALID_AEAD_ALGOS, VALID_KEY_LENGTHS, item1, item2)) + .toArray(Pair[]::new); + } + + return mProposedAeadAlgos.toArray(new Pair[mProposedAeadAlgos.size()]); + } + + protected Pair<Integer, Integer>[] getSupportedAeadAlgos() { + Pair<Integer, Integer>[] aeadAlgos = + new Pair[VALID_AEAD_ALGOS.size() * VALID_KEY_LENGTHS.size()]; + int index = 0; + for (int algo : VALID_AEAD_ALGOS) { + for (int len : VALID_KEY_LENGTHS) { + aeadAlgos[index++] = new Pair(algo, len); + } + } + + return aeadAlgos; + } + + protected static boolean validateConfig( + int config, Set<Integer> validConfigValues, String configType) { + if (validConfigValues.contains(config)) { + return true; + } + + Log.e(TAG, "Invalid config value for " + configType + ":" + config); + return false; + } +} diff --git a/src/com/google/android/iwlan/epdg/EpdgSelector.java b/src/com/google/android/iwlan/epdg/EpdgSelector.java index 3590a7e..dc2c364 100644 --- a/src/com/google/android/iwlan/epdg/EpdgSelector.java +++ b/src/com/google/android/iwlan/epdg/EpdgSelector.java @@ -155,6 +155,9 @@ public class EpdgSelector { mV4PcoData = new ArrayList<>(); mV6PcoData = new ArrayList<>(); + mV4PcoData = new ArrayList<>(); + mV6PcoData = new ArrayList<>(); + mErrorPolicyManager = ErrorPolicyManager.getInstance(mContext, mSlotId); mTemporaryExcludedAddresses = new HashSet<>(); diff --git a/src/com/google/android/iwlan/epdg/EpdgTunnelManager.java b/src/com/google/android/iwlan/epdg/EpdgTunnelManager.java index c350525..8b53ee1 100644 --- a/src/com/google/android/iwlan/epdg/EpdgTunnelManager.java +++ b/src/com/google/android/iwlan/epdg/EpdgTunnelManager.java @@ -76,6 +76,7 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.google.android.iwlan.ErrorPolicyManager; +import com.google.android.iwlan.IwlanCarrierConfig; import com.google.android.iwlan.IwlanError; import com.google.android.iwlan.IwlanHelper; import com.google.android.iwlan.IwlanTunnelMetricsImpl; @@ -187,6 +188,7 @@ public class EpdgTunnelManager { private static final Set<Integer> VALID_PRF_ALGOS; private static final Set<Integer> VALID_INTEGRITY_ALGOS; private static final Set<Integer> VALID_ENCRYPTION_ALGOS; + private static final Set<Integer> VALID_AEAD_ALGOS; private static final String CONFIG_TYPE_DH_GROUP = "dh group"; private static final String CONFIG_TYPE_KEY_LEN = "algorithm key length"; @@ -221,6 +223,12 @@ public class EpdgTunnelManager { SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192, SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256); + VALID_AEAD_ALGOS = + Set.of( + SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8, + SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12, + SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16); + VALID_PRF_ALGOS = Set.of( SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1, @@ -918,7 +926,35 @@ public class EpdgTunnelManager { new TunnelModeChildSessionParams.Builder() .setLifetimeSeconds(hardTimeSeconds, softTimeSeconds); - childSessionParamsBuilder.addChildSaProposal(buildChildSaProposal()); + if (mFeatureFlags.multipleSaProposals() + && IwlanCarrierConfig.getConfigBoolean( + mContext, + mSlotId, + CarrierConfigManager.Iwlan + .KEY_SUPPORTS_CHILD_SESSION_MULTIPLE_SA_PROPOSALS_BOOL)) { + EpdgChildSaProposal epdgChildSaProposal = createEpdgChildSaProposal(); + + if (mFeatureFlags.highSecureTransformsPrioritized()) { + epdgChildSaProposal.enableReorderingSaferProposals(); + } + + if (isChildSessionAeadAlgosAvailable()) { + childSessionParamsBuilder.addChildSaProposal( + epdgChildSaProposal.buildProposedChildSaAeadProposal()); + } + childSessionParamsBuilder.addChildSaProposal( + epdgChildSaProposal.buildProposedChildSaProposal()); + childSessionParamsBuilder.addChildSaProposal( + epdgChildSaProposal.buildSupportedChildSaAeadProposal()); + childSessionParamsBuilder.addChildSaProposal( + epdgChildSaProposal.buildSupportedChildSaProposal()); + } else { + if (mFeatureFlags.aeadAlgosEnabled() && isChildSessionAeadAlgosAvailable()) { + childSessionParamsBuilder.addChildSaProposal(buildAeadChildSaProposal()); + } else { + childSessionParamsBuilder.addChildSaProposal(buildChildSaProposal()); + } + } boolean handoverIPv4Present = setupRequest.srcIpv4Address().isPresent(); boolean handoverIPv6Present = setupRequest.srcIpv6Address().isPresent(); @@ -1047,7 +1083,6 @@ public class EpdgTunnelManager { .setLocalIdentification(getLocalIdentification()) .setRemoteIdentification(getId(setupRequest.apnName(), false)) .setAuthEap(null, getEapConfig()) - .addIkeSaProposal(buildIkeSaProposal()) .setNetwork(mDefaultNetwork) .addIkeOption(IkeSessionParams.IKE_OPTION_ACCEPT_ANY_REMOTE_ID) .addIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE) @@ -1056,6 +1091,32 @@ public class EpdgTunnelManager { .setRetransmissionTimeoutsMillis(getRetransmissionTimeoutsFromConfig()) .setDpdDelaySeconds(getDpdDelayFromConfig()); + if (mFeatureFlags.multipleSaProposals() + && IwlanCarrierConfig.getConfigBoolean( + mContext, + mSlotId, + CarrierConfigManager.Iwlan + .KEY_SUPPORTS_IKE_SESSION_MULTIPLE_SA_PROPOSALS_BOOL)) { + EpdgIkeSaProposal epdgIkeSaProposal = createEpdgIkeSaProposal(); + + if (mFeatureFlags.highSecureTransformsPrioritized()) { + epdgIkeSaProposal.enableReorderingSaferProposals(); + } + + if (isIkeSessionAeadAlgosAvailable()) { + builder.addIkeSaProposal(epdgIkeSaProposal.buildProposedIkeSaAeadProposal()); + } + builder.addIkeSaProposal(epdgIkeSaProposal.buildProposedIkeSaProposal()); + builder.addIkeSaProposal(epdgIkeSaProposal.buildSupportedIkeSaAeadProposal()); + builder.addIkeSaProposal(epdgIkeSaProposal.buildSupportedIkeSaProposal()); + } else { + if (mFeatureFlags.aeadAlgosEnabled() && isIkeSessionAeadAlgosAvailable()) { + builder.addIkeSaProposal(buildIkeSaAeadProposal()); + } else { + builder.addIkeSaProposal(buildIkeSaProposal()); + } + } + if (numPdnTunnels() == 0) { builder.addIkeOption(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT); Log.d(TAG, "IKE_OPTION_INITIAL_CONTACT"); @@ -1120,6 +1181,32 @@ public class EpdgTunnelManager { builder3gppParams.build(), new TmIke3gppCallback(apnName, token)); } + private boolean isChildSessionAeadAlgosAvailable() { + int[] encryptionAlgos = + getConfig( + CarrierConfigManager.Iwlan + .KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY); + for (int encryptionAlgo : encryptionAlgos) { + if (validateConfig(encryptionAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) { + return true; + } + } + return false; + } + + private boolean isIkeSessionAeadAlgosAvailable() { + int[] encryptionAlgos = + getConfig( + CarrierConfigManager.Iwlan + .KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY); + for (int encryptionAlgo : encryptionAlgos) { + if (validateConfig(encryptionAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) { + return true; + } + } + return false; + } + private boolean isValidChildSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds) { return hardLifetimeSeconds >= CHILD_HARD_LIFETIME_SEC_MINIMUM && hardLifetimeSeconds <= CHILD_HARD_LIFETIME_SEC_MAXIMUM @@ -1138,6 +1225,124 @@ public class EpdgTunnelManager { return IwlanHelper.getConfig(configKey, mContext, mSlotId); } + private void createEpdgSaProposal(EpdgSaProposal epdgSaProposal, boolean isChildProposal) { + epdgSaProposal.addProposedDhGroups( + IwlanCarrierConfig.getConfigIntArray( + mContext, + mSlotId, + CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY)); + + int[] encryptionAlgos = + isChildProposal + ? IwlanCarrierConfig.getConfigIntArray( + mContext, + mSlotId, + CarrierConfigManager.Iwlan + .KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY) + : IwlanCarrierConfig.getConfigIntArray( + mContext, + mSlotId, + CarrierConfigManager.Iwlan + .KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY); + + for (int encryptionAlgo : encryptionAlgos) { + if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CBC) { + int[] aesCbcKeyLens = + isChildProposal + ? IwlanCarrierConfig.getConfigIntArray( + mContext, + mSlotId, + CarrierConfigManager.Iwlan + .KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY) + : IwlanCarrierConfig.getConfigIntArray( + mContext, + mSlotId, + CarrierConfigManager.Iwlan + .KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY); + epdgSaProposal.addProposedEncryptionAlgorithm(encryptionAlgo, aesCbcKeyLens); + } + + if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CTR) { + int[] aesCtrKeyLens = + isChildProposal + ? IwlanCarrierConfig.getConfigIntArray( + mContext, + mSlotId, + CarrierConfigManager.Iwlan + .KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY) + : IwlanCarrierConfig.getConfigIntArray( + mContext, + mSlotId, + CarrierConfigManager.Iwlan + .KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY); + epdgSaProposal.addProposedEncryptionAlgorithm(encryptionAlgo, aesCtrKeyLens); + } + } + + if (encryptionAlgos.length > 0) { + epdgSaProposal.addProposedIntegrityAlgorithm( + IwlanCarrierConfig.getConfigIntArray( + mContext, + mSlotId, + CarrierConfigManager.Iwlan + .KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY)); + } + + int[] aeadAlgos = + isChildProposal + ? IwlanCarrierConfig.getConfigIntArray( + mContext, + mSlotId, + CarrierConfigManager.Iwlan + .KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY) + : IwlanCarrierConfig.getConfigIntArray( + mContext, + mSlotId, + CarrierConfigManager.Iwlan + .KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY); + for (int aeadAlgo : aeadAlgos) { + if (!validateConfig(aeadAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) { + continue; + } + if ((aeadAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8) + || (aeadAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12) + || (aeadAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16)) { + int[] aesGcmKeyLens = + isChildProposal + ? IwlanCarrierConfig.getConfigIntArray( + mContext, + mSlotId, + CarrierConfigManager.Iwlan + .KEY_CHILD_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY) + : IwlanCarrierConfig.getConfigIntArray( + mContext, + mSlotId, + CarrierConfigManager.Iwlan + .KEY_IKE_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY); + epdgSaProposal.addProposedAeadAlgorithm(aeadAlgo, aesGcmKeyLens); + } + } + } + + private EpdgChildSaProposal createEpdgChildSaProposal() { + EpdgChildSaProposal epdgChildSaProposal = new EpdgChildSaProposal(); + createEpdgSaProposal(epdgChildSaProposal, true); + return epdgChildSaProposal; + } + + private EpdgIkeSaProposal createEpdgIkeSaProposal() { + EpdgIkeSaProposal epdgIkeSaProposal = new EpdgIkeSaProposal(); + + createEpdgSaProposal(epdgIkeSaProposal, false); + + epdgIkeSaProposal.addProposedPrfAlgorithm( + IwlanCarrierConfig.getConfigIntArray( + mContext, + mSlotId, + CarrierConfigManager.Iwlan.KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY)); + return epdgIkeSaProposal; + } + private IkeSaProposal buildIkeSaProposal() { IkeSaProposal.Builder saProposalBuilder = new IkeSaProposal.Builder(); @@ -1199,6 +1404,50 @@ public class EpdgTunnelManager { return saProposalBuilder.build(); } + private IkeSaProposal buildIkeSaAeadProposal() { + IkeSaProposal.Builder saProposalBuilder = new IkeSaProposal.Builder(); + + int[] dhGroups = getConfig(CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY); + for (int dhGroup : dhGroups) { + if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) { + saProposalBuilder.addDhGroup(dhGroup); + } + } + + int[] encryptionAlgos = + getConfig( + CarrierConfigManager.Iwlan + .KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY); + for (int encryptionAlgo : encryptionAlgos) { + if (!validateConfig(encryptionAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) { + continue; + } + if ((encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8) + || (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12) + || (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16)) { + int[] aesGcmKeyLens = + getConfig( + CarrierConfigManager.Iwlan + .KEY_IKE_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY); + for (int aesGcmKeyLen : aesGcmKeyLens) { + if (validateConfig(aesGcmKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { + saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesGcmKeyLen); + } + } + } + } + + int[] prfAlgos = + getConfig(CarrierConfigManager.Iwlan.KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY); + for (int prfAlgo : prfAlgos) { + if (validateConfig(prfAlgo, VALID_PRF_ALGOS, CONFIG_TYPE_PRF_ALGO)) { + saProposalBuilder.addPseudorandomFunction(prfAlgo); + } + } + + return saProposalBuilder.build(); + } + private boolean validateConfig(int config, Set<Integer> validConfigValues, String configType) { if (validConfigValues.contains(config)) { return true; @@ -1278,6 +1527,42 @@ public class EpdgTunnelManager { return saProposalBuilder.build(); } + private ChildSaProposal buildAeadChildSaProposal() { + ChildSaProposal.Builder saProposalBuilder = new ChildSaProposal.Builder(); + + int[] dhGroups = getConfig(CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY); + for (int dhGroup : dhGroups) { + if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) { + saProposalBuilder.addDhGroup(dhGroup); + } + } + + int[] encryptionAlgos = + getConfig( + CarrierConfigManager.Iwlan + .KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY); + for (int encryptionAlgo : encryptionAlgos) { + if (!validateConfig(encryptionAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) { + continue; + } + if ((encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8) + || (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12) + || (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16)) { + int[] aesGcmKeyLens = + getConfig( + CarrierConfigManager.Iwlan + .KEY_CHILD_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY); + for (int aesGcmKeyLen : aesGcmKeyLens) { + if (validateConfig(aesGcmKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { + saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesGcmKeyLen); + } + } + } + } + + return saProposalBuilder.build(); + } + private IkeIdentification getLocalIdentification() throws IwlanSimNotReadyException { String nai; diff --git a/test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java b/test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java index 1829047..05ab0bc 100644 --- a/test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java +++ b/test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java @@ -28,6 +28,7 @@ import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyLong; +import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; @@ -74,6 +75,7 @@ import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; +import android.util.Pair; import com.google.android.iwlan.IwlanError; import com.google.android.iwlan.IwlanTunnelMetricsImpl; @@ -545,6 +547,207 @@ public class EpdgTunnelManagerTest { } @Test + public void testAeadSaProposals() throws Exception { + when(mFakeFeatureFlags.aeadAlgosEnabled()).thenReturn(true); + final String apnName = "ims"; + int[] aeadAlgos = { + SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8, + SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12, + SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16, + }; + int[] aeadAlgosKeyLens = { + SaProposal.KEY_LEN_AES_128, SaProposal.KEY_LEN_AES_192, SaProposal.KEY_LEN_AES_256, + }; + + PersistableBundle bundle = new PersistableBundle(); + bundle.putIntArray( + CarrierConfigManager.Iwlan.KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY, + aeadAlgos); + bundle.putIntArray( + CarrierConfigManager.Iwlan.KEY_IKE_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY, + aeadAlgosKeyLens); + bundle.putIntArray( + CarrierConfigManager.Iwlan.KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY, + aeadAlgos); + bundle.putIntArray( + CarrierConfigManager.Iwlan.KEY_CHILD_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY, + aeadAlgosKeyLens); + + setupMockForGetConfig(bundle); + + IkeSessionArgumentCaptors tunnelArgumentCaptors = + verifyBringUpTunnelWithDnsQuery(apnName, mMockDefaultNetwork); + + IkeSessionParams ikeTunnelParams = tunnelArgumentCaptors.mIkeSessionParamsCaptor.getValue(); + + List<Pair<Integer, Integer>> ikeEncrAlgos = + ikeTunnelParams.getIkeSaProposals().get(0).getEncryptionAlgorithms(); + + assertTrue(ikeEncrAlgos.contains(new Pair(aeadAlgos[0], aeadAlgosKeyLens[0]))); + assertEquals( + "IKE AEAD algorithms mismatch", + (long) aeadAlgos.length * aeadAlgosKeyLens.length, + (long) ikeEncrAlgos.size()); + + ChildSessionParams childTunnelParams = + tunnelArgumentCaptors.mChildSessionParamsCaptor.getValue(); + + List<Pair<Integer, Integer>> childEncrAlgos = + childTunnelParams.getChildSaProposals().get(0).getEncryptionAlgorithms(); + + assertTrue(childEncrAlgos.contains(new Pair(aeadAlgos[0], aeadAlgosKeyLens[0]))); + assertEquals( + "Child AEAD algorithms mismatch", + (long) aeadAlgos.length * aeadAlgosKeyLens.length, + (long) childEncrAlgos.size()); + } + + @Test + public void testMultipleSaProposals() throws Exception { + when(mFakeFeatureFlags.multipleSaProposals()).thenReturn(true); + final String apnName = "ims"; + PersistableBundle bundle = new PersistableBundle(); + + int[] aeadAlgos = { + SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12, + }; + int[] aeadAlgosKeyLens = { + SaProposal.KEY_LEN_AES_192, SaProposal.KEY_LEN_AES_256, + }; + + bundle.putIntArray( + CarrierConfigManager.Iwlan.KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY, + aeadAlgos); + bundle.putIntArray( + CarrierConfigManager.Iwlan.KEY_IKE_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY, + aeadAlgosKeyLens); + bundle.putIntArray( + CarrierConfigManager.Iwlan.KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY, + aeadAlgos); + bundle.putIntArray( + CarrierConfigManager.Iwlan.KEY_CHILD_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY, + aeadAlgosKeyLens); + + bundle.putBoolean( + CarrierConfigManager.Iwlan.KEY_SUPPORTS_IKE_SESSION_MULTIPLE_SA_PROPOSALS_BOOL, + true); + bundle.putBoolean( + CarrierConfigManager.Iwlan.KEY_SUPPORTS_CHILD_SESSION_MULTIPLE_SA_PROPOSALS_BOOL, + true); + + setupMockForGetConfig(bundle); + + IkeSessionArgumentCaptors tunnelArgumentCaptors = + verifyBringUpTunnelWithDnsQuery(apnName, mMockDefaultNetwork); + + IkeSessionParams ikeTunnelParams = tunnelArgumentCaptors.mIkeSessionParamsCaptor.getValue(); + + assertTrue(ikeTunnelParams.getIkeSaProposals().size() > 1); + + List<Pair<Integer, Integer>> ikeAeadAlgos = + ikeTunnelParams.getIkeSaProposals().get(0).getEncryptionAlgorithms(); + assertEquals( + "Reorder higher AEAD in IKE SA mismatch", + (long) SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12, + (long) ikeAeadAlgos.get(0).first); + + ChildSessionParams childTunnelParams = + tunnelArgumentCaptors.mChildSessionParamsCaptor.getValue(); + + assertTrue(childTunnelParams.getChildSaProposals().size() > 1); + + List<Pair<Integer, Integer>> childAeadAlgos = + childTunnelParams.getChildSaProposals().get(0).getEncryptionAlgorithms(); + assertEquals( + "Reorder higher AEAD in Child SA mismatch", + (long) SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12, + (long) childAeadAlgos.get(0).first); + } + + @Test + public void testSaProposalsReorder() throws Exception { + when(mFakeFeatureFlags.aeadAlgosEnabled()).thenReturn(true); + when(mFakeFeatureFlags.multipleSaProposals()).thenReturn(true); + when(mFakeFeatureFlags.highSecureTransformsPrioritized()).thenReturn(true); + + final String apnName = "ims"; + int[] aeadAlgos = { + SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, + }; + int[] aeadAlgosKeyLens = { + SaProposal.KEY_LEN_AES_128, SaProposal.KEY_LEN_AES_192, SaProposal.KEY_LEN_AES_256, + }; + + PersistableBundle bundle = new PersistableBundle(); + + bundle.putIntArray( + CarrierConfigManager.Iwlan + .KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY, + aeadAlgos); + bundle.putIntArray( + CarrierConfigManager.Iwlan.KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY, + aeadAlgosKeyLens); + bundle.putIntArray( + CarrierConfigManager.Iwlan + .KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY, + aeadAlgos); + bundle.putIntArray( + CarrierConfigManager.Iwlan.KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY, + aeadAlgosKeyLens); + + bundle.putBoolean( + CarrierConfigManager.Iwlan.KEY_SUPPORTS_IKE_SESSION_MULTIPLE_SA_PROPOSALS_BOOL, + true); + bundle.putBoolean( + CarrierConfigManager.Iwlan.KEY_SUPPORTS_CHILD_SESSION_MULTIPLE_SA_PROPOSALS_BOOL, + true); + + setupMockForGetConfig(bundle); + + IkeSessionArgumentCaptors tunnelArgumentCaptors = + verifyBringUpTunnelWithDnsQuery(apnName, mMockDefaultNetwork); + + IkeSessionParams ikeTunnelParams = tunnelArgumentCaptors.mIkeSessionParamsCaptor.getValue(); + + assertTrue(ikeTunnelParams.getIkeSaProposals().size() > 1); + + List<Pair<Integer, Integer>> ikeEncrAlgos = + ikeTunnelParams.getIkeSaProposals().get(0).getEncryptionAlgorithms(); + + assertEquals( + "Reorder bigger key length in IKE SA mismatch", + (long) SaProposal.KEY_LEN_AES_256, + (long) ikeEncrAlgos.get(0).second); + + List<Pair<Integer, Integer>> ikeAeadAlgos = + ikeTunnelParams.getIkeSaProposals().get(1).getEncryptionAlgorithms(); + assertEquals( + "Reorder higher AEAD in IKE SA mismatch", + (long) SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16, + (long) ikeAeadAlgos.get(0).first); + + ChildSessionParams childTunnelParams = + tunnelArgumentCaptors.mChildSessionParamsCaptor.getValue(); + + assertTrue(childTunnelParams.getChildSaProposals().size() > 1); + + List<Pair<Integer, Integer>> childEncrAlgos = + childTunnelParams.getChildSaProposals().get(0).getEncryptionAlgorithms(); + + assertEquals( + "Reorder bigger key length in Child SA mismatch", + (long) SaProposal.KEY_LEN_AES_256, + (long) childEncrAlgos.get(0).second); + + List<Pair<Integer, Integer>> childAeadAlgos = + childTunnelParams.getChildSaProposals().get(1).getEncryptionAlgorithms(); + assertEquals( + "Reorder higher AEAD in Child SA mismatch", + (long) SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16, + (long) childAeadAlgos.get(0).first); + } + + @Test public void testCloseTunnelWithNoTunnelForApn() throws Exception { String testApnName = "www.xyz.com"; doReturn(0L) @@ -1158,6 +1361,7 @@ public class EpdgTunnelManagerTest { when(mMockTelephonyManager.createForSubscriptionId(DEFAULT_SUBID)) .thenReturn(mMockTelephonyManager); when(mMockCarrierConfigManager.getConfigForSubId(DEFAULT_SLOT_INDEX)).thenReturn(bundle); + when(mMockCarrierConfigManager.getConfigForSubId(anyInt(), anyString())).thenReturn(bundle); } private void setVariable(Object target, String variableName, Object value) throws Exception { |