blob: 2273bc61225c28a2e41a9b5e8de2b7c981018820 [file] [log] [blame]
Benedict Wong4416f382019-11-01 16:45:08 -07001/*
2 * Copyright (C) 2019 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
17package android.net;
18
19import static org.junit.Assert.assertArrayEquals;
20import static org.junit.Assert.assertEquals;
21import static org.junit.Assert.assertNotNull;
22import static org.junit.Assert.assertNull;
23import static org.junit.Assert.assertTrue;
24import static org.junit.Assert.fail;
Benedict Wong4416f382019-11-01 16:45:08 -070025
26import android.test.mock.MockContext;
27
28import androidx.test.filters.SmallTest;
29import androidx.test.runner.AndroidJUnit4;
30
31import com.android.internal.net.VpnProfile;
32import com.android.org.bouncycastle.x509.X509V1CertificateGenerator;
33
34import org.junit.Before;
35import org.junit.Test;
36import org.junit.runner.RunWith;
37
38import java.math.BigInteger;
39import java.security.KeyPair;
40import java.security.KeyPairGenerator;
41import java.security.PrivateKey;
42import java.security.cert.X509Certificate;
43import java.util.Date;
44import java.util.concurrent.TimeUnit;
45
46import javax.security.auth.x500.X500Principal;
47
48/** Unit tests for {@link Ikev2VpnProfile.Builder}. */
49@SmallTest
50@RunWith(AndroidJUnit4.class)
51public class Ikev2VpnProfileTest {
52 private static final String SERVER_ADDR_STRING = "1.2.3.4";
53 private static final String IDENTITY_STRING = "Identity";
54 private static final String USERNAME_STRING = "username";
55 private static final String PASSWORD_STRING = "pa55w0rd";
56 private static final String EXCL_LIST = "exclList";
57 private static final byte[] PSK_BYTES = "preSharedKey".getBytes();
58 private static final int TEST_MTU = 1300;
59
60 private final MockContext mMockContext =
61 new MockContext() {
62 @Override
63 public String getOpPackageName() {
64 return "fooPackage";
65 }
66 };
67 private final ProxyInfo mProxy = new ProxyInfo(SERVER_ADDR_STRING, -1, EXCL_LIST);
68
69 private X509Certificate mUserCert;
70 private X509Certificate mServerRootCa;
71 private PrivateKey mPrivateKey;
72
73 @Before
74 public void setUp() throws Exception {
75 mServerRootCa = generateRandomCertAndKeyPair().cert;
76
77 final CertificateAndKey userCertKey = generateRandomCertAndKeyPair();
78 mUserCert = userCertKey.cert;
79 mPrivateKey = userCertKey.key;
80 }
81
82 private Ikev2VpnProfile.Builder getBuilderWithDefaultOptions() {
83 final Ikev2VpnProfile.Builder builder =
84 new Ikev2VpnProfile.Builder(SERVER_ADDR_STRING, IDENTITY_STRING);
85
86 builder.setBypassable(true);
87 builder.setProxy(mProxy);
88 builder.setMaxMtu(TEST_MTU);
89 builder.setMetered(true);
90
91 return builder;
92 }
93
94 @Test
95 public void testBuildValidProfileWithOptions() throws Exception {
96 final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
97
98 builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
99 final Ikev2VpnProfile profile = builder.build();
100 assertNotNull(profile);
101
102 // Check non-auth parameters correctly stored
103 assertEquals(SERVER_ADDR_STRING, profile.getServerAddr());
104 assertEquals(IDENTITY_STRING, profile.getUserIdentity());
105 assertEquals(mProxy, profile.getProxyInfo());
106 assertTrue(profile.isBypassable());
107 assertTrue(profile.isMetered());
108 assertEquals(TEST_MTU, profile.getMaxMtu());
109 }
110
111 @Test
112 public void testBuildUsernamePasswordProfile() throws Exception {
113 final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
114
115 builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
116 final Ikev2VpnProfile profile = builder.build();
117 assertNotNull(profile);
118
119 assertEquals(USERNAME_STRING, profile.getUsername());
120 assertEquals(PASSWORD_STRING, profile.getPassword());
121 assertEquals(mServerRootCa, profile.getServerRootCaCert());
122
123 assertNull(profile.getPresharedKey());
124 assertNull(profile.getRsaPrivateKey());
125 assertNull(profile.getUserCert());
126 }
127
128 @Test
129 public void testBuildDigitalSignatureProfile() throws Exception {
130 final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
131
132 builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
133 final Ikev2VpnProfile profile = builder.build();
134 assertNotNull(profile);
135
136 assertEquals(profile.getUserCert(), mUserCert);
137 assertEquals(mPrivateKey, profile.getRsaPrivateKey());
138 assertEquals(profile.getServerRootCaCert(), mServerRootCa);
139
140 assertNull(profile.getPresharedKey());
141 assertNull(profile.getUsername());
142 assertNull(profile.getPassword());
143 }
144
145 @Test
146 public void testBuildPresharedKeyProfile() throws Exception {
147 final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
148
149 builder.setAuthPsk(PSK_BYTES);
150 final Ikev2VpnProfile profile = builder.build();
151 assertNotNull(profile);
152
153 assertArrayEquals(PSK_BYTES, profile.getPresharedKey());
154
155 assertNull(profile.getServerRootCaCert());
156 assertNull(profile.getUsername());
157 assertNull(profile.getPassword());
158 assertNull(profile.getRsaPrivateKey());
159 assertNull(profile.getUserCert());
160 }
161
162 @Test
163 public void testBuildNoAuthMethodSet() throws Exception {
164 final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
165
166 try {
167 builder.build();
168 fail("Expected exception due to lack of auth method");
169 } catch (IllegalArgumentException expected) {
170 }
171 }
172
173 @Test
174 public void testBuildInvalidMtu() throws Exception {
175 final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
176
177 try {
178 builder.setMaxMtu(500);
179 fail("Expected exception due to too-small MTU");
180 } catch (IllegalArgumentException expected) {
181 }
182 }
183
184 private void verifyVpnProfileCommon(VpnProfile profile) {
185 assertEquals(SERVER_ADDR_STRING, profile.server);
186 assertEquals(IDENTITY_STRING, profile.ipsecIdentifier);
187 assertEquals(mProxy, profile.proxy);
188 assertTrue(profile.isBypassable);
189 assertTrue(profile.isMetered);
190 assertEquals(TEST_MTU, profile.maxMtu);
191 }
192
193 @Test
194 public void testPskConvertToVpnProfile() throws Exception {
195 final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
196
197 builder.setAuthPsk(PSK_BYTES);
198 final VpnProfile profile = builder.build().toVpnProfile();
199
200 verifyVpnProfileCommon(profile);
201 assertEquals(Ikev2VpnProfile.encodeForIpsecSecret(PSK_BYTES), profile.ipsecSecret);
202
203 // Check nothing else is set
204 assertEquals("", profile.username);
205 assertEquals("", profile.password);
206 assertEquals("", profile.ipsecUserCert);
207 assertEquals("", profile.ipsecCaCert);
208 }
209
210 @Test
211 public void testUsernamePasswordConvertToVpnProfile() throws Exception {
212 final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
213
214 builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
215 final VpnProfile profile = builder.build().toVpnProfile();
216
217 verifyVpnProfileCommon(profile);
218 assertEquals(USERNAME_STRING, profile.username);
219 assertEquals(PASSWORD_STRING, profile.password);
220 assertEquals(Ikev2VpnProfile.certificateToPemString(mServerRootCa), profile.ipsecCaCert);
221
222 // Check nothing else is set
223 assertEquals("", profile.ipsecUserCert);
224 assertEquals("", profile.ipsecSecret);
225 }
226
227 @Test
228 public void testRsaConvertToVpnProfile() throws Exception {
229 final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
230
231 builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
232 final VpnProfile profile = builder.build().toVpnProfile();
233
Benedict Wongd896b132020-01-17 19:41:38 -0800234 final String expectedSecret = Ikev2VpnProfile.PREFIX_INLINE
235 + Ikev2VpnProfile.encodeForIpsecSecret(mPrivateKey.getEncoded());
Benedict Wong4416f382019-11-01 16:45:08 -0700236 verifyVpnProfileCommon(profile);
237 assertEquals(Ikev2VpnProfile.certificateToPemString(mUserCert), profile.ipsecUserCert);
238 assertEquals(
Benedict Wongd896b132020-01-17 19:41:38 -0800239 expectedSecret,
Benedict Wong4416f382019-11-01 16:45:08 -0700240 profile.ipsecSecret);
241 assertEquals(Ikev2VpnProfile.certificateToPemString(mServerRootCa), profile.ipsecCaCert);
242
243 // Check nothing else is set
244 assertEquals("", profile.username);
245 assertEquals("", profile.password);
246 }
247
248 @Test
249 public void testPskFromVpnProfileDiscardsIrrelevantValues() throws Exception {
250 final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
251
252 builder.setAuthPsk(PSK_BYTES);
253 final VpnProfile profile = builder.build().toVpnProfile();
254 profile.username = USERNAME_STRING;
255 profile.password = PASSWORD_STRING;
256 profile.ipsecCaCert = Ikev2VpnProfile.certificateToPemString(mServerRootCa);
257 profile.ipsecUserCert = Ikev2VpnProfile.certificateToPemString(mUserCert);
258
259 final Ikev2VpnProfile result = Ikev2VpnProfile.fromVpnProfile(profile);
260 assertNull(result.getUsername());
261 assertNull(result.getPassword());
262 assertNull(result.getUserCert());
263 assertNull(result.getRsaPrivateKey());
264 assertNull(result.getServerRootCaCert());
265 }
266
267 @Test
268 public void testUsernamePasswordFromVpnProfileDiscardsIrrelevantValues() throws Exception {
269 final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
270
271 builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
272 final VpnProfile profile = builder.build().toVpnProfile();
273 profile.ipsecSecret = new String(PSK_BYTES);
274 profile.ipsecUserCert = Ikev2VpnProfile.certificateToPemString(mUserCert);
275
276 final Ikev2VpnProfile result = Ikev2VpnProfile.fromVpnProfile(profile);
277 assertNull(result.getPresharedKey());
278 assertNull(result.getUserCert());
279 assertNull(result.getRsaPrivateKey());
280 }
281
282 @Test
283 public void testRsaFromVpnProfileDiscardsIrrelevantValues() throws Exception {
284 final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
285
286 builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
287 final VpnProfile profile = builder.build().toVpnProfile();
288 profile.username = USERNAME_STRING;
289 profile.password = PASSWORD_STRING;
290
291 final Ikev2VpnProfile result = Ikev2VpnProfile.fromVpnProfile(profile);
292 assertNull(result.getUsername());
293 assertNull(result.getPassword());
294 assertNull(result.getPresharedKey());
295 }
296
297 @Test
298 public void testPskConversionIsLossless() throws Exception {
299 final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
300
301 builder.setAuthPsk(PSK_BYTES);
302 final Ikev2VpnProfile ikeProfile = builder.build();
303
304 assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile()));
305 }
306
307 @Test
308 public void testUsernamePasswordConversionIsLossless() throws Exception {
309 final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
310
311 builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
312 final Ikev2VpnProfile ikeProfile = builder.build();
313
314 assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile()));
315 }
316
317 @Test
318 public void testRsaConversionIsLossless() throws Exception {
319 final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
320
321 builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
322 final Ikev2VpnProfile ikeProfile = builder.build();
323
324 assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile()));
325 }
326
327 private static class CertificateAndKey {
328 public final X509Certificate cert;
329 public final PrivateKey key;
330
331 CertificateAndKey(X509Certificate cert, PrivateKey key) {
332 this.cert = cert;
333 this.key = key;
334 }
335 }
336
337 private static CertificateAndKey generateRandomCertAndKeyPair() throws Exception {
338 final Date validityBeginDate =
339 new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1L));
340 final Date validityEndDate =
341 new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1L));
342
343 // Generate a keypair
344 final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
345 keyPairGenerator.initialize(512);
346 final KeyPair keyPair = keyPairGenerator.generateKeyPair();
347
348 final X500Principal dnName = new X500Principal("CN=test.android.com");
349 final X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
350 certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
351 certGen.setSubjectDN(dnName);
352 certGen.setIssuerDN(dnName);
353 certGen.setNotBefore(validityBeginDate);
354 certGen.setNotAfter(validityEndDate);
355 certGen.setPublicKey(keyPair.getPublic());
356 certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
357
358 final X509Certificate cert = certGen.generate(keyPair.getPrivate(), "AndroidOpenSSL");
359 return new CertificateAndKey(cert, keyPair.getPrivate());
360 }
361}