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