blob: 1ddab5b47846b3e5a576dcd899db66ba42ef7c9f [file] [log] [blame]
Nathan Harold2e9a5202017-09-26 11:44:23 -07001/*
2 * Copyright (C) 2017 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 com.android.server;
18
19import static org.junit.Assert.assertEquals;
Benedict Wong0febe5e2017-08-22 21:42:33 -070020import static org.junit.Assert.fail;
Nathan Harold2e9a5202017-09-26 11:44:23 -070021import static org.mockito.Matchers.anyInt;
22import static org.mockito.Matchers.anyLong;
23import static org.mockito.Matchers.anyString;
24import static org.mockito.Matchers.eq;
25import static org.mockito.Mockito.mock;
26import static org.mockito.Mockito.verify;
27import static org.mockito.Mockito.when;
28
29import android.content.Context;
30import android.net.INetd;
31import android.net.IpSecAlgorithm;
32import android.net.IpSecConfig;
33import android.net.IpSecManager;
34import android.net.IpSecSpiResponse;
Nathan Harold2e9a5202017-09-26 11:44:23 -070035import android.net.IpSecTransformResponse;
36import android.net.NetworkUtils;
37import android.os.Binder;
38import android.os.ParcelFileDescriptor;
39import android.support.test.filters.SmallTest;
Benedict Wong344bd622017-11-16 15:27:22 -080040import android.system.Os;
Nathan Harold2e9a5202017-09-26 11:44:23 -070041
42import java.net.Socket;
43import java.util.Arrays;
44import java.util.Collection;
45
46import org.junit.Before;
47import org.junit.Test;
48import org.junit.runner.RunWith;
49import org.junit.runners.Parameterized;
50
51/** Unit tests for {@link IpSecService}. */
52@SmallTest
53@RunWith(Parameterized.class)
54public class IpSecServiceParameterizedTest {
55
Nathan Harolda2523312018-01-05 19:25:13 -080056 private static final int TEST_SPI = 0xD1201D;
Nathan Harold2e9a5202017-09-26 11:44:23 -070057
Nathan Harolda2523312018-01-05 19:25:13 -080058 private final String mDestinationAddr;
Nathan Harold5676f5f2018-01-16 19:34:01 -080059 private final String mSourceAddr;
Nathan Harold2e9a5202017-09-26 11:44:23 -070060
61 @Parameterized.Parameters
62 public static Collection ipSecConfigs() {
Nathan Harold5676f5f2018-01-16 19:34:01 -080063 return Arrays.asList(new Object[][] {{"1.2.3.4", "8.8.4.4"}, {"2601::2", "2601::10"}});
Nathan Harold2e9a5202017-09-26 11:44:23 -070064 }
65
Benedict Wong4ebc2c52017-11-01 17:14:25 -070066 private static final byte[] AEAD_KEY = {
67 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
68 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
69 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
70 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
71 0x73, 0x61, 0x6C, 0x74
72 };
Nathan Harold2e9a5202017-09-26 11:44:23 -070073 private static final byte[] CRYPT_KEY = {
74 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
75 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
76 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
77 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
78 };
79 private static final byte[] AUTH_KEY = {
80 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
82 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F
84 };
85
86 Context mMockContext;
87 INetd mMockNetd;
88 IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
89 IpSecService mIpSecService;
90
Benedict Wong0febe5e2017-08-22 21:42:33 -070091 private static final IpSecAlgorithm AUTH_ALGO =
92 new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4);
93 private static final IpSecAlgorithm CRYPT_ALGO =
94 new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
95 private static final IpSecAlgorithm AEAD_ALGO =
Benedict Wong4ebc2c52017-11-01 17:14:25 -070096 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
Benedict Wong0febe5e2017-08-22 21:42:33 -070097
Nathan Harold5676f5f2018-01-16 19:34:01 -080098 public IpSecServiceParameterizedTest(String sourceAddr, String destAddr) {
99 mSourceAddr = sourceAddr;
100 mDestinationAddr = destAddr;
Nathan Harold2e9a5202017-09-26 11:44:23 -0700101 }
102
103 @Before
104 public void setUp() throws Exception {
105 mMockContext = mock(Context.class);
106 mMockNetd = mock(INetd.class);
107 mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class);
108 mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig);
109
110 // Injecting mock netd
111 when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd);
112 }
113
114 @Test
115 public void testIpSecServiceReserveSpi() throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800116 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
117 .thenReturn(TEST_SPI);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700118
119 IpSecSpiResponse spiResp =
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800120 mIpSecService.allocateSecurityParameterIndex(
Nathan Harolda2523312018-01-05 19:25:13 -0800121 mDestinationAddr, TEST_SPI, new Binder());
Nathan Harold2e9a5202017-09-26 11:44:23 -0700122 assertEquals(IpSecManager.Status.OK, spiResp.status);
Nathan Harolda2523312018-01-05 19:25:13 -0800123 assertEquals(TEST_SPI, spiResp.spi);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700124 }
125
126 @Test
127 public void testReleaseSecurityParameterIndex() throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800128 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
129 .thenReturn(TEST_SPI);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700130
131 IpSecSpiResponse spiResp =
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800132 mIpSecService.allocateSecurityParameterIndex(
Nathan Harolda2523312018-01-05 19:25:13 -0800133 mDestinationAddr, TEST_SPI, new Binder());
Nathan Harold2e9a5202017-09-26 11:44:23 -0700134
135 mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId);
136
137 verify(mMockNetd)
138 .ipSecDeleteSecurityAssociation(
Nathan Harolda2523312018-01-05 19:25:13 -0800139 eq(spiResp.resourceId), anyString(), anyString(), eq(TEST_SPI));
Benedict Wong344bd622017-11-16 15:27:22 -0800140
141 // Verify quota and RefcountedResource objects cleaned up
142 IpSecService.UserRecord userRecord =
143 mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
144 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
145 try {
146 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
147 fail("Expected IllegalArgumentException on attempt to access deleted resource");
148 } catch (IllegalArgumentException expected) {
149
150 }
151 }
152
153 @Test
154 public void testSecurityParameterIndexBinderDeath() throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800155 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
156 .thenReturn(TEST_SPI);
Benedict Wong344bd622017-11-16 15:27:22 -0800157
158 IpSecSpiResponse spiResp =
Nathan Harold660a3352017-12-14 14:46:46 -0800159 mIpSecService.allocateSecurityParameterIndex(
Nathan Harolda2523312018-01-05 19:25:13 -0800160 mDestinationAddr, TEST_SPI, new Binder());
Benedict Wong344bd622017-11-16 15:27:22 -0800161
162 IpSecService.UserRecord userRecord =
163 mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
164 IpSecService.RefcountedResource refcountedRecord =
165 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
166
167 refcountedRecord.binderDied();
168
169 verify(mMockNetd)
170 .ipSecDeleteSecurityAssociation(
Nathan Harolda2523312018-01-05 19:25:13 -0800171 eq(spiResp.resourceId), anyString(), anyString(), eq(TEST_SPI));
Benedict Wong344bd622017-11-16 15:27:22 -0800172
173 // Verify quota and RefcountedResource objects cleaned up
174 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
175 try {
176 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
177 fail("Expected IllegalArgumentException on attempt to access deleted resource");
178 } catch (IllegalArgumentException expected) {
179
180 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700181 }
182
Nathan Harolda2523312018-01-05 19:25:13 -0800183 private int getNewSpiResourceId(String remoteAddress, int returnSpi) throws Exception {
184 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), anyString(), anyInt()))
Benedict Wong0febe5e2017-08-22 21:42:33 -0700185 .thenReturn(returnSpi);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700186
Benedict Wong0febe5e2017-08-22 21:42:33 -0700187 IpSecSpiResponse spi =
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800188 mIpSecService.allocateSecurityParameterIndex(
Benedict Wong0febe5e2017-08-22 21:42:33 -0700189 NetworkUtils.numericToInetAddress(remoteAddress).getHostAddress(),
190 IpSecManager.INVALID_SECURITY_PARAMETER_INDEX,
191 new Binder());
192 return spi.resourceId;
193 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700194
Benedict Wong0febe5e2017-08-22 21:42:33 -0700195 private void addDefaultSpisAndRemoteAddrToIpSecConfig(IpSecConfig config) throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800196 config.setSpiResourceId(getNewSpiResourceId(mDestinationAddr, TEST_SPI));
Nathan Harold5676f5f2018-01-16 19:34:01 -0800197 config.setSourceAddress(mSourceAddr);
Nathan Harolda2523312018-01-05 19:25:13 -0800198 config.setDestinationAddress(mDestinationAddr);
Benedict Wong0febe5e2017-08-22 21:42:33 -0700199 }
200
201 private void addAuthAndCryptToIpSecConfig(IpSecConfig config) throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800202 config.setEncryption(CRYPT_ALGO);
203 config.setAuthentication(AUTH_ALGO);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700204 }
205
206 @Test
207 public void testCreateTransportModeTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700208 IpSecConfig ipSecConfig = new IpSecConfig();
209 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
210 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700211
212 IpSecTransformResponse createTransformResp =
213 mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
214 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
215
216 verify(mMockNetd)
217 .ipSecAddSecurityAssociation(
218 eq(createTransformResp.resourceId),
219 anyInt(),
Nathan Harold2e9a5202017-09-26 11:44:23 -0700220 anyString(),
221 anyString(),
222 anyLong(),
Nathan Harolda2523312018-01-05 19:25:13 -0800223 eq(TEST_SPI),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700224 eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
225 eq(AUTH_KEY),
226 anyInt(),
227 eq(IpSecAlgorithm.CRYPT_AES_CBC),
228 eq(CRYPT_KEY),
229 anyInt(),
230 eq(""),
Manoj Boopathi Rajfffa8112017-10-26 11:49:02 -0700231 eq(new byte[] {}),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700232 eq(0),
233 anyInt(),
234 anyInt(),
235 anyInt());
236 }
237
238 @Test
239 public void testCreateTransportModeTransformAead() throws Exception {
240 IpSecConfig ipSecConfig = new IpSecConfig();
241 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
242
Nathan Harolda2523312018-01-05 19:25:13 -0800243 ipSecConfig.setAuthenticatedEncryption(AEAD_ALGO);
Benedict Wong0febe5e2017-08-22 21:42:33 -0700244
245 IpSecTransformResponse createTransformResp =
246 mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
247 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
248
249 verify(mMockNetd)
250 .ipSecAddSecurityAssociation(
251 eq(createTransformResp.resourceId),
252 anyInt(),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700253 anyString(),
254 anyString(),
255 anyLong(),
Nathan Harolda2523312018-01-05 19:25:13 -0800256 eq(TEST_SPI),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700257 eq(""),
Manoj Boopathi Rajfffa8112017-10-26 11:49:02 -0700258 eq(new byte[] {}),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700259 eq(0),
260 eq(""),
Manoj Boopathi Rajfffa8112017-10-26 11:49:02 -0700261 eq(new byte[] {}),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700262 eq(0),
263 eq(IpSecAlgorithm.AUTH_CRYPT_AES_GCM),
Benedict Wong4ebc2c52017-11-01 17:14:25 -0700264 eq(AEAD_KEY),
Nathan Harold2e9a5202017-09-26 11:44:23 -0700265 anyInt(),
266 anyInt(),
267 anyInt(),
268 anyInt());
269 }
270
271 @Test
272 public void testDeleteTransportModeTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700273 IpSecConfig ipSecConfig = new IpSecConfig();
274 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
275 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700276
277 IpSecTransformResponse createTransformResp =
278 mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
279 mIpSecService.deleteTransportModeTransform(createTransformResp.resourceId);
280
281 verify(mMockNetd)
282 .ipSecDeleteSecurityAssociation(
Nathan Harolda2523312018-01-05 19:25:13 -0800283 eq(createTransformResp.resourceId), anyString(), anyString(), eq(TEST_SPI));
Benedict Wong344bd622017-11-16 15:27:22 -0800284
285 // Verify quota and RefcountedResource objects cleaned up
286 IpSecService.UserRecord userRecord =
287 mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
288 assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent);
289 try {
290 userRecord.mTransformRecords.getRefcountedResourceOrThrow(
291 createTransformResp.resourceId);
292 fail("Expected IllegalArgumentException on attempt to access deleted resource");
293 } catch (IllegalArgumentException expected) {
294
295 }
296 }
297
298 @Test
299 public void testTransportModeTransformBinderDeath() throws Exception {
300 IpSecConfig ipSecConfig = new IpSecConfig();
301 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
302 addAuthAndCryptToIpSecConfig(ipSecConfig);
303
304 IpSecTransformResponse createTransformResp =
305 mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
306
307 IpSecService.UserRecord userRecord =
308 mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
309 IpSecService.RefcountedResource refcountedRecord =
310 userRecord.mTransformRecords.getRefcountedResourceOrThrow(
311 createTransformResp.resourceId);
312
313 refcountedRecord.binderDied();
314
315 verify(mMockNetd)
316 .ipSecDeleteSecurityAssociation(
Nathan Harolda2523312018-01-05 19:25:13 -0800317 eq(createTransformResp.resourceId), anyString(), anyString(), eq(TEST_SPI));
Benedict Wong344bd622017-11-16 15:27:22 -0800318
319 // Verify quota and RefcountedResource objects cleaned up
320 assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent);
321 try {
322 userRecord.mTransformRecords.getRefcountedResourceOrThrow(
323 createTransformResp.resourceId);
324 fail("Expected IllegalArgumentException on attempt to access deleted resource");
325 } catch (IllegalArgumentException expected) {
326
327 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700328 }
329
330 @Test
331 public void testApplyTransportModeTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700332 IpSecConfig ipSecConfig = new IpSecConfig();
333 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
334 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700335
336 IpSecTransformResponse createTransformResp =
337 mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
338 ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
339
340 int resourceId = createTransformResp.resourceId;
Nathan Harolda2523312018-01-05 19:25:13 -0800341 mIpSecService.applyTransportModeTransform(pfd, IpSecManager.DIRECTION_OUT, resourceId);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700342
343 verify(mMockNetd)
344 .ipSecApplyTransportModeTransform(
345 eq(pfd.getFileDescriptor()),
346 eq(resourceId),
Nathan Harolda2523312018-01-05 19:25:13 -0800347 eq(IpSecManager.DIRECTION_OUT),
Nathan Harold2e9a5202017-09-26 11:44:23 -0700348 anyString(),
349 anyString(),
Nathan Harolda2523312018-01-05 19:25:13 -0800350 eq(TEST_SPI));
Nathan Harold2e9a5202017-09-26 11:44:23 -0700351 }
352
353 @Test
354 public void testRemoveTransportModeTransform() throws Exception {
355 ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
Nathan Harolda2523312018-01-05 19:25:13 -0800356 mIpSecService.removeTransportModeTransforms(pfd, 1);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700357
358 verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
359 }
360}