• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.ipsec.ike.cts;
18 
19 import static android.net.IpSecAlgorithm.AUTH_AES_CMAC;
20 import static android.net.IpSecAlgorithm.AUTH_AES_XCBC;
21 import static android.net.IpSecAlgorithm.AUTH_CRYPT_AES_GCM;
22 import static android.net.IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305;
23 import static android.net.IpSecAlgorithm.AUTH_HMAC_MD5;
24 import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA1;
25 import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA256;
26 import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA384;
27 import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512;
28 import static android.net.IpSecAlgorithm.CRYPT_AES_CBC;
29 import static android.net.IpSecAlgorithm.CRYPT_AES_CTR;
30 import static android.net.ipsec.ike.SaProposal.DH_GROUP_1024_BIT_MODP;
31 import static android.net.ipsec.ike.SaProposal.DH_GROUP_1536_BIT_MODP;
32 import static android.net.ipsec.ike.SaProposal.DH_GROUP_2048_BIT_MODP;
33 import static android.net.ipsec.ike.SaProposal.DH_GROUP_3072_BIT_MODP;
34 import static android.net.ipsec.ike.SaProposal.DH_GROUP_4096_BIT_MODP;
35 import static android.net.ipsec.ike.SaProposal.DH_GROUP_CURVE_25519;
36 import static android.net.ipsec.ike.SaProposal.DH_GROUP_NONE;
37 import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_3DES;
38 import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_CBC;
39 import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_CTR;
40 import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12;
41 import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16;
42 import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8;
43 import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_CHACHA20_POLY1305;
44 import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_AES_CMAC_96;
45 import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96;
46 import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96;
47 import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128;
48 import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192;
49 import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256;
50 import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_NONE;
51 import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_128;
52 import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_192;
53 import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_256;
54 import static android.net.ipsec.ike.SaProposal.KEY_LEN_UNUSED;
55 import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_AES128_CMAC;
56 import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC;
57 import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1;
58 import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_SHA2_256;
59 import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_SHA2_384;
60 import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_SHA2_512;
61 import static android.os.Build.VERSION.CODENAME;
62 import static android.os.Build.VERSION.SDK_INT;
63 import static android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
64 import static android.os.Build.VERSION_CODES.R;
65 import static android.os.Build.VERSION_CODES.S;
66 
67 import static org.junit.Assert.assertEquals;
68 import static org.junit.Assert.assertTrue;
69 import static org.junit.Assume.assumeFalse;
70 import static org.junit.Assume.assumeTrue;
71 
72 import android.net.IpSecAlgorithm;
73 import android.net.ipsec.ike.ChildSaProposal;
74 import android.net.ipsec.ike.IkeSaProposal;
75 import android.net.ipsec.ike.SaProposal;
76 import android.util.Pair;
77 
78 import androidx.test.ext.junit.runners.AndroidJUnit4;
79 
80 import com.android.testutils.DevSdkIgnoreRule;
81 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
82 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
83 
84 import org.junit.Rule;
85 import org.junit.Test;
86 import org.junit.runner.RunWith;
87 
88 import java.util.ArrayList;
89 import java.util.Arrays;
90 import java.util.Collections;
91 import java.util.HashMap;
92 import java.util.HashSet;
93 import java.util.List;
94 import java.util.Map;
95 import java.util.Map.Entry;
96 import java.util.Set;
97 
98 @RunWith(AndroidJUnit4.class)
99 public class SaProposalTest {
100     @Rule public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
101 
102     private static final List<Pair<Integer, Integer>> IKE_NORMAL_MODE_CIPHERS =
103             getNormalModeCiphers(true /* isIke */);
104     private static final List<Pair<Integer, Integer>> IKE_COMBINED_MODE_CIPHERS =
105             getCombinedModeCiphers(true /* isIke */);
106     private static final List<Pair<Integer, Integer>> CHILD_NORMAL_MODE_CIPHERS =
107             getNormalModeCiphers(false /* isIke */);
108     private static final List<Pair<Integer, Integer>> CHILD_COMBINED_MODE_CIPHERS =
109             getCombinedModeCiphers(false /* isIke */);
110 
111     private static final List<Integer> IKE_INTEGRITY_ALGOS = getIntegrityAlgos(true /* isIke */);
112     private static final List<Integer> CHILD_INTEGRITY_ALGOS = getIntegrityAlgos(false /* isIke */);
113 
114     private static final List<Integer> DH_GROUPS = getDhGroups(false /* includeNone */);
115     private static final List<Integer> DH_GROUPS_WITH_NONE = getDhGroups(true /* includeNone */);
116     private static final List<Integer> PRFS = getPrfs();
117 
118     // Utility method for 3DES and ChaChaPoly
addCipherWithFixedKeyLenIfSupported( int cipherId, boolean isIke, List<Pair<Integer, Integer>> ciphers)119     private static void addCipherWithFixedKeyLenIfSupported(
120             int cipherId, boolean isIke, List<Pair<Integer, Integer>> ciphers) {
121         final Set<Integer> supportedAlgos =
122                 isIke
123                         ? IkeSaProposal.getSupportedEncryptionAlgorithms()
124                         : ChildSaProposal.getSupportedEncryptionAlgorithms();
125 
126         if (supportedAlgos.contains(cipherId)) {
127             ciphers.add(new Pair<>(cipherId, KEY_LEN_UNUSED));
128         }
129     }
130 
131     // Utility method for AES-CBC, AES-CTR and AES-GCM
addAesCipherIfSupported( int cipherId, boolean isIke, List<Pair<Integer, Integer>> ciphers)132     private static void addAesCipherIfSupported(
133             int cipherId, boolean isIke, List<Pair<Integer, Integer>> ciphers) {
134         final Set<Integer> supportedAlgos =
135                 isIke
136                         ? IkeSaProposal.getSupportedEncryptionAlgorithms()
137                         : ChildSaProposal.getSupportedEncryptionAlgorithms();
138 
139         if (supportedAlgos.contains(cipherId)) {
140             ciphers.add(new Pair<>(cipherId, KEY_LEN_AES_128));
141             ciphers.add(new Pair<>(cipherId, KEY_LEN_AES_192));
142             ciphers.add(new Pair<>(cipherId, KEY_LEN_AES_256));
143         }
144     }
145 
getNormalModeCiphers(boolean isIke)146     private static List<Pair<Integer, Integer>> getNormalModeCiphers(boolean isIke) {
147         final List<Pair<Integer, Integer>> ciphers = new ArrayList<>();
148         addCipherWithFixedKeyLenIfSupported(ENCRYPTION_ALGORITHM_3DES, isIke, ciphers);
149         addAesCipherIfSupported(ENCRYPTION_ALGORITHM_AES_CBC, isIke, ciphers);
150         addAesCipherIfSupported(ENCRYPTION_ALGORITHM_AES_CTR, isIke, ciphers);
151         return ciphers;
152     }
153 
getCombinedModeCiphers(boolean isIke)154     private static List<Pair<Integer, Integer>> getCombinedModeCiphers(boolean isIke) {
155         final List<Pair<Integer, Integer>> ciphers = new ArrayList<>();
156         addCipherWithFixedKeyLenIfSupported(ENCRYPTION_ALGORITHM_CHACHA20_POLY1305, isIke, ciphers);
157         addAesCipherIfSupported(ENCRYPTION_ALGORITHM_AES_GCM_8, isIke, ciphers);
158         addAesCipherIfSupported(ENCRYPTION_ALGORITHM_AES_GCM_12, isIke, ciphers);
159         addAesCipherIfSupported(ENCRYPTION_ALGORITHM_AES_GCM_16, isIke, ciphers);
160         return ciphers;
161     }
162 
getIntegrityAlgos(boolean isIke)163     private static List<Integer> getIntegrityAlgos(boolean isIke) {
164         final List<Integer> algoList = new ArrayList<>();
165 
166         if (isIke) {
167             algoList.addAll(IkeSaProposal.getSupportedIntegrityAlgorithms());
168         } else {
169             algoList.addAll(ChildSaProposal.getSupportedIntegrityAlgorithms());
170         }
171         algoList.remove(INTEGRITY_ALGORITHM_NONE);
172 
173         return algoList;
174     }
175 
getDhGroups(boolean includeNone)176     private static List<Integer> getDhGroups(boolean includeNone) {
177         final List<Integer> algoList = new ArrayList<>();
178 
179         algoList.addAll(SaProposal.getSupportedDhGroups());
180         if (!includeNone) {
181             algoList.remove(DH_GROUP_NONE);
182         }
183         return algoList;
184     }
185 
getPrfs()186     private static List<Integer> getPrfs() {
187         final List<Integer> algoList = new ArrayList<>();
188         algoList.addAll(IkeSaProposal.getSupportedPseudorandomFunctions());
189         return algoList;
190     }
191 
192     // Package private
buildIkeSaProposalWithNormalModeCipher()193     static IkeSaProposal buildIkeSaProposalWithNormalModeCipher() {
194         // This IkeSaProposal will be used for IKE exchange tests with pre-captured responses
195         // that expect KE payload with MODP 1024. Make sure MODP 1024 is the first DH group in the
196         // proposal so that IKE client will sent KE payload using MODP 1024.
197         return buildIkeSaProposalWithNormalModeCipher(true /* preferModp1024 */);
198     }
199 
buildIkeSaProposalWithNormalModeCipher(boolean preferModp1024)200     private static IkeSaProposal buildIkeSaProposalWithNormalModeCipher(boolean preferModp1024) {
201         return buildIkeSaProposal(
202                 IKE_NORMAL_MODE_CIPHERS, IKE_INTEGRITY_ALGOS, PRFS, DH_GROUPS, preferModp1024);
203     }
204 
205     // Package private
buildIkeSaProposalWithCombinedModeCipher()206     static IkeSaProposal buildIkeSaProposalWithCombinedModeCipher() {
207         return buildIkeSaProposalWithCombinedModeCipher(true /* hasIntegrityNone */);
208     }
209 
buildIkeSaProposalWithCombinedModeCipher( boolean hasIntegrityNone)210     private static IkeSaProposal buildIkeSaProposalWithCombinedModeCipher(
211             boolean hasIntegrityNone) {
212         return buildIkeSaProposalWithCombinedModeCipher(
213                 hasIntegrityNone, false /* preferModp1024 */);
214     }
215 
buildIkeSaProposalWithCombinedModeCipher( boolean hasIntegrityNone, boolean preferModp1024)216     private static IkeSaProposal buildIkeSaProposalWithCombinedModeCipher(
217             boolean hasIntegrityNone, boolean preferModp1024) {
218         final List<Integer> integerAlgos = new ArrayList<>();
219         if (hasIntegrityNone) {
220             integerAlgos.add(INTEGRITY_ALGORITHM_NONE);
221         }
222         return buildIkeSaProposal(
223                 IKE_COMBINED_MODE_CIPHERS, integerAlgos, PRFS, DH_GROUPS, preferModp1024);
224     }
225 
buildIkeSaProposal( List<Pair<Integer, Integer>> ciphers, List<Integer> integrityAlgos, List<Integer> prfs, List<Integer> dhGroups)226     private static IkeSaProposal buildIkeSaProposal(
227             List<Pair<Integer, Integer>> ciphers,
228             List<Integer> integrityAlgos,
229             List<Integer> prfs,
230             List<Integer> dhGroups) {
231         return buildIkeSaProposal(
232                 ciphers, integrityAlgos, prfs, dhGroups, false /* preferModp1024 */);
233     }
234 
buildIkeSaProposal( List<Pair<Integer, Integer>> ciphers, List<Integer> integrityAlgos, List<Integer> prfs, List<Integer> dhGroups, boolean preferModp1024)235     private static IkeSaProposal buildIkeSaProposal(
236             List<Pair<Integer, Integer>> ciphers,
237             List<Integer> integrityAlgos,
238             List<Integer> prfs,
239             List<Integer> dhGroups,
240             boolean preferModp1024) {
241         IkeSaProposal.Builder builder = new IkeSaProposal.Builder();
242 
243         for (Pair<Integer, Integer> pair : ciphers) {
244             builder.addEncryptionAlgorithm(pair.first, pair.second);
245         }
246         for (int algo : integrityAlgos) {
247             builder.addIntegrityAlgorithm(algo);
248         }
249         for (int algo : prfs) {
250             builder.addPseudorandomFunction(algo);
251         }
252 
253         // Make sure MODP 1024 is the first DH group if preferModp1024 is true
254         if (preferModp1024) {
255             builder.addDhGroup(DH_GROUP_1024_BIT_MODP);
256         }
257         for (int algo : dhGroups) {
258             if (algo != DH_GROUP_1024_BIT_MODP || !preferModp1024) {
259                 builder.addDhGroup(algo);
260             }
261         }
262 
263         return builder.build();
264     }
265 
266     // Package private
buildChildSaProposalWithNormalModeCipher()267     static ChildSaProposal buildChildSaProposalWithNormalModeCipher() {
268         return buildChildSaProposal(
269                 CHILD_NORMAL_MODE_CIPHERS, CHILD_INTEGRITY_ALGOS, DH_GROUPS_WITH_NONE);
270     }
271 
272     // Package private
buildChildSaProposalWithCombinedModeCipher()273     static ChildSaProposal buildChildSaProposalWithCombinedModeCipher() {
274         return buildChildSaProposalWithCombinedModeCipher(true /* hasIntegrityNone */);
275     }
276 
buildChildSaProposalWithCombinedModeCipher( boolean hasIntegrityNone)277     private static ChildSaProposal buildChildSaProposalWithCombinedModeCipher(
278             boolean hasIntegrityNone) {
279         final List<Integer> integerAlgos = new ArrayList<>();
280         if (hasIntegrityNone) {
281             integerAlgos.add(INTEGRITY_ALGORITHM_NONE);
282         }
283 
284         return buildChildSaProposal(CHILD_COMBINED_MODE_CIPHERS, integerAlgos, DH_GROUPS_WITH_NONE);
285     }
286 
buildChildSaProposal( List<Pair<Integer, Integer>> ciphers, List<Integer> integrityAlgos, List<Integer> dhGroups)287     private static ChildSaProposal buildChildSaProposal(
288             List<Pair<Integer, Integer>> ciphers,
289             List<Integer> integrityAlgos,
290             List<Integer> dhGroups) {
291         ChildSaProposal.Builder builder = new ChildSaProposal.Builder();
292 
293         for (Pair<Integer, Integer> pair : ciphers) {
294             builder.addEncryptionAlgorithm(pair.first, pair.second);
295         }
296         for (int algo : integrityAlgos) {
297             builder.addIntegrityAlgorithm(algo);
298         }
299         for (int algo : dhGroups) {
300             builder.addDhGroup(algo);
301         }
302 
303         return builder.build();
304     }
305 
306     // Package private
buildChildSaProposalWithOnlyCiphers()307     static ChildSaProposal buildChildSaProposalWithOnlyCiphers() {
308         return buildChildSaProposal(
309                 CHILD_COMBINED_MODE_CIPHERS, Collections.EMPTY_LIST, Collections.EMPTY_LIST);
310     }
311 
312     @Test
testBuildIkeSaProposalWithNormalModeCipher()313     public void testBuildIkeSaProposalWithNormalModeCipher() {
314         IkeSaProposal saProposal =
315                 buildIkeSaProposalWithNormalModeCipher(false /* preferModp1024 */);
316 
317         assertEquals(IKE_NORMAL_MODE_CIPHERS, saProposal.getEncryptionAlgorithms());
318         assertEquals(IKE_INTEGRITY_ALGOS, saProposal.getIntegrityAlgorithms());
319         assertEquals(PRFS, saProposal.getPseudorandomFunctions());
320         assertEquals(DH_GROUPS, saProposal.getDhGroups());
321     }
322 
323     @Test
testBuildIkeSaProposalWithCombinedModeCipher()324     public void testBuildIkeSaProposalWithCombinedModeCipher() {
325         IkeSaProposal saProposal =
326                 buildIkeSaProposalWithCombinedModeCipher(false /* hasIntegrityNone */);
327 
328         assertEquals(IKE_COMBINED_MODE_CIPHERS, saProposal.getEncryptionAlgorithms());
329         assertEquals(PRFS, saProposal.getPseudorandomFunctions());
330         assertEquals(DH_GROUPS, saProposal.getDhGroups());
331         assertTrue(saProposal.getIntegrityAlgorithms().isEmpty());
332     }
333 
334     @Test
testBuildIkeSaProposalWithCombinedModeCipherAndIntegrityNone()335     public void testBuildIkeSaProposalWithCombinedModeCipherAndIntegrityNone() {
336         IkeSaProposal saProposal =
337                 buildIkeSaProposalWithCombinedModeCipher(true /* hasIntegrityNone */);
338 
339         assertEquals(IKE_COMBINED_MODE_CIPHERS, saProposal.getEncryptionAlgorithms());
340         assertEquals(PRFS, saProposal.getPseudorandomFunctions());
341         assertEquals(DH_GROUPS, saProposal.getDhGroups());
342         assertEquals(Arrays.asList(INTEGRITY_ALGORITHM_NONE), saProposal.getIntegrityAlgorithms());
343     }
344 
345     @Test
testBuildChildSaProposalWithNormalModeCipher()346     public void testBuildChildSaProposalWithNormalModeCipher() {
347         ChildSaProposal saProposal = buildChildSaProposalWithNormalModeCipher();
348 
349         assertEquals(CHILD_NORMAL_MODE_CIPHERS, saProposal.getEncryptionAlgorithms());
350         assertEquals(CHILD_INTEGRITY_ALGOS, saProposal.getIntegrityAlgorithms());
351         assertEquals(DH_GROUPS_WITH_NONE, saProposal.getDhGroups());
352     }
353 
354     @Test
testBuildChildProposalWithCombinedModeCipher()355     public void testBuildChildProposalWithCombinedModeCipher() {
356         ChildSaProposal saProposal =
357                 buildChildSaProposalWithCombinedModeCipher(false /* hasIntegrityNone */);
358 
359         assertEquals(CHILD_COMBINED_MODE_CIPHERS, saProposal.getEncryptionAlgorithms());
360         assertTrue(saProposal.getIntegrityAlgorithms().isEmpty());
361         assertEquals(DH_GROUPS_WITH_NONE, saProposal.getDhGroups());
362     }
363 
364     @Test
testBuildChildProposalWithCombinedModeCipherAndIntegrityNone()365     public void testBuildChildProposalWithCombinedModeCipherAndIntegrityNone() {
366         ChildSaProposal saProposal =
367                 buildChildSaProposalWithCombinedModeCipher(true /* hasIntegrityNone */);
368 
369         assertEquals(CHILD_COMBINED_MODE_CIPHERS, saProposal.getEncryptionAlgorithms());
370         assertEquals(Arrays.asList(INTEGRITY_ALGORITHM_NONE), saProposal.getIntegrityAlgorithms());
371         assertEquals(DH_GROUPS_WITH_NONE, saProposal.getDhGroups());
372     }
373 
374     @Test
testBuildChildSaProposalWithOnlyCiphers()375     public void testBuildChildSaProposalWithOnlyCiphers() {
376         ChildSaProposal saProposal = buildChildSaProposalWithOnlyCiphers();
377 
378         assertEquals(CHILD_COMBINED_MODE_CIPHERS, saProposal.getEncryptionAlgorithms());
379         assertTrue(saProposal.getIntegrityAlgorithms().isEmpty());
380         assertTrue(saProposal.getDhGroups().isEmpty());
381     }
382 
383     private static final String IPSEC_NAME_NA = "";
384 
385     private static class CryptoInfo {
386         public final int minSdk;
387         public final String ipSecName;
388 
CryptoInfo(int minSdk, String ipSecName)389         CryptoInfo(int minSdk, String ipSecName) {
390             this.minSdk = minSdk;
391             this.ipSecName = ipSecName;
392         }
393     }
394 
395     private static final Map<Integer, CryptoInfo> ALL_ENCRYPT_ALGOS = getAllCiphers();
396     private static final Map<Integer, CryptoInfo> ALL_INTEGRITY_ALGOS = getAllIntegrityAlgos();
397     private static final Map<Integer, Integer> ALL_DH_GROUPS = getAllDhGroups();
398     private static final Map<Integer, Integer> ALL_PRFS = getAllPrfs();
399 
getAllCiphers()400     private static Map<Integer, CryptoInfo> getAllCiphers() {
401         final Map<Integer, CryptoInfo> ciphers = new HashMap<>();
402         ciphers.put(ENCRYPTION_ALGORITHM_3DES, new CryptoInfo(R, IPSEC_NAME_NA));
403         ciphers.put(ENCRYPTION_ALGORITHM_AES_CBC, new CryptoInfo(R, CRYPT_AES_CBC));
404         ciphers.put(ENCRYPTION_ALGORITHM_AES_CTR, new CryptoInfo(R, CRYPT_AES_CTR));
405         ciphers.put(ENCRYPTION_ALGORITHM_AES_GCM_8, new CryptoInfo(R, AUTH_CRYPT_AES_GCM));
406         ciphers.put(ENCRYPTION_ALGORITHM_AES_GCM_12, new CryptoInfo(R, AUTH_CRYPT_AES_GCM));
407         ciphers.put(ENCRYPTION_ALGORITHM_AES_GCM_16, new CryptoInfo(R, AUTH_CRYPT_AES_GCM));
408         ciphers.put(
409                 ENCRYPTION_ALGORITHM_CHACHA20_POLY1305,
410                 new CryptoInfo(R, AUTH_CRYPT_CHACHA20_POLY1305));
411         return ciphers;
412     }
413 
getAllIntegrityAlgos()414     private static Map<Integer, CryptoInfo> getAllIntegrityAlgos() {
415         final Map<Integer, CryptoInfo> integrityAlgos = new HashMap<>();
416         integrityAlgos.put(INTEGRITY_ALGORITHM_NONE, new CryptoInfo(R, IPSEC_NAME_NA));
417         integrityAlgos.put(INTEGRITY_ALGORITHM_HMAC_SHA1_96, new CryptoInfo(R, AUTH_HMAC_SHA1));
418         integrityAlgos.put(INTEGRITY_ALGORITHM_AES_XCBC_96, new CryptoInfo(R, AUTH_AES_XCBC));
419         integrityAlgos.put(
420                 INTEGRITY_ALGORITHM_HMAC_SHA2_256_128, new CryptoInfo(R, AUTH_HMAC_SHA256));
421         integrityAlgos.put(
422                 INTEGRITY_ALGORITHM_HMAC_SHA2_384_192, new CryptoInfo(R, AUTH_HMAC_SHA384));
423         integrityAlgos.put(
424                 INTEGRITY_ALGORITHM_HMAC_SHA2_512_256, new CryptoInfo(R, AUTH_HMAC_SHA512));
425         integrityAlgos.put(INTEGRITY_ALGORITHM_AES_CMAC_96, new CryptoInfo(S, AUTH_AES_CMAC));
426 
427         return integrityAlgos;
428     }
429 
getAllDhGroups()430     private static Map<Integer, Integer> getAllDhGroups() {
431         final Map<Integer, Integer> dhGroups = new HashMap<>();
432         dhGroups.put(DH_GROUP_NONE, R);
433         dhGroups.put(DH_GROUP_1024_BIT_MODP, R);
434         dhGroups.put(DH_GROUP_1536_BIT_MODP, R);
435         dhGroups.put(DH_GROUP_2048_BIT_MODP, R);
436         dhGroups.put(DH_GROUP_3072_BIT_MODP, R);
437         dhGroups.put(DH_GROUP_4096_BIT_MODP, R);
438         dhGroups.put(DH_GROUP_CURVE_25519, S);
439         return dhGroups;
440     }
441 
getAllPrfs()442     private static Map<Integer, Integer> getAllPrfs() {
443         final Map<Integer, Integer> prfs = new HashMap<>();
444         prfs.put(PSEUDORANDOM_FUNCTION_HMAC_SHA1, R);
445         prfs.put(PSEUDORANDOM_FUNCTION_AES128_XCBC, R);
446         prfs.put(PSEUDORANDOM_FUNCTION_SHA2_256, R);
447         prfs.put(PSEUDORANDOM_FUNCTION_SHA2_384, R);
448         prfs.put(PSEUDORANDOM_FUNCTION_SHA2_512, R);
449         prfs.put(PSEUDORANDOM_FUNCTION_AES128_CMAC, S);
450         return prfs;
451     }
452 
getExpectedSupportedCryptoAlgorithms( Map<Integer, CryptoInfo> algoMap, int sdkLevel)453     private static Set<Integer> getExpectedSupportedCryptoAlgorithms(
454             Map<Integer, CryptoInfo> algoMap, int sdkLevel) {
455         final Set<Integer> supportedSet = new HashSet<>();
456         for (Entry<Integer, CryptoInfo> entry : algoMap.entrySet()) {
457             if (sdkLevel >= entry.getValue().minSdk) {
458                 supportedSet.add(entry.getKey());
459             }
460         }
461 
462         return supportedSet;
463     }
464 
getExpectedSupportedDhOrPrf( Map<Integer, Integer> algoMap, int sdkLevel)465     private static Set<Integer> getExpectedSupportedDhOrPrf(
466             Map<Integer, Integer> algoMap, int sdkLevel) {
467         final Set<Integer> supportedSet = new HashSet<>();
468         for (Entry<Integer, Integer> entry : algoMap.entrySet()) {
469             if (sdkLevel >= entry.getValue()) {
470                 supportedSet.add(entry.getKey());
471             }
472         }
473 
474         return supportedSet;
475     }
476 
checkGetSupportedIkeSaAlgos(int sdkLevel)477     private static void checkGetSupportedIkeSaAlgos(int sdkLevel) {
478         assertEquals(
479                 getExpectedSupportedCryptoAlgorithms(ALL_ENCRYPT_ALGOS, sdkLevel),
480                 IkeSaProposal.getSupportedEncryptionAlgorithms());
481         assertEquals(
482                 getExpectedSupportedCryptoAlgorithms(ALL_INTEGRITY_ALGOS, sdkLevel),
483                 IkeSaProposal.getSupportedIntegrityAlgorithms());
484         assertEquals(
485                 getExpectedSupportedDhOrPrf(ALL_DH_GROUPS, sdkLevel),
486                 IkeSaProposal.getSupportedDhGroups());
487         assertEquals(
488                 getExpectedSupportedDhOrPrf(ALL_PRFS, sdkLevel),
489                 IkeSaProposal.getSupportedPseudorandomFunctions());
490     }
491 
492     @Test
testGetSupportedIkeAlgosOnReleasedSdk()493     public void testGetSupportedIkeAlgosOnReleasedSdk() {
494         // It is a release branch.
495         assumeTrue("REL".equals(CODENAME));
496         checkGetSupportedIkeSaAlgos(SDK_INT);
497     }
498 
499     @Test
testGetSupportedIkeAlgosOnPrereleasedSdk()500     public void testGetSupportedIkeAlgosOnPrereleasedSdk() {
501         // On a pre-released branch, the VERSION.SDK_INT is still the previous version code, and the
502         // value of the current version code is CUR_DEVELOPMENT. For example, on an S development
503         // branch, VERSION.SDK_INT is still VERSION_CODES.R (30), and VERSION_CODES.S is
504         // CUR_DEVELOPMENT (1000).
505         assumeFalse("REL".equals(CODENAME));
506         checkGetSupportedIkeSaAlgos(CUR_DEVELOPMENT);
507     }
508 
checkGetSupportedChildSaAlgos(Set<String> expectedAlgos)509     private static void checkGetSupportedChildSaAlgos(Set<String> expectedAlgos) {
510         final Set<String> supportedIpSecAlgos = new HashSet<>();
511 
512         for (int algo : ChildSaProposal.getSupportedEncryptionAlgorithms()) {
513             supportedIpSecAlgos.add(ALL_ENCRYPT_ALGOS.get(algo).ipSecName);
514         }
515 
516         for (int algo : ChildSaProposal.getSupportedIntegrityAlgorithms()) {
517             if (algo != INTEGRITY_ALGORITHM_NONE) {
518                 supportedIpSecAlgos.add(ALL_INTEGRITY_ALGOS.get(algo).ipSecName);
519             }
520         }
521         assertEquals(expectedAlgos, supportedIpSecAlgos);
522     }
523 
524     @Test
525     @IgnoreUpTo(R)
testGetSupportedChildAlgosAtLeastSdkS()526     public void testGetSupportedChildAlgosAtLeastSdkS() {
527         // MD5 is not allowed by IKE for security reasons
528         final Set<String> expectedAlgos = new HashSet<>();
529         expectedAlgos.addAll(IpSecAlgorithm.getSupportedAlgorithms());
530         expectedAlgos.remove(AUTH_HMAC_MD5);
531 
532         checkGetSupportedChildSaAlgos(expectedAlgos);
533     }
534 
535     @Test
536     @IgnoreAfter(R)
testGetSupportedChildAlgosPreS()537     public void testGetSupportedChildAlgosPreS() {
538         final Set<String> expectedAlgos = new HashSet<>();
539         expectedAlgos.add(ALL_ENCRYPT_ALGOS.get(ENCRYPTION_ALGORITHM_AES_CBC).ipSecName);
540         expectedAlgos.add(ALL_ENCRYPT_ALGOS.get(ENCRYPTION_ALGORITHM_AES_GCM_8).ipSecName);
541         expectedAlgos.add(ALL_ENCRYPT_ALGOS.get(ENCRYPTION_ALGORITHM_AES_GCM_12).ipSecName);
542         expectedAlgos.add(ALL_ENCRYPT_ALGOS.get(ENCRYPTION_ALGORITHM_AES_GCM_16).ipSecName);
543 
544         expectedAlgos.add(ALL_INTEGRITY_ALGOS.get(INTEGRITY_ALGORITHM_HMAC_SHA1_96).ipSecName);
545         expectedAlgos.add(ALL_INTEGRITY_ALGOS.get(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128).ipSecName);
546         expectedAlgos.add(ALL_INTEGRITY_ALGOS.get(INTEGRITY_ALGORITHM_HMAC_SHA2_384_192).ipSecName);
547         expectedAlgos.add(ALL_INTEGRITY_ALGOS.get(INTEGRITY_ALGORITHM_HMAC_SHA2_512_256).ipSecName);
548 
549         checkGetSupportedChildSaAlgos(expectedAlgos);
550     }
551 
552     // TODO(b/148689509): Test throwing exception when algorithm combination is invalid
553 }
554