• 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.net.cts;
18 
19 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
20 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
21 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
22 import static android.net.cts.util.CtsNetUtils.TestNetworkCallback;
23 
24 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
25 import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
26 import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
27 
28 import static org.junit.Assert.assertArrayEquals;
29 import static org.junit.Assert.assertEquals;
30 import static org.junit.Assert.assertFalse;
31 import static org.junit.Assert.assertNotNull;
32 import static org.junit.Assert.assertNull;
33 import static org.junit.Assert.assertThrows;
34 import static org.junit.Assert.assertTrue;
35 import static org.junit.Assert.fail;
36 import static org.junit.Assume.assumeTrue;
37 
38 import android.Manifest;
39 import android.annotation.NonNull;
40 import android.app.AppOpsManager;
41 import android.content.Context;
42 import android.content.Intent;
43 import android.net.ConnectivityManager;
44 import android.net.Ikev2VpnProfile;
45 import android.net.IpSecAlgorithm;
46 import android.net.Network;
47 import android.net.NetworkRequest;
48 import android.net.ProxyInfo;
49 import android.net.TestNetworkInterface;
50 import android.net.VpnManager;
51 import android.net.cts.util.CtsNetUtils;
52 import android.net.cts.util.IkeSessionTestUtils;
53 import android.net.ipsec.ike.IkeTunnelConnectionParams;
54 import android.os.Build;
55 import android.os.Process;
56 import android.platform.test.annotations.AppModeFull;
57 import android.text.TextUtils;
58 
59 import androidx.test.InstrumentationRegistry;
60 
61 import com.android.internal.util.HexDump;
62 import com.android.networkstack.apishim.ConstantsShim;
63 import com.android.networkstack.apishim.Ikev2VpnProfileBuilderShimImpl;
64 import com.android.networkstack.apishim.Ikev2VpnProfileShimImpl;
65 import com.android.networkstack.apishim.VpnManagerShimImpl;
66 import com.android.networkstack.apishim.common.Ikev2VpnProfileBuilderShim;
67 import com.android.networkstack.apishim.common.Ikev2VpnProfileShim;
68 import com.android.networkstack.apishim.common.VpnManagerShim;
69 import com.android.networkstack.apishim.common.VpnProfileStateShim;
70 import com.android.testutils.DevSdkIgnoreRule;
71 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
72 import com.android.testutils.DevSdkIgnoreRunner;
73 import com.android.testutils.RecorderCallback.CallbackEntry;
74 import com.android.testutils.TestableNetworkCallback;
75 
76 import org.bouncycastle.x509.X509V1CertificateGenerator;
77 import org.junit.After;
78 import org.junit.Rule;
79 import org.junit.Test;
80 import org.junit.runner.RunWith;
81 
82 import java.math.BigInteger;
83 import java.net.InetAddress;
84 import java.security.KeyPair;
85 import java.security.KeyPairGenerator;
86 import java.security.PrivateKey;
87 import java.security.cert.X509Certificate;
88 import java.util.ArrayList;
89 import java.util.Arrays;
90 import java.util.Date;
91 import java.util.List;
92 import java.util.concurrent.TimeUnit;
93 
94 import javax.security.auth.x500.X500Principal;
95 
96 @RunWith(DevSdkIgnoreRunner.class)
97 @IgnoreUpTo(Build.VERSION_CODES.Q)
98 @AppModeFull(reason = "Appops state changes disallowed for instant apps (OP_ACTIVATE_PLATFORM_VPN)")
99 public class Ikev2VpnTest {
100     private static final String TAG = Ikev2VpnTest.class.getSimpleName();
101 
102     @Rule
103     public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
104 
105     // Test vectors for IKE negotiation in test mode.
106     private static final String SUCCESSFUL_IKE_INIT_RESP_V4 =
107             "46b8eca1e0d72a18b2b5d9006d47a0022120222000000000000002d0220000300000002c01010004030000"
108                     + "0c0100000c800e0100030000080300000c030000080200000400000008040000102800020800"
109                     + "100000b8070f159fe5141d8754ca86f72ecc28d66f514927e96cbe9eec0adb42bf2c276a0ab7"
110                     + "a97fa93555f4be9218c14e7f286bb28c6b4fb13825a420f2ffc165854f200bab37d69c8963d4"
111                     + "0acb831d983163aa50622fd35c182efe882cf54d6106222abcfaa597255d302f1b95ab71c142"
112                     + "c279ea5839a180070bff73f9d03fab815f0d5ee2adec7e409d1e35979f8bd92ffd8aab13d1a0"
113                     + "0657d816643ae767e9ae84d2ccfa2bcce1a50572be8d3748ae4863c41ae90da16271e014270f"
114                     + "77edd5cd2e3299f3ab27d7203f93d770bacf816041cdcecd0f9af249033979da4369cb242dd9"
115                     + "6d172e60513ff3db02de63e50eb7d7f596ada55d7946cad0af0669d1f3e2804846ab3f2a930d"
116                     + "df56f7f025f25c25ada694e6231abbb87ee8cfd072c8481dc0b0f6b083fdc3bd89b080e49feb"
117                     + "0288eef6fdf8a26ee2fc564a11e7385215cf2deaf2a9965638fc279c908ccdf04094988d91a2"
118                     + "464b4a8c0326533aff5119ed79ecbd9d99a218b44f506a5eb09351e67da86698b4c58718db25"
119                     + "d55f426fb4c76471b27a41fbce00777bc233c7f6e842e39146f466826de94f564cad8b92bfbe"
120                     + "87c99c4c7973ec5f1eea8795e7da82819753aa7c4fcfdab77066c56b939330c4b0d354c23f83"
121                     + "ea82fa7a64c4b108f1188379ea0eb4918ee009d804100e6bf118771b9058d42141c847d5ec37"
122                     + "6e5ec591c71fc9dac01063c2bd31f9c783b28bf1182900002430f3d5de3449462b31dd28bc27"
123                     + "297b6ad169bccce4f66c5399c6e0be9120166f2900001c0000400428b8df2e66f69c8584a186"
124                     + "c5eac66783551d49b72900001c000040054e7a622e802d5cbfb96d5f30a6e433994370173529"
125                     + "0000080000402e290000100000402f00020003000400050000000800004014";
126     private static final String SUCCESSFUL_IKE_INIT_RESP_V6 =
127             "46b8eca1e0d72a1800d9ea1babce26bf2120222000000000000002d0220000300000002c01010004030000"
128                     + "0c0100000c800e0100030000080300000c030000080200000400000008040000102800020800"
129                     + "100000ea0e6dd9ca5930a9a45c323a41f64bfd8cdef7730f5fbff37d7c377da427f489a42aa8"
130                     + "c89233380e6e925990d49de35c2cdcf63a61302c731a4b3569df1ee1bf2457e55a6751838ede"
131                     + "abb75cc63ba5c9e4355e8e784f383a5efe8a44727dc14aeaf8dacc2620fb1c8875416dc07739"
132                     + "7fe4decc1bd514a9c7d270cf21fd734c63a25c34b30b68686e54e8a198f37f27cb491fe27235"
133                     + "fab5476b036d875ccab9a68d65fbf3006197f9bebbf94de0d3802b4fafe1d48d931ce3a1a346"
134                     + "2d65bd639e9bd7fa46299650a9dbaf9b324e40b466942d91a59f41ef8042f8474c4850ed0f63"
135                     + "e9238949d41cd8bbaea9aefdb65443a6405792839563aa5dc5c36b5ce8326ccf8a94d9622b85"
136                     + "038d390d5fc0299e14e1f022966d4ac66515f6108ca04faec44821fe5bbf2ed4f84ff5671219"
137                     + "608cb4c36b44a31ba010c9088f8d5ff943bb9ff857f74be1755f57a5783874adc57f42bb174e"
138                     + "4ad3215de628707014dbcb1707bd214658118fdd7a42b3e1638b991ce5b812a667f1145be811"
139                     + "685e3cd3baf9b18d062657b64c206a4d19a531c252a6a51a04aeaf42c618620cdbab65baca23"
140                     + "82c57ed888422aeaacf7f1bc3fe2247ff7e7eaca218b74d7b31d02f2b0afa123f802529e7e6c"
141                     + "3259d418290740ddbf55686e26998d7edcbbf895664972fed666f2f20af40503aa2af436ec6d"
142                     + "4ec981ab19b9088755d94ae7a7c2066ea331d4e56e290000243fefe5555fce552d57a84e682c"
143                     + "d4a6dfb3f2f94a94464d5bec3d88b88e9559642900001c00004004eb4afff764e7b79bca78b1"
144                     + "3a89100d36d678ae982900001c00004005d177216a3c26f782076e12570d40bfaaa148822929"
145                     + "0000080000402e290000100000402f00020003000400050000000800004014";
146     private static final String SUCCESSFUL_IKE_AUTH_RESP_V4 =
147             "46b8eca1e0d72a18b2b5d9006d47a0022e20232000000001000000e0240000c420a2500a3da4c66fa6929e"
148                     + "600f36349ba0e38de14f78a3ad0416cba8c058735712a3d3f9a0a6ed36de09b5e9e02697e7c4"
149                     + "2d210ac86cfbd709503cfa51e2eab8cfdc6427d136313c072968f6506a546eb5927164200592"
150                     + "6e36a16ee994e63f029432a67bc7d37ca619e1bd6e1678df14853067ecf816b48b81e8746069"
151                     + "406363e5aa55f13cb2afda9dbebee94256c29d630b17dd7f1ee52351f92b6e1c3d8551c513f1"
152                     + "d74ac52a80b2041397e109fe0aeb3c105b0d4be0ae343a943398764281";
153     private static final String SUCCESSFUL_IKE_AUTH_RESP_V6 =
154             "46b8eca1e0d72a1800d9ea1babce26bf2e20232000000001000000f0240000d4aaf6eaa6c06b50447e6f54"
155                     + "827fd8a9d9d6ac8015c1ebb3e8cb03fc6e54b49a107441f50004027cc5021600828026367f03"
156                     + "bc425821cd7772ee98637361300c9b76056e874fea2bd4a17212370b291894264d8c023a01d1"
157                     + "c3b691fd4b7c0b534e8c95af4c4638e2d125cb21c6267e2507cd745d72e8da109c47b9259c6c"
158                     + "57a26f6bc5b337b9b9496d54bdde0333d7a32e6e1335c9ee730c3ecd607a8689aa7b0577b74f"
159                     + "3bf437696a9fd5fc0aee3ed346cd9e15d1dda293df89eb388a8719388a60ca7625754de12cdb"
160                     + "efe4c886c5c401";
161     private static final long IKE_INITIATOR_SPI = Long.parseLong("46B8ECA1E0D72A18", 16);
162 
163     private static final InetAddress LOCAL_OUTER_4 = InetAddress.parseNumericAddress("192.0.2.1");
164     private static final InetAddress LOCAL_OUTER_6 =
165             InetAddress.parseNumericAddress("2001:db8::1");
166 
167     private static final int IP4_PREFIX_LEN = 32;
168     private static final int IP6_PREFIX_LEN = 128;
169 
170     // TODO: Use IPv6 address when we can generate test vectors (GCE does not allow IPv6 yet).
171     private static final String TEST_SERVER_ADDR_V4 = "192.0.2.2";
172     private static final String TEST_SERVER_ADDR_V6 = "2001:db8::2";
173     private static final String TEST_IDENTITY = "client.cts.android.com";
174     private static final List<String> TEST_ALLOWED_ALGORITHMS =
175             Arrays.asList(IpSecAlgorithm.AUTH_CRYPT_AES_GCM);
176 
177     private static final ProxyInfo TEST_PROXY_INFO =
178             ProxyInfo.buildDirectProxy("proxy.cts.android.com", 1234);
179     private static final int TEST_MTU = 1300;
180 
181     private static final byte[] TEST_PSK = "ikeAndroidPsk".getBytes();
182     private static final String TEST_USER = "username";
183     private static final String TEST_PASSWORD = "pa55w0rd";
184 
185     // Static state to reduce setup/teardown
186     private static final Context sContext = InstrumentationRegistry.getContext();
187     private static final ConnectivityManager sCM =
188             (ConnectivityManager) sContext.getSystemService(Context.CONNECTIVITY_SERVICE);
189     private static final VpnManager sVpnMgr =
190             (VpnManager) sContext.getSystemService(Context.VPN_MANAGEMENT_SERVICE);
191     private static final CtsNetUtils mCtsNetUtils = new CtsNetUtils(sContext);
192     private static final long TIMEOUT_MS = 15_000;
193 
194     private VpnManagerShim mVmShim = VpnManagerShimImpl.newInstance(sContext);
195 
196     private final X509Certificate mServerRootCa;
197     private final CertificateAndKey mUserCertKey;
198     private final List<TestableNetworkCallback> mCallbacksToUnregister = new ArrayList<>();
199 
Ikev2VpnTest()200     public Ikev2VpnTest() throws Exception {
201         // Build certificates
202         mServerRootCa = generateRandomCertAndKeyPair().cert;
203         mUserCertKey = generateRandomCertAndKeyPair();
204     }
205 
206     @After
tearDown()207     public void tearDown() {
208         for (TestableNetworkCallback callback : mCallbacksToUnregister) {
209             sCM.unregisterNetworkCallback(callback);
210         }
211         setAppop(AppOpsManager.OP_ACTIVATE_VPN, false);
212         setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, false);
213     }
214 
215     /**
216      * Sets the given appop using shell commands
217      *
218      * <p>This method must NEVER be called from within a shell permission, as it will attempt to
219      * acquire, and then drop the shell permission identity. This results in the caller losing the
220      * shell permission identity due to these calls not being reference counted.
221      */
setAppop(int appop, boolean allow)222     public void setAppop(int appop, boolean allow) {
223         // Requires shell permission to update appops.
224         runWithShellPermissionIdentity(() -> {
225             mCtsNetUtils.setAppopPrivileged(appop, allow);
226         }, Manifest.permission.MANAGE_TEST_NETWORKS);
227     }
228 
buildIkev2VpnProfileCommon( @onNull Ikev2VpnProfileBuilderShim builderShim, boolean isRestrictedToTestNetworks, boolean requiresValidation, boolean automaticIpVersionSelectionEnabled, boolean automaticNattKeepaliveTimerEnabled)229     private Ikev2VpnProfile buildIkev2VpnProfileCommon(
230             @NonNull Ikev2VpnProfileBuilderShim builderShim, boolean isRestrictedToTestNetworks,
231             boolean requiresValidation, boolean automaticIpVersionSelectionEnabled,
232             boolean automaticNattKeepaliveTimerEnabled) throws Exception {
233 
234         builderShim.setBypassable(true)
235                 .setAllowedAlgorithms(TEST_ALLOWED_ALGORITHMS)
236                 .setProxy(TEST_PROXY_INFO)
237                 .setMaxMtu(TEST_MTU)
238                 .setMetered(false);
239         if (TestUtils.shouldTestTApis()) {
240             builderShim.setRequiresInternetValidation(requiresValidation);
241         }
242 
243         if (TestUtils.shouldTestUApis()) {
244             builderShim.setAutomaticIpVersionSelectionEnabled(automaticIpVersionSelectionEnabled);
245             builderShim.setAutomaticNattKeepaliveTimerEnabled(automaticNattKeepaliveTimerEnabled);
246         }
247 
248         // Convert shim back to Ikev2VpnProfile.Builder since restrictToTestNetworks is a hidden
249         // method and is not defined in shims.
250         // TODO: replace it in alternative way to remove the hidden method usage
251         final Ikev2VpnProfile.Builder builder = (Ikev2VpnProfile.Builder) builderShim.getBuilder();
252         if (isRestrictedToTestNetworks) {
253             builder.restrictToTestNetworks();
254         }
255 
256         return builder.build();
257     }
258 
buildIkev2VpnProfileIkeTunConnParams( final boolean isRestrictedToTestNetworks, final boolean requiresValidation, final boolean testIpv6)259     private Ikev2VpnProfile buildIkev2VpnProfileIkeTunConnParams(
260             final boolean isRestrictedToTestNetworks, final boolean requiresValidation,
261             final boolean testIpv6) throws Exception {
262         final IkeTunnelConnectionParams params =
263                 new IkeTunnelConnectionParams(testIpv6
264                         ? IkeSessionTestUtils.IKE_PARAMS_V6 : IkeSessionTestUtils.IKE_PARAMS_V4,
265                         IkeSessionTestUtils.CHILD_PARAMS);
266 
267         final Ikev2VpnProfileBuilderShim builderShim =
268                 Ikev2VpnProfileBuilderShimImpl.newInstance(params)
269                         .setRequiresInternetValidation(requiresValidation)
270                         .setProxy(TEST_PROXY_INFO)
271                         .setMaxMtu(TEST_MTU)
272                         .setMetered(false);
273         // Convert shim back to Ikev2VpnProfile.Builder since restrictToTestNetworks is a hidden
274         // method and is not defined in shims.
275         // TODO: replace it in alternative way to remove the hidden method usage
276         final Ikev2VpnProfile.Builder builder = (Ikev2VpnProfile.Builder) builderShim.getBuilder();
277         if (isRestrictedToTestNetworks) {
278             builder.restrictToTestNetworks();
279         }
280         return builder.build();
281     }
282 
buildIkev2VpnProfilePsk(@onNull String remote, boolean isRestrictedToTestNetworks, boolean requiresValidation)283     private Ikev2VpnProfile buildIkev2VpnProfilePsk(@NonNull String remote,
284             boolean isRestrictedToTestNetworks, boolean requiresValidation)
285             throws Exception {
286         final Ikev2VpnProfileBuilderShim builder =
287                 Ikev2VpnProfileBuilderShimImpl.newInstance(remote, TEST_IDENTITY)
288                         .setAuthPsk(TEST_PSK);
289         return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks,
290                 requiresValidation, false /* automaticIpVersionSelectionEnabled */,
291                 false /* automaticNattKeepaliveTimerEnabled */);
292     }
293 
buildIkev2VpnProfileUsernamePassword(boolean isRestrictedToTestNetworks)294     private Ikev2VpnProfile buildIkev2VpnProfileUsernamePassword(boolean isRestrictedToTestNetworks)
295             throws Exception {
296         final Ikev2VpnProfileBuilderShim builder =
297                 Ikev2VpnProfileBuilderShimImpl.newInstance(TEST_SERVER_ADDR_V6, TEST_IDENTITY)
298                         .setAuthUsernamePassword(TEST_USER, TEST_PASSWORD, mServerRootCa);
299         return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks,
300                 false /* requiresValidation */, false /* automaticIpVersionSelectionEnabled */,
301                 false /* automaticNattKeepaliveTimerEnabled */);
302     }
303 
buildIkev2VpnProfileDigitalSignature(boolean isRestrictedToTestNetworks)304     private Ikev2VpnProfile buildIkev2VpnProfileDigitalSignature(boolean isRestrictedToTestNetworks)
305             throws Exception {
306         final Ikev2VpnProfileBuilderShim builder =
307                 Ikev2VpnProfileBuilderShimImpl.newInstance(TEST_SERVER_ADDR_V6, TEST_IDENTITY)
308                         .setAuthDigitalSignature(
309                                 mUserCertKey.cert, mUserCertKey.key, mServerRootCa);
310         return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks,
311                 false /* requiresValidation */, false /* automaticIpVersionSelectionEnabled */,
312                 false /* automaticNattKeepaliveTimerEnabled */);
313     }
314 
checkBasicIkev2VpnProfile(@onNull Ikev2VpnProfile profile)315     private void checkBasicIkev2VpnProfile(@NonNull Ikev2VpnProfile profile) throws Exception {
316         assertEquals(TEST_SERVER_ADDR_V6, profile.getServerAddr());
317         assertEquals(TEST_IDENTITY, profile.getUserIdentity());
318         assertEquals(TEST_PROXY_INFO, profile.getProxyInfo());
319         assertEquals(TEST_ALLOWED_ALGORITHMS, profile.getAllowedAlgorithms());
320         assertTrue(profile.isBypassable());
321         assertFalse(profile.isMetered());
322         assertEquals(TEST_MTU, profile.getMaxMtu());
323         assertFalse(profile.isRestrictedToTestNetworks());
324     }
325 
doTestBuildIkev2VpnProfilePsk(final boolean requiresValidation)326     public void doTestBuildIkev2VpnProfilePsk(final boolean requiresValidation) throws Exception {
327         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
328 
329         final Ikev2VpnProfile profile = buildIkev2VpnProfilePsk(TEST_SERVER_ADDR_V6,
330                 false /* isRestrictedToTestNetworks */, requiresValidation);
331 
332         checkBasicIkev2VpnProfile(profile);
333         assertArrayEquals(TEST_PSK, profile.getPresharedKey());
334 
335         // Verify nothing else is set.
336         assertNull(profile.getUsername());
337         assertNull(profile.getPassword());
338         assertNull(profile.getServerRootCaCert());
339         assertNull(profile.getRsaPrivateKey());
340         assertNull(profile.getUserCert());
341         if (isAtLeastT()) {
342             assertEquals(requiresValidation, profile.isInternetValidationRequired());
343         }
344     }
345 
346     @IgnoreUpTo(SC_V2)
347     @Test
testBuildIkev2VpnProfileWithIkeTunnelConnectionParams()348     public void testBuildIkev2VpnProfileWithIkeTunnelConnectionParams() throws Exception {
349         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
350         assumeTrue(TestUtils.shouldTestTApis());
351 
352         final IkeTunnelConnectionParams expectedParams = new IkeTunnelConnectionParams(
353                 IkeSessionTestUtils.IKE_PARAMS_V6, IkeSessionTestUtils.CHILD_PARAMS);
354         final Ikev2VpnProfile.Builder ikeProfileBuilder =
355                 new Ikev2VpnProfile.Builder(expectedParams);
356         // Verify the other Ike options could not be set with IkeTunnelConnectionParams.
357         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
358         assertThrows(expected, () -> ikeProfileBuilder.setAuthPsk(TEST_PSK));
359         assertThrows(expected, () ->
360                 ikeProfileBuilder.setAuthUsernamePassword(TEST_USER, TEST_PASSWORD, mServerRootCa));
361         assertThrows(expected, () -> ikeProfileBuilder.setAuthDigitalSignature(
362                 mUserCertKey.cert, mUserCertKey.key, mServerRootCa));
363 
364         final Ikev2VpnProfile profile = ikeProfileBuilder.build();
365 
366         assertEquals(expectedParams, profile.getIkeTunnelConnectionParams());
367     }
368 
369     @Test
testBuildIkev2VpnProfilePsk()370     public void testBuildIkev2VpnProfilePsk() throws Exception {
371         doTestBuildIkev2VpnProfilePsk(true /* requiresValidation */);
372         doTestBuildIkev2VpnProfilePsk(false /* requiresValidation */);
373     }
374 
375     @Test
testBuildIkev2VpnProfileUsernamePassword()376     public void testBuildIkev2VpnProfileUsernamePassword() throws Exception {
377         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
378 
379         final Ikev2VpnProfile profile =
380                 buildIkev2VpnProfileUsernamePassword(false /* isRestrictedToTestNetworks */);
381 
382         checkBasicIkev2VpnProfile(profile);
383         assertEquals(TEST_USER, profile.getUsername());
384         assertEquals(TEST_PASSWORD, profile.getPassword());
385         assertEquals(mServerRootCa, profile.getServerRootCaCert());
386 
387         // Verify nothing else is set.
388         assertNull(profile.getPresharedKey());
389         assertNull(profile.getRsaPrivateKey());
390         assertNull(profile.getUserCert());
391     }
392 
393     @Test
testBuildIkev2VpnProfileDigitalSignature()394     public void testBuildIkev2VpnProfileDigitalSignature() throws Exception {
395         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
396 
397         final Ikev2VpnProfile profile =
398                 buildIkev2VpnProfileDigitalSignature(false /* isRestrictedToTestNetworks */);
399 
400         checkBasicIkev2VpnProfile(profile);
401         assertEquals(mUserCertKey.cert, profile.getUserCert());
402         assertEquals(mUserCertKey.key, profile.getRsaPrivateKey());
403         assertEquals(mServerRootCa, profile.getServerRootCaCert());
404 
405         // Verify nothing else is set.
406         assertNull(profile.getUsername());
407         assertNull(profile.getPassword());
408         assertNull(profile.getPresharedKey());
409     }
410 
verifyProvisionVpnProfile( boolean hasActivateVpn, boolean hasActivatePlatformVpn, boolean expectIntent)411     private void verifyProvisionVpnProfile(
412             boolean hasActivateVpn, boolean hasActivatePlatformVpn, boolean expectIntent)
413             throws Exception {
414         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
415 
416         setAppop(AppOpsManager.OP_ACTIVATE_VPN, hasActivateVpn);
417         setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, hasActivatePlatformVpn);
418 
419         final Ikev2VpnProfile profile = buildIkev2VpnProfilePsk(TEST_SERVER_ADDR_V6,
420                 false /* isRestrictedToTestNetworks */, false /* requiresValidation */);
421         final Intent intent = sVpnMgr.provisionVpnProfile(profile);
422         assertEquals(expectIntent, intent != null);
423     }
424 
425     @Test
testProvisionVpnProfileNoPreviousConsent()426     public void testProvisionVpnProfileNoPreviousConsent() throws Exception {
427         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
428 
429         verifyProvisionVpnProfile(false /* hasActivateVpn */,
430                 false /* hasActivatePlatformVpn */, true /* expectIntent */);
431     }
432 
433     @Test
testProvisionVpnProfilePlatformVpnConsented()434     public void testProvisionVpnProfilePlatformVpnConsented() throws Exception {
435         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
436 
437         verifyProvisionVpnProfile(false /* hasActivateVpn */,
438                 true /* hasActivatePlatformVpn */, false /* expectIntent */);
439     }
440 
441     @Test
testProvisionVpnProfileVpnServiceConsented()442     public void testProvisionVpnProfileVpnServiceConsented() throws Exception {
443         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
444 
445         verifyProvisionVpnProfile(true /* hasActivateVpn */,
446                 false /* hasActivatePlatformVpn */, false /* expectIntent */);
447     }
448 
449     @Test
testProvisionVpnProfileAllPreConsented()450     public void testProvisionVpnProfileAllPreConsented() throws Exception {
451         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
452 
453         verifyProvisionVpnProfile(true /* hasActivateVpn */,
454                 true /* hasActivatePlatformVpn */, false /* expectIntent */);
455     }
456 
457     @Test
testDeleteVpnProfile()458     public void testDeleteVpnProfile() throws Exception {
459         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
460 
461         setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, true);
462 
463         final Ikev2VpnProfile profile = buildIkev2VpnProfilePsk(TEST_SERVER_ADDR_V6,
464                 false /* isRestrictedToTestNetworks */, false /* requiresValidation */);
465         assertNull(sVpnMgr.provisionVpnProfile(profile));
466 
467         // Verify that deleting the profile works (even without the appop)
468         setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, false);
469         sVpnMgr.deleteProvisionedVpnProfile();
470 
471         // Test that the profile was deleted - starting it should throw an IAE.
472         try {
473             setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, true);
474             sVpnMgr.startProvisionedVpnProfile();
475             fail("Expected IllegalArgumentException due to missing profile");
476         } catch (IllegalArgumentException expected) {
477         }
478     }
479 
480     @Test
testStartVpnProfileNoPreviousConsent()481     public void testStartVpnProfileNoPreviousConsent() throws Exception {
482         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
483 
484         setAppop(AppOpsManager.OP_ACTIVATE_VPN, false);
485         setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, false);
486 
487         // Make sure the VpnProfile is not provisioned already.
488         sVpnMgr.stopProvisionedVpnProfile();
489 
490         try {
491             sVpnMgr.startProvisionedVpnProfile();
492             fail("Expected SecurityException for missing consent");
493         } catch (SecurityException expected) {
494         }
495     }
496 
checkStartStopVpnProfileBuildsNetworks(@onNull IkeTunUtils tunUtils, boolean testIpv6, boolean requiresValidation, boolean testSessionKey, boolean testIkeTunConnParams)497     private void checkStartStopVpnProfileBuildsNetworks(@NonNull IkeTunUtils tunUtils,
498             boolean testIpv6, boolean requiresValidation, boolean testSessionKey,
499             boolean testIkeTunConnParams)
500             throws Exception {
501         String serverAddr = testIpv6 ? TEST_SERVER_ADDR_V6 : TEST_SERVER_ADDR_V4;
502         String initResp = testIpv6 ? SUCCESSFUL_IKE_INIT_RESP_V6 : SUCCESSFUL_IKE_INIT_RESP_V4;
503         String authResp = testIpv6 ? SUCCESSFUL_IKE_AUTH_RESP_V6 : SUCCESSFUL_IKE_AUTH_RESP_V4;
504         boolean hasNat = !testIpv6;
505 
506         // Requires MANAGE_TEST_NETWORKS to provision a test-mode profile.
507         mCtsNetUtils.setAppopPrivileged(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, true);
508 
509         final Ikev2VpnProfile profile = testIkeTunConnParams
510                 ? buildIkev2VpnProfileIkeTunConnParams(true /* isRestrictedToTestNetworks */,
511                         requiresValidation, testIpv6)
512                 : buildIkev2VpnProfilePsk(serverAddr, true /* isRestrictedToTestNetworks */,
513                         requiresValidation);
514         assertNull(sVpnMgr.provisionVpnProfile(profile));
515 
516         final TestableNetworkCallback cb = new TestableNetworkCallback(TIMEOUT_MS);
517         final NetworkRequest nr = new NetworkRequest.Builder()
518                 .clearCapabilities().addTransportType(TRANSPORT_VPN).build();
519         registerNetworkCallback(nr, cb);
520 
521         if (testSessionKey) {
522             // testSessionKey will never be true if running on <T
523             // startProvisionedVpnProfileSession() should return a non-null & non-empty random UUID.
524             final String sessionId = mVmShim.startProvisionedVpnProfileSession();
525             assertFalse(TextUtils.isEmpty(sessionId));
526             final VpnProfileStateShim profileState = mVmShim.getProvisionedVpnProfileState();
527             assertNotNull(profileState);
528             assertEquals(ConstantsShim.VPN_PROFILE_STATE_CONNECTING, profileState.getState());
529             assertEquals(sessionId, profileState.getSessionId());
530             assertFalse(profileState.isAlwaysOn());
531             assertFalse(profileState.isLockdownEnabled());
532         } else {
533             sVpnMgr.startProvisionedVpnProfile();
534         }
535 
536         // Inject IKE negotiation
537         int expectedMsgId = 0;
538         tunUtils.awaitReqAndInjectResp(IKE_INITIATOR_SPI, expectedMsgId++, false /* isEncap */,
539                 HexDump.hexStringToByteArray(initResp));
540         tunUtils.awaitReqAndInjectResp(IKE_INITIATOR_SPI, expectedMsgId++, hasNat /* isEncap */,
541                 HexDump.hexStringToByteArray(authResp));
542 
543         // Verify the VPN network came up
544         final Network vpnNetwork = cb.expect(CallbackEntry.AVAILABLE).getNetwork();
545 
546         if (testSessionKey) {
547             final VpnProfileStateShim profileState = mVmShim.getProvisionedVpnProfileState();
548             assertNotNull(profileState);
549             assertEquals(ConstantsShim.VPN_PROFILE_STATE_CONNECTED, profileState.getState());
550             assertFalse(profileState.isAlwaysOn());
551             assertFalse(profileState.isLockdownEnabled());
552         }
553 
554         cb.expectCaps(vpnNetwork, TIMEOUT_MS, c -> c.hasTransport(TRANSPORT_VPN)
555                 && c.hasCapability(NET_CAPABILITY_INTERNET)
556                 && !c.hasCapability(NET_CAPABILITY_VALIDATED)
557                 && Process.myUid() == c.getOwnerUid());
558         cb.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, vpnNetwork);
559         cb.expect(CallbackEntry.BLOCKED_STATUS, vpnNetwork);
560 
561         // A VPN that requires validation is initially not validated, while one that doesn't
562         // immediately validate automatically. Because this VPN can't actually access Internet,
563         // the VPN only validates if it doesn't require validation. If the VPN requires validation
564         // but unexpectedly sends this callback, expecting LOST below will fail because the next
565         // callback will be the validated capabilities instead.
566         // In S and below, |requiresValidation| is ignored, so this callback is always sent
567         // regardless of its value. However, there is a race in Vpn(see b/228574221) that VPN may
568         // misuse VPN network itself as the underlying network. The fix is not available without
569         // SDK > T platform. Thus, verify this only on T+ platform.
570         if (!requiresValidation && TestUtils.shouldTestTApis()) {
571             cb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED, TIMEOUT_MS,
572                     entry -> ((CallbackEntry.CapabilitiesChanged) entry).getCaps()
573                             .hasCapability(NET_CAPABILITY_VALIDATED));
574         }
575 
576         sVpnMgr.stopProvisionedVpnProfile();
577         // Using expectCallback may cause the test to be flaky since test may receive other
578         // callbacks such as linkproperties change.
579         cb.eventuallyExpect(CallbackEntry.LOST, TIMEOUT_MS,
580                 lost -> vpnNetwork.equals(lost.getNetwork()));
581     }
582 
registerNetworkCallback(NetworkRequest request, TestableNetworkCallback callback)583     private void registerNetworkCallback(NetworkRequest request, TestableNetworkCallback callback) {
584         sCM.registerNetworkCallback(request, callback);
585         mCallbacksToUnregister.add(callback);
586     }
587 
588     private class VerifyStartStopVpnProfileTest implements TestNetworkRunnable.Test {
589         private final boolean mTestIpv6Only;
590         private final boolean mRequiresValidation;
591         private final boolean mTestSessionKey;
592         private final boolean mTestIkeTunConnParams;
593 
594         /**
595          * Constructs the test
596          *
597          * @param testIpv6Only if true, builds a IPv6-only test; otherwise builds a IPv4-only test
598          * @param requiresValidation whether this VPN should request platform validation
599          * @param testSessionKey if true, start VPN by calling startProvisionedVpnProfileSession()
600          */
VerifyStartStopVpnProfileTest(boolean testIpv6Only, boolean requiresValidation, boolean testSessionKey, boolean testIkeTunConnParams)601         VerifyStartStopVpnProfileTest(boolean testIpv6Only, boolean requiresValidation,
602                 boolean testSessionKey, boolean testIkeTunConnParams) {
603             mTestIpv6Only = testIpv6Only;
604             mRequiresValidation = requiresValidation;
605             mTestSessionKey = testSessionKey;
606             mTestIkeTunConnParams = testIkeTunConnParams;
607         }
608 
609         @Override
runTest(TestNetworkInterface testIface, TestNetworkCallback tunNetworkCallback)610         public void runTest(TestNetworkInterface testIface, TestNetworkCallback tunNetworkCallback)
611                 throws Exception {
612             final IkeTunUtils tunUtils = new IkeTunUtils(testIface.getFileDescriptor());
613 
614             checkStartStopVpnProfileBuildsNetworks(tunUtils, mTestIpv6Only, mRequiresValidation,
615                     mTestSessionKey, mTestIkeTunConnParams);
616         }
617 
618         @Override
cleanupTest()619         public void cleanupTest() {
620             sVpnMgr.stopProvisionedVpnProfile();
621         }
622 
623         @Override
getTestNetworkAddresses()624         public InetAddress[] getTestNetworkAddresses() {
625             if (mTestIpv6Only) {
626                 return new InetAddress[] {LOCAL_OUTER_6};
627             } else {
628                 return new InetAddress[] {LOCAL_OUTER_4};
629             }
630         }
631     }
632 
doTestStartStopVpnProfile(boolean testIpv6Only, boolean requiresValidation, boolean testSessionKey, boolean testIkeTunConnParams)633     private void doTestStartStopVpnProfile(boolean testIpv6Only, boolean requiresValidation,
634             boolean testSessionKey, boolean testIkeTunConnParams) throws Exception {
635         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
636         // Requires shell permission to update appops.
637         runWithShellPermissionIdentity(
638                 new TestNetworkRunnable(new VerifyStartStopVpnProfileTest(
639                         testIpv6Only, requiresValidation, testSessionKey , testIkeTunConnParams)));
640     }
641 
642     @Test
testStartStopVpnProfileV4()643     public void testStartStopVpnProfileV4() throws Exception {
644         doTestStartStopVpnProfile(false /* testIpv6Only */, false /* requiresValidation */,
645                 false /* testSessionKey */, false /* testIkeTunConnParams */);
646     }
647 
648     @Test @IgnoreUpTo(SC_V2)
testStartStopVpnProfileV4WithValidation()649     public void testStartStopVpnProfileV4WithValidation() throws Exception {
650         assumeTrue(TestUtils.shouldTestTApis());
651         doTestStartStopVpnProfile(false /* testIpv6Only */, true /* requiresValidation */,
652                 false /* testSessionKey */, false /* testIkeTunConnParams */);
653     }
654 
655     @Test
testStartStopVpnProfileV6()656     public void testStartStopVpnProfileV6() throws Exception {
657         doTestStartStopVpnProfile(true /* testIpv6Only */, false /* requiresValidation */,
658                 false /* testSessionKey */, false /* testIkeTunConnParams */);
659     }
660 
661     @Test @IgnoreUpTo(SC_V2)
testStartStopVpnProfileV6WithValidation()662     public void testStartStopVpnProfileV6WithValidation() throws Exception {
663         assumeTrue(TestUtils.shouldTestTApis());
664         doTestStartStopVpnProfile(true /* testIpv6Only */, true /* requiresValidation */,
665                 false /* testSessionKey */, false /* testIkeTunConnParams */);
666     }
667 
668     @Test @IgnoreUpTo(SC_V2)
testStartStopVpnProfileIkeTunConnParamsV4()669     public void testStartStopVpnProfileIkeTunConnParamsV4() throws Exception {
670         assumeTrue(TestUtils.shouldTestTApis());
671         doTestStartStopVpnProfile(false /* testIpv6Only */, false /* requiresValidation */,
672                 false /* testSessionKey */, true /* testIkeTunConnParams */);
673     }
674 
675     @Test @IgnoreUpTo(SC_V2)
testStartStopVpnProfileIkeTunConnParamsV4WithValidation()676     public void testStartStopVpnProfileIkeTunConnParamsV4WithValidation() throws Exception {
677         assumeTrue(TestUtils.shouldTestTApis());
678         doTestStartStopVpnProfile(false /* testIpv6Only */, true /* requiresValidation */,
679                 false /* testSessionKey */, true /* testIkeTunConnParams */);
680     }
681 
682     @Test @IgnoreUpTo(SC_V2)
testStartStopVpnProfileIkeTunConnParamsV6()683     public void testStartStopVpnProfileIkeTunConnParamsV6() throws Exception {
684         assumeTrue(TestUtils.shouldTestTApis());
685         doTestStartStopVpnProfile(true /* testIpv6Only */, false /* requiresValidation */,
686                 false /* testSessionKey */, true /* testIkeTunConnParams */);
687     }
688 
689     @Test @IgnoreUpTo(SC_V2)
testStartStopVpnProfileIkeTunConnParamsV6WithValidation()690     public void testStartStopVpnProfileIkeTunConnParamsV6WithValidation() throws Exception {
691         assumeTrue(TestUtils.shouldTestTApis());
692         doTestStartStopVpnProfile(true /* testIpv6Only */, true /* requiresValidation */,
693                 false /* testSessionKey */, true /* testIkeTunConnParams */);
694     }
695 
696     @IgnoreUpTo(SC_V2)
697     @Test
testStartProvisionedVpnV4ProfileSession()698     public void testStartProvisionedVpnV4ProfileSession() throws Exception {
699         assumeTrue(TestUtils.shouldTestTApis());
700         doTestStartStopVpnProfile(false /* testIpv6Only */, false /* requiresValidation */,
701                 true /* testSessionKey */, false /* testIkeTunConnParams */);
702     }
703 
704     @IgnoreUpTo(SC_V2)
705     @Test
testStartProvisionedVpnV6ProfileSession()706     public void testStartProvisionedVpnV6ProfileSession() throws Exception {
707         assumeTrue(TestUtils.shouldTestTApis());
708         doTestStartStopVpnProfile(true /* testIpv6Only */, false /* requiresValidation */,
709                 true /* testSessionKey */, false /* testIkeTunConnParams */);
710     }
711 
712     @Test
testBuildIkev2VpnProfileWithAutomaticNattKeepaliveTimerEnabled()713     public void testBuildIkev2VpnProfileWithAutomaticNattKeepaliveTimerEnabled() throws Exception {
714         // Cannot use @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) because this test also requires API
715         // 34 shims, and @IgnoreUpTo does not check that.
716         assumeTrue(TestUtils.shouldTestUApis());
717 
718         final Ikev2VpnProfile profileWithDefaultValue = buildIkev2VpnProfilePsk(TEST_SERVER_ADDR_V6,
719                 false /* isRestrictedToTestNetworks */, false /* requiresValidation */);
720         final Ikev2VpnProfileShim<Ikev2VpnProfile> shimWithDefaultValue =
721                 Ikev2VpnProfileShimImpl.newInstance(profileWithDefaultValue);
722         assertFalse(shimWithDefaultValue.isAutomaticNattKeepaliveTimerEnabled());
723 
724         final Ikev2VpnProfileBuilderShim builder =
725                 Ikev2VpnProfileBuilderShimImpl.newInstance(TEST_SERVER_ADDR_V6, TEST_IDENTITY)
726                         .setAuthPsk(TEST_PSK);
727         final Ikev2VpnProfile profile = buildIkev2VpnProfileCommon(builder,
728                 false /* isRestrictedToTestNetworks */,
729                 false /* requiresValidation */,
730                 false /* automaticIpVersionSelectionEnabled */,
731                 true /* automaticNattKeepaliveTimerEnabled */);
732         final Ikev2VpnProfileShim<Ikev2VpnProfile> shim =
733                 Ikev2VpnProfileShimImpl.newInstance(profile);
734         assertTrue(shim.isAutomaticNattKeepaliveTimerEnabled());
735     }
736 
737     @Test
testBuildIkev2VpnProfileWithAutomaticIpVersionSelectionEnabled()738     public void testBuildIkev2VpnProfileWithAutomaticIpVersionSelectionEnabled() throws Exception {
739         // Cannot use @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) because this test also requires API
740         // 34 shims, and @IgnoreUpTo does not check that.
741         assumeTrue(TestUtils.shouldTestUApis());
742 
743         final Ikev2VpnProfile profileWithDefaultValue = buildIkev2VpnProfilePsk(TEST_SERVER_ADDR_V6,
744                 false /* isRestrictedToTestNetworks */, false /* requiresValidation */);
745         final Ikev2VpnProfileShim<Ikev2VpnProfile> shimWithDefaultValue =
746                 Ikev2VpnProfileShimImpl.newInstance(profileWithDefaultValue);
747         assertFalse(shimWithDefaultValue.isAutomaticIpVersionSelectionEnabled());
748 
749         final Ikev2VpnProfileBuilderShim builder =
750                 Ikev2VpnProfileBuilderShimImpl.newInstance(TEST_SERVER_ADDR_V6, TEST_IDENTITY)
751                         .setAuthPsk(TEST_PSK);
752         final Ikev2VpnProfile profile = buildIkev2VpnProfileCommon(builder,
753                 false /* isRestrictedToTestNetworks */,
754                 false /* requiresValidation */,
755                 true /* automaticIpVersionSelectionEnabled */,
756                 false /* automaticNattKeepaliveTimerEnabled */);
757         final Ikev2VpnProfileShim<Ikev2VpnProfile> shim =
758                 Ikev2VpnProfileShimImpl.newInstance(profile);
759         assertTrue(shim.isAutomaticIpVersionSelectionEnabled());
760     }
761 
762     private static class CertificateAndKey {
763         public final X509Certificate cert;
764         public final PrivateKey key;
765 
CertificateAndKey(X509Certificate cert, PrivateKey key)766         CertificateAndKey(X509Certificate cert, PrivateKey key) {
767             this.cert = cert;
768             this.key = key;
769         }
770     }
771 
generateRandomCertAndKeyPair()772     private static CertificateAndKey generateRandomCertAndKeyPair() throws Exception {
773         final Date validityBeginDate =
774                 new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1L));
775         final Date validityEndDate =
776                 new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1L));
777 
778         // Generate a keypair
779         final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
780         keyPairGenerator.initialize(512);
781         final KeyPair keyPair = keyPairGenerator.generateKeyPair();
782 
783         final X500Principal dnName = new X500Principal("CN=test.android.com");
784         final X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
785         certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
786         certGen.setSubjectDN(dnName);
787         certGen.setIssuerDN(dnName);
788         certGen.setNotBefore(validityBeginDate);
789         certGen.setNotAfter(validityEndDate);
790         certGen.setPublicKey(keyPair.getPublic());
791         certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
792 
793         final X509Certificate cert = certGen.generate(keyPair.getPrivate(), "AndroidOpenSSL");
794         return new CertificateAndKey(cert, keyPair.getPrivate());
795     }
796 }
797