• 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.TRANSPORT_VPN;
21 import static android.net.cts.util.CtsNetUtils.TestNetworkCallback;
22 
23 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
24 
25 import static org.junit.Assert.assertArrayEquals;
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertFalse;
28 import static org.junit.Assert.assertNotNull;
29 import static org.junit.Assert.assertNull;
30 import static org.junit.Assert.assertTrue;
31 import static org.junit.Assert.fail;
32 import static org.junit.Assume.assumeTrue;
33 
34 import android.Manifest;
35 import android.annotation.NonNull;
36 import android.app.AppOpsManager;
37 import android.content.Context;
38 import android.content.Intent;
39 import android.net.ConnectivityManager;
40 import android.net.Ikev2VpnProfile;
41 import android.net.IpSecAlgorithm;
42 import android.net.Network;
43 import android.net.NetworkCapabilities;
44 import android.net.NetworkRequest;
45 import android.net.ProxyInfo;
46 import android.net.TestNetworkInterface;
47 import android.net.VpnManager;
48 import android.net.cts.util.CtsNetUtils;
49 import android.os.Build;
50 import android.os.Process;
51 import android.platform.test.annotations.AppModeFull;
52 
53 import androidx.test.InstrumentationRegistry;
54 
55 import com.android.internal.util.HexDump;
56 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
57 import com.android.testutils.DevSdkIgnoreRunner;
58 
59 import org.bouncycastle.x509.X509V1CertificateGenerator;
60 import org.junit.After;
61 import org.junit.Test;
62 import org.junit.runner.RunWith;
63 
64 import java.math.BigInteger;
65 import java.net.InetAddress;
66 import java.security.KeyPair;
67 import java.security.KeyPairGenerator;
68 import java.security.PrivateKey;
69 import java.security.cert.X509Certificate;
70 import java.util.Arrays;
71 import java.util.Date;
72 import java.util.List;
73 import java.util.concurrent.TimeUnit;
74 
75 import javax.security.auth.x500.X500Principal;
76 
77 @RunWith(DevSdkIgnoreRunner.class)
78 @IgnoreUpTo(Build.VERSION_CODES.Q)
79 @AppModeFull(reason = "Appops state changes disallowed for instant apps (OP_ACTIVATE_PLATFORM_VPN)")
80 public class Ikev2VpnTest {
81     private static final String TAG = Ikev2VpnTest.class.getSimpleName();
82 
83     // Test vectors for IKE negotiation in test mode.
84     private static final String SUCCESSFUL_IKE_INIT_RESP_V4 =
85             "46b8eca1e0d72a18b2b5d9006d47a0022120222000000000000002d0220000300000002c01010004030000"
86                     + "0c0100000c800e0100030000080300000c030000080200000400000008040000102800020800"
87                     + "100000b8070f159fe5141d8754ca86f72ecc28d66f514927e96cbe9eec0adb42bf2c276a0ab7"
88                     + "a97fa93555f4be9218c14e7f286bb28c6b4fb13825a420f2ffc165854f200bab37d69c8963d4"
89                     + "0acb831d983163aa50622fd35c182efe882cf54d6106222abcfaa597255d302f1b95ab71c142"
90                     + "c279ea5839a180070bff73f9d03fab815f0d5ee2adec7e409d1e35979f8bd92ffd8aab13d1a0"
91                     + "0657d816643ae767e9ae84d2ccfa2bcce1a50572be8d3748ae4863c41ae90da16271e014270f"
92                     + "77edd5cd2e3299f3ab27d7203f93d770bacf816041cdcecd0f9af249033979da4369cb242dd9"
93                     + "6d172e60513ff3db02de63e50eb7d7f596ada55d7946cad0af0669d1f3e2804846ab3f2a930d"
94                     + "df56f7f025f25c25ada694e6231abbb87ee8cfd072c8481dc0b0f6b083fdc3bd89b080e49feb"
95                     + "0288eef6fdf8a26ee2fc564a11e7385215cf2deaf2a9965638fc279c908ccdf04094988d91a2"
96                     + "464b4a8c0326533aff5119ed79ecbd9d99a218b44f506a5eb09351e67da86698b4c58718db25"
97                     + "d55f426fb4c76471b27a41fbce00777bc233c7f6e842e39146f466826de94f564cad8b92bfbe"
98                     + "87c99c4c7973ec5f1eea8795e7da82819753aa7c4fcfdab77066c56b939330c4b0d354c23f83"
99                     + "ea82fa7a64c4b108f1188379ea0eb4918ee009d804100e6bf118771b9058d42141c847d5ec37"
100                     + "6e5ec591c71fc9dac01063c2bd31f9c783b28bf1182900002430f3d5de3449462b31dd28bc27"
101                     + "297b6ad169bccce4f66c5399c6e0be9120166f2900001c0000400428b8df2e66f69c8584a186"
102                     + "c5eac66783551d49b72900001c000040054e7a622e802d5cbfb96d5f30a6e433994370173529"
103                     + "0000080000402e290000100000402f00020003000400050000000800004014";
104     private static final String SUCCESSFUL_IKE_INIT_RESP_V6 =
105             "46b8eca1e0d72a1800d9ea1babce26bf2120222000000000000002d0220000300000002c01010004030000"
106                     + "0c0100000c800e0100030000080300000c030000080200000400000008040000102800020800"
107                     + "100000ea0e6dd9ca5930a9a45c323a41f64bfd8cdef7730f5fbff37d7c377da427f489a42aa8"
108                     + "c89233380e6e925990d49de35c2cdcf63a61302c731a4b3569df1ee1bf2457e55a6751838ede"
109                     + "abb75cc63ba5c9e4355e8e784f383a5efe8a44727dc14aeaf8dacc2620fb1c8875416dc07739"
110                     + "7fe4decc1bd514a9c7d270cf21fd734c63a25c34b30b68686e54e8a198f37f27cb491fe27235"
111                     + "fab5476b036d875ccab9a68d65fbf3006197f9bebbf94de0d3802b4fafe1d48d931ce3a1a346"
112                     + "2d65bd639e9bd7fa46299650a9dbaf9b324e40b466942d91a59f41ef8042f8474c4850ed0f63"
113                     + "e9238949d41cd8bbaea9aefdb65443a6405792839563aa5dc5c36b5ce8326ccf8a94d9622b85"
114                     + "038d390d5fc0299e14e1f022966d4ac66515f6108ca04faec44821fe5bbf2ed4f84ff5671219"
115                     + "608cb4c36b44a31ba010c9088f8d5ff943bb9ff857f74be1755f57a5783874adc57f42bb174e"
116                     + "4ad3215de628707014dbcb1707bd214658118fdd7a42b3e1638b991ce5b812a667f1145be811"
117                     + "685e3cd3baf9b18d062657b64c206a4d19a531c252a6a51a04aeaf42c618620cdbab65baca23"
118                     + "82c57ed888422aeaacf7f1bc3fe2247ff7e7eaca218b74d7b31d02f2b0afa123f802529e7e6c"
119                     + "3259d418290740ddbf55686e26998d7edcbbf895664972fed666f2f20af40503aa2af436ec6d"
120                     + "4ec981ab19b9088755d94ae7a7c2066ea331d4e56e290000243fefe5555fce552d57a84e682c"
121                     + "d4a6dfb3f2f94a94464d5bec3d88b88e9559642900001c00004004eb4afff764e7b79bca78b1"
122                     + "3a89100d36d678ae982900001c00004005d177216a3c26f782076e12570d40bfaaa148822929"
123                     + "0000080000402e290000100000402f00020003000400050000000800004014";
124     private static final String SUCCESSFUL_IKE_AUTH_RESP_V4 =
125             "46b8eca1e0d72a18b2b5d9006d47a0022e20232000000001000000e0240000c420a2500a3da4c66fa6929e"
126                     + "600f36349ba0e38de14f78a3ad0416cba8c058735712a3d3f9a0a6ed36de09b5e9e02697e7c4"
127                     + "2d210ac86cfbd709503cfa51e2eab8cfdc6427d136313c072968f6506a546eb5927164200592"
128                     + "6e36a16ee994e63f029432a67bc7d37ca619e1bd6e1678df14853067ecf816b48b81e8746069"
129                     + "406363e5aa55f13cb2afda9dbebee94256c29d630b17dd7f1ee52351f92b6e1c3d8551c513f1"
130                     + "d74ac52a80b2041397e109fe0aeb3c105b0d4be0ae343a943398764281";
131     private static final String SUCCESSFUL_IKE_AUTH_RESP_V6 =
132             "46b8eca1e0d72a1800d9ea1babce26bf2e20232000000001000000f0240000d4aaf6eaa6c06b50447e6f54"
133                     + "827fd8a9d9d6ac8015c1ebb3e8cb03fc6e54b49a107441f50004027cc5021600828026367f03"
134                     + "bc425821cd7772ee98637361300c9b76056e874fea2bd4a17212370b291894264d8c023a01d1"
135                     + "c3b691fd4b7c0b534e8c95af4c4638e2d125cb21c6267e2507cd745d72e8da109c47b9259c6c"
136                     + "57a26f6bc5b337b9b9496d54bdde0333d7a32e6e1335c9ee730c3ecd607a8689aa7b0577b74f"
137                     + "3bf437696a9fd5fc0aee3ed346cd9e15d1dda293df89eb388a8719388a60ca7625754de12cdb"
138                     + "efe4c886c5c401";
139     private static final long IKE_INITIATOR_SPI = Long.parseLong("46B8ECA1E0D72A18", 16);
140 
141     private static final InetAddress LOCAL_OUTER_4 = InetAddress.parseNumericAddress("192.0.2.1");
142     private static final InetAddress LOCAL_OUTER_6 =
143             InetAddress.parseNumericAddress("2001:db8::1");
144 
145     private static final int IP4_PREFIX_LEN = 32;
146     private static final int IP6_PREFIX_LEN = 128;
147 
148     // TODO: Use IPv6 address when we can generate test vectors (GCE does not allow IPv6 yet).
149     private static final String TEST_SERVER_ADDR_V4 = "192.0.2.2";
150     private static final String TEST_SERVER_ADDR_V6 = "2001:db8::2";
151     private static final String TEST_IDENTITY = "client.cts.android.com";
152     private static final List<String> TEST_ALLOWED_ALGORITHMS =
153             Arrays.asList(IpSecAlgorithm.AUTH_CRYPT_AES_GCM);
154 
155     private static final ProxyInfo TEST_PROXY_INFO =
156             ProxyInfo.buildDirectProxy("proxy.cts.android.com", 1234);
157     private static final int TEST_MTU = 1300;
158 
159     private static final byte[] TEST_PSK = "ikeAndroidPsk".getBytes();
160     private static final String TEST_USER = "username";
161     private static final String TEST_PASSWORD = "pa55w0rd";
162 
163     // Static state to reduce setup/teardown
164     private static final Context sContext = InstrumentationRegistry.getContext();
165     private static final ConnectivityManager sCM =
166             (ConnectivityManager) sContext.getSystemService(Context.CONNECTIVITY_SERVICE);
167     private static final VpnManager sVpnMgr =
168             (VpnManager) sContext.getSystemService(Context.VPN_MANAGEMENT_SERVICE);
169     private static final CtsNetUtils mCtsNetUtils = new CtsNetUtils(sContext);
170 
171     private final X509Certificate mServerRootCa;
172     private final CertificateAndKey mUserCertKey;
173 
Ikev2VpnTest()174     public Ikev2VpnTest() throws Exception {
175         // Build certificates
176         mServerRootCa = generateRandomCertAndKeyPair().cert;
177         mUserCertKey = generateRandomCertAndKeyPair();
178     }
179 
180     @After
tearDown()181     public void tearDown() {
182         setAppop(AppOpsManager.OP_ACTIVATE_VPN, false);
183         setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, false);
184     }
185 
186     /**
187      * Sets the given appop using shell commands
188      *
189      * <p>This method must NEVER be called from within a shell permission, as it will attempt to
190      * acquire, and then drop the shell permission identity. This results in the caller losing the
191      * shell permission identity due to these calls not being reference counted.
192      */
setAppop(int appop, boolean allow)193     public void setAppop(int appop, boolean allow) {
194         // Requires shell permission to update appops.
195         runWithShellPermissionIdentity(() -> {
196             mCtsNetUtils.setAppopPrivileged(appop, allow);
197         }, Manifest.permission.MANAGE_TEST_NETWORKS);
198     }
199 
buildIkev2VpnProfileCommon( Ikev2VpnProfile.Builder builder, boolean isRestrictedToTestNetworks)200     private Ikev2VpnProfile buildIkev2VpnProfileCommon(
201             Ikev2VpnProfile.Builder builder, boolean isRestrictedToTestNetworks) throws Exception {
202         if (isRestrictedToTestNetworks) {
203             builder.restrictToTestNetworks();
204         }
205 
206         return builder.setBypassable(true)
207                 .setAllowedAlgorithms(TEST_ALLOWED_ALGORITHMS)
208                 .setProxy(TEST_PROXY_INFO)
209                 .setMaxMtu(TEST_MTU)
210                 .setMetered(false)
211                 .build();
212     }
213 
buildIkev2VpnProfilePsk(boolean isRestrictedToTestNetworks)214     private Ikev2VpnProfile buildIkev2VpnProfilePsk(boolean isRestrictedToTestNetworks)
215             throws Exception {
216         return buildIkev2VpnProfilePsk(TEST_SERVER_ADDR_V6, isRestrictedToTestNetworks);
217     }
218 
buildIkev2VpnProfilePsk( String remote, boolean isRestrictedToTestNetworks)219     private Ikev2VpnProfile buildIkev2VpnProfilePsk(
220             String remote, boolean isRestrictedToTestNetworks) throws Exception {
221         final Ikev2VpnProfile.Builder builder =
222                 new Ikev2VpnProfile.Builder(remote, TEST_IDENTITY).setAuthPsk(TEST_PSK);
223 
224         return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks);
225     }
226 
buildIkev2VpnProfileUsernamePassword(boolean isRestrictedToTestNetworks)227     private Ikev2VpnProfile buildIkev2VpnProfileUsernamePassword(boolean isRestrictedToTestNetworks)
228             throws Exception {
229         final Ikev2VpnProfile.Builder builder =
230                 new Ikev2VpnProfile.Builder(TEST_SERVER_ADDR_V6, TEST_IDENTITY)
231                         .setAuthUsernamePassword(TEST_USER, TEST_PASSWORD, mServerRootCa);
232 
233         return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks);
234     }
235 
buildIkev2VpnProfileDigitalSignature(boolean isRestrictedToTestNetworks)236     private Ikev2VpnProfile buildIkev2VpnProfileDigitalSignature(boolean isRestrictedToTestNetworks)
237             throws Exception {
238         final Ikev2VpnProfile.Builder builder =
239                 new Ikev2VpnProfile.Builder(TEST_SERVER_ADDR_V6, TEST_IDENTITY)
240                         .setAuthDigitalSignature(
241                                 mUserCertKey.cert, mUserCertKey.key, mServerRootCa);
242 
243         return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks);
244     }
245 
checkBasicIkev2VpnProfile(@onNull Ikev2VpnProfile profile)246     private void checkBasicIkev2VpnProfile(@NonNull Ikev2VpnProfile profile) throws Exception {
247         assertEquals(TEST_SERVER_ADDR_V6, profile.getServerAddr());
248         assertEquals(TEST_IDENTITY, profile.getUserIdentity());
249         assertEquals(TEST_PROXY_INFO, profile.getProxyInfo());
250         assertEquals(TEST_ALLOWED_ALGORITHMS, profile.getAllowedAlgorithms());
251         assertTrue(profile.isBypassable());
252         assertFalse(profile.isMetered());
253         assertEquals(TEST_MTU, profile.getMaxMtu());
254         assertFalse(profile.isRestrictedToTestNetworks());
255     }
256 
257     @Test
testBuildIkev2VpnProfilePsk()258     public void testBuildIkev2VpnProfilePsk() throws Exception {
259         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
260 
261         final Ikev2VpnProfile profile =
262                 buildIkev2VpnProfilePsk(false /* isRestrictedToTestNetworks */);
263 
264         checkBasicIkev2VpnProfile(profile);
265         assertArrayEquals(TEST_PSK, profile.getPresharedKey());
266 
267         // Verify nothing else is set.
268         assertNull(profile.getUsername());
269         assertNull(profile.getPassword());
270         assertNull(profile.getServerRootCaCert());
271         assertNull(profile.getRsaPrivateKey());
272         assertNull(profile.getUserCert());
273     }
274 
275     @Test
testBuildIkev2VpnProfileUsernamePassword()276     public void testBuildIkev2VpnProfileUsernamePassword() throws Exception {
277         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
278 
279         final Ikev2VpnProfile profile =
280                 buildIkev2VpnProfileUsernamePassword(false /* isRestrictedToTestNetworks */);
281 
282         checkBasicIkev2VpnProfile(profile);
283         assertEquals(TEST_USER, profile.getUsername());
284         assertEquals(TEST_PASSWORD, profile.getPassword());
285         assertEquals(mServerRootCa, profile.getServerRootCaCert());
286 
287         // Verify nothing else is set.
288         assertNull(profile.getPresharedKey());
289         assertNull(profile.getRsaPrivateKey());
290         assertNull(profile.getUserCert());
291     }
292 
293     @Test
testBuildIkev2VpnProfileDigitalSignature()294     public void testBuildIkev2VpnProfileDigitalSignature() throws Exception {
295         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
296 
297         final Ikev2VpnProfile profile =
298                 buildIkev2VpnProfileDigitalSignature(false /* isRestrictedToTestNetworks */);
299 
300         checkBasicIkev2VpnProfile(profile);
301         assertEquals(mUserCertKey.cert, profile.getUserCert());
302         assertEquals(mUserCertKey.key, profile.getRsaPrivateKey());
303         assertEquals(mServerRootCa, profile.getServerRootCaCert());
304 
305         // Verify nothing else is set.
306         assertNull(profile.getUsername());
307         assertNull(profile.getPassword());
308         assertNull(profile.getPresharedKey());
309     }
310 
verifyProvisionVpnProfile( boolean hasActivateVpn, boolean hasActivatePlatformVpn, boolean expectIntent)311     private void verifyProvisionVpnProfile(
312             boolean hasActivateVpn, boolean hasActivatePlatformVpn, boolean expectIntent)
313             throws Exception {
314         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
315 
316         setAppop(AppOpsManager.OP_ACTIVATE_VPN, hasActivateVpn);
317         setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, hasActivatePlatformVpn);
318 
319         final Ikev2VpnProfile profile =
320                 buildIkev2VpnProfilePsk(false /* isRestrictedToTestNetworks */);
321         final Intent intent = sVpnMgr.provisionVpnProfile(profile);
322         assertEquals(expectIntent, intent != null);
323     }
324 
325     @Test
testProvisionVpnProfileNoPreviousConsent()326     public void testProvisionVpnProfileNoPreviousConsent() throws Exception {
327         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
328 
329         verifyProvisionVpnProfile(false /* hasActivateVpn */,
330                 false /* hasActivatePlatformVpn */, true /* expectIntent */);
331     }
332 
333     @Test
testProvisionVpnProfilePlatformVpnConsented()334     public void testProvisionVpnProfilePlatformVpnConsented() throws Exception {
335         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
336 
337         verifyProvisionVpnProfile(false /* hasActivateVpn */,
338                 true /* hasActivatePlatformVpn */, false /* expectIntent */);
339     }
340 
341     @Test
testProvisionVpnProfileVpnServiceConsented()342     public void testProvisionVpnProfileVpnServiceConsented() throws Exception {
343         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
344 
345         verifyProvisionVpnProfile(true /* hasActivateVpn */,
346                 false /* hasActivatePlatformVpn */, false /* expectIntent */);
347     }
348 
349     @Test
testProvisionVpnProfileAllPreConsented()350     public void testProvisionVpnProfileAllPreConsented() throws Exception {
351         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
352 
353         verifyProvisionVpnProfile(true /* hasActivateVpn */,
354                 true /* hasActivatePlatformVpn */, false /* expectIntent */);
355     }
356 
357     @Test
testDeleteVpnProfile()358     public void testDeleteVpnProfile() throws Exception {
359         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
360 
361         setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, true);
362 
363         final Ikev2VpnProfile profile =
364                 buildIkev2VpnProfilePsk(false /* isRestrictedToTestNetworks */);
365         assertNull(sVpnMgr.provisionVpnProfile(profile));
366 
367         // Verify that deleting the profile works (even without the appop)
368         setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, false);
369         sVpnMgr.deleteProvisionedVpnProfile();
370 
371         // Test that the profile was deleted - starting it should throw an IAE.
372         try {
373             setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, true);
374             sVpnMgr.startProvisionedVpnProfile();
375             fail("Expected IllegalArgumentException due to missing profile");
376         } catch (IllegalArgumentException expected) {
377         }
378     }
379 
380     @Test
testStartVpnProfileNoPreviousConsent()381     public void testStartVpnProfileNoPreviousConsent() throws Exception {
382         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
383 
384         setAppop(AppOpsManager.OP_ACTIVATE_VPN, false);
385         setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, false);
386 
387         // Make sure the VpnProfile is not provisioned already.
388         sVpnMgr.stopProvisionedVpnProfile();
389 
390         try {
391             sVpnMgr.startProvisionedVpnProfile();
392             fail("Expected SecurityException for missing consent");
393         } catch (SecurityException expected) {
394         }
395     }
396 
checkStartStopVpnProfileBuildsNetworks(IkeTunUtils tunUtils, boolean testIpv6)397     private void checkStartStopVpnProfileBuildsNetworks(IkeTunUtils tunUtils, boolean testIpv6)
398             throws Exception {
399         String serverAddr = testIpv6 ? TEST_SERVER_ADDR_V6 : TEST_SERVER_ADDR_V4;
400         String initResp = testIpv6 ? SUCCESSFUL_IKE_INIT_RESP_V6 : SUCCESSFUL_IKE_INIT_RESP_V4;
401         String authResp = testIpv6 ? SUCCESSFUL_IKE_AUTH_RESP_V6 : SUCCESSFUL_IKE_AUTH_RESP_V4;
402         boolean hasNat = !testIpv6;
403 
404         // Requires MANAGE_TEST_NETWORKS to provision a test-mode profile.
405         mCtsNetUtils.setAppopPrivileged(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, true);
406 
407         final Ikev2VpnProfile profile =
408                 buildIkev2VpnProfilePsk(serverAddr, true /* isRestrictedToTestNetworks */);
409         assertNull(sVpnMgr.provisionVpnProfile(profile));
410 
411         sVpnMgr.startProvisionedVpnProfile();
412 
413         // Inject IKE negotiation
414         int expectedMsgId = 0;
415         tunUtils.awaitReqAndInjectResp(IKE_INITIATOR_SPI, expectedMsgId++, false /* isEncap */,
416                 HexDump.hexStringToByteArray(initResp));
417         tunUtils.awaitReqAndInjectResp(IKE_INITIATOR_SPI, expectedMsgId++, hasNat /* isEncap */,
418                 HexDump.hexStringToByteArray(authResp));
419 
420         // Verify the VPN network came up
421         final NetworkRequest nr = new NetworkRequest.Builder()
422                 .clearCapabilities().addTransportType(TRANSPORT_VPN).build();
423 
424         final TestNetworkCallback cb = new TestNetworkCallback();
425         sCM.requestNetwork(nr, cb);
426         cb.waitForAvailable();
427         final Network vpnNetwork = cb.currentNetwork;
428         assertNotNull(vpnNetwork);
429 
430         final NetworkCapabilities caps = sCM.getNetworkCapabilities(vpnNetwork);
431         assertTrue(caps.hasTransport(TRANSPORT_VPN));
432         assertTrue(caps.hasCapability(NET_CAPABILITY_INTERNET));
433         assertEquals(Process.myUid(), caps.getOwnerUid());
434 
435         sVpnMgr.stopProvisionedVpnProfile();
436         cb.waitForLost();
437         assertEquals(vpnNetwork, cb.lastLostNetwork);
438     }
439 
440     private class VerifyStartStopVpnProfileTest implements TestNetworkRunnable.Test {
441         private final boolean mTestIpv6Only;
442 
443         /**
444          * Constructs the test
445          *
446          * @param testIpv6Only if true, builds a IPv6-only test; otherwise builds a IPv4-only test
447          */
VerifyStartStopVpnProfileTest(boolean testIpv6Only)448         VerifyStartStopVpnProfileTest(boolean testIpv6Only) {
449             mTestIpv6Only = testIpv6Only;
450         }
451 
452         @Override
runTest(TestNetworkInterface testIface, TestNetworkCallback tunNetworkCallback)453         public void runTest(TestNetworkInterface testIface, TestNetworkCallback tunNetworkCallback)
454                 throws Exception {
455             final IkeTunUtils tunUtils = new IkeTunUtils(testIface.getFileDescriptor());
456 
457             checkStartStopVpnProfileBuildsNetworks(tunUtils, mTestIpv6Only);
458         }
459 
460         @Override
cleanupTest()461         public void cleanupTest() {
462             sVpnMgr.stopProvisionedVpnProfile();
463         }
464 
465         @Override
getTestNetworkAddresses()466         public InetAddress[] getTestNetworkAddresses() {
467             if (mTestIpv6Only) {
468                 return new InetAddress[] {LOCAL_OUTER_6};
469             } else {
470                 return new InetAddress[] {LOCAL_OUTER_4};
471             }
472         }
473     }
474 
475     @Test
testStartStopVpnProfileV4()476     public void testStartStopVpnProfileV4() throws Exception {
477         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
478 
479         // Requires shell permission to update appops.
480         runWithShellPermissionIdentity(
481                 new TestNetworkRunnable(new VerifyStartStopVpnProfileTest(false)));
482     }
483 
484     @Test
testStartStopVpnProfileV6()485     public void testStartStopVpnProfileV6() throws Exception {
486         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
487 
488         // Requires shell permission to update appops.
489         runWithShellPermissionIdentity(
490                 new TestNetworkRunnable(new VerifyStartStopVpnProfileTest(true)));
491     }
492 
493     private static class CertificateAndKey {
494         public final X509Certificate cert;
495         public final PrivateKey key;
496 
CertificateAndKey(X509Certificate cert, PrivateKey key)497         CertificateAndKey(X509Certificate cert, PrivateKey key) {
498             this.cert = cert;
499             this.key = key;
500         }
501     }
502 
generateRandomCertAndKeyPair()503     private static CertificateAndKey generateRandomCertAndKeyPair() throws Exception {
504         final Date validityBeginDate =
505                 new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1L));
506         final Date validityEndDate =
507                 new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1L));
508 
509         // Generate a keypair
510         final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
511         keyPairGenerator.initialize(512);
512         final KeyPair keyPair = keyPairGenerator.generateKeyPair();
513 
514         final X500Principal dnName = new X500Principal("CN=test.android.com");
515         final X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
516         certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
517         certGen.setSubjectDN(dnName);
518         certGen.setIssuerDN(dnName);
519         certGen.setNotBefore(validityBeginDate);
520         certGen.setNotAfter(validityEndDate);
521         certGen.setPublicKey(keyPair.getPublic());
522         certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
523 
524         final X509Certificate cert = certGen.generate(keyPair.getPrivate(), "AndroidOpenSSL");
525         return new CertificateAndKey(cert, keyPair.getPrivate());
526     }
527 }
528