blob: b4b809480ffb78c95f0b0f1fc3bffd415599d934 [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;
Benedict Wong0febe5e2017-08-22 21:42:33 -070025import static org.mockito.Matchers.isNull;
Nathan Harold2e9a5202017-09-26 11:44:23 -070026import static org.mockito.Mockito.mock;
27import static org.mockito.Mockito.verify;
28import static org.mockito.Mockito.when;
29
30import android.content.Context;
31import android.net.INetd;
32import android.net.IpSecAlgorithm;
33import android.net.IpSecConfig;
34import android.net.IpSecManager;
35import android.net.IpSecSpiResponse;
36import android.net.IpSecTransform;
37import android.net.IpSecTransformResponse;
38import android.net.NetworkUtils;
39import android.os.Binder;
40import android.os.ParcelFileDescriptor;
41import android.support.test.filters.SmallTest;
Nathan Harold2e9a5202017-09-26 11:44:23 -070042
43import java.net.Socket;
44import java.util.Arrays;
45import java.util.Collection;
46
47import org.junit.Before;
48import org.junit.Test;
49import org.junit.runner.RunWith;
50import org.junit.runners.Parameterized;
51
52/** Unit tests for {@link IpSecService}. */
53@SmallTest
54@RunWith(Parameterized.class)
55public class IpSecServiceParameterizedTest {
56
Benedict Wong0febe5e2017-08-22 21:42:33 -070057 private static final int TEST_SPI_OUT = 0xD1201D;
58 private static final int TEST_SPI_IN = TEST_SPI_OUT + 1;
Nathan Harold2e9a5202017-09-26 11:44:23 -070059
60 private final String mRemoteAddr;
61
62 @Parameterized.Parameters
63 public static Collection ipSecConfigs() {
64 return Arrays.asList(new Object[][] {{"8.8.4.4"}, {"2601::10"}});
65 }
66
67 private static final byte[] CRYPT_KEY = {
68 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
69 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
70 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
71 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
72 };
73 private static final byte[] AUTH_KEY = {
74 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
76 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F
78 };
79
80 Context mMockContext;
81 INetd mMockNetd;
82 IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
83 IpSecService mIpSecService;
84
Benedict Wong0febe5e2017-08-22 21:42:33 -070085 private static final IpSecAlgorithm AUTH_ALGO =
86 new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4);
87 private static final IpSecAlgorithm CRYPT_ALGO =
88 new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
89 private static final IpSecAlgorithm AEAD_ALGO =
90 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, CRYPT_KEY, CRYPT_KEY.length * 4);
91
92 private static final int[] DIRECTIONS =
93 new int[] {IpSecTransform.DIRECTION_IN, IpSecTransform.DIRECTION_OUT};
94
Nathan Harold2e9a5202017-09-26 11:44:23 -070095 public IpSecServiceParameterizedTest(String remoteAddr) {
96 mRemoteAddr = remoteAddr;
97 }
98
99 @Before
100 public void setUp() throws Exception {
101 mMockContext = mock(Context.class);
102 mMockNetd = mock(INetd.class);
103 mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class);
104 mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig);
105
106 // Injecting mock netd
107 when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd);
108 }
109
110 @Test
111 public void testIpSecServiceReserveSpi() throws Exception {
112 when(mMockNetd.ipSecAllocateSpi(
113 anyInt(),
114 eq(IpSecTransform.DIRECTION_OUT),
115 anyString(),
116 eq(mRemoteAddr),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700117 eq(TEST_SPI_OUT)))
118 .thenReturn(TEST_SPI_OUT);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700119
120 IpSecSpiResponse spiResp =
121 mIpSecService.reserveSecurityParameterIndex(
Benedict Wong0febe5e2017-08-22 21:42:33 -0700122 IpSecTransform.DIRECTION_OUT, mRemoteAddr, TEST_SPI_OUT, new Binder());
Nathan Harold2e9a5202017-09-26 11:44:23 -0700123 assertEquals(IpSecManager.Status.OK, spiResp.status);
Benedict Wong0febe5e2017-08-22 21:42:33 -0700124 assertEquals(TEST_SPI_OUT, spiResp.spi);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700125 }
126
127 @Test
128 public void testReleaseSecurityParameterIndex() throws Exception {
129 when(mMockNetd.ipSecAllocateSpi(
130 anyInt(),
131 eq(IpSecTransform.DIRECTION_OUT),
132 anyString(),
133 eq(mRemoteAddr),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700134 eq(TEST_SPI_OUT)))
135 .thenReturn(TEST_SPI_OUT);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700136
137 IpSecSpiResponse spiResp =
138 mIpSecService.reserveSecurityParameterIndex(
Benedict Wong0febe5e2017-08-22 21:42:33 -0700139 IpSecTransform.DIRECTION_OUT, mRemoteAddr, TEST_SPI_OUT, new Binder());
Nathan Harold2e9a5202017-09-26 11:44:23 -0700140
141 mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId);
142
143 verify(mMockNetd)
144 .ipSecDeleteSecurityAssociation(
Benedict Wong0febe5e2017-08-22 21:42:33 -0700145 eq(spiResp.resourceId),
146 anyInt(),
147 anyString(),
148 anyString(),
149 eq(TEST_SPI_OUT));
Nathan Harold2e9a5202017-09-26 11:44:23 -0700150 }
151
Benedict Wong0febe5e2017-08-22 21:42:33 -0700152 private int getNewSpiResourceId(int direction, String remoteAddress, int returnSpi)
153 throws Exception {
Nathan Harold2e9a5202017-09-26 11:44:23 -0700154 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyInt(), anyString(), anyString(), anyInt()))
Benedict Wong0febe5e2017-08-22 21:42:33 -0700155 .thenReturn(returnSpi);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700156
Benedict Wong0febe5e2017-08-22 21:42:33 -0700157 IpSecSpiResponse spi =
158 mIpSecService.reserveSecurityParameterIndex(
159 direction,
160 NetworkUtils.numericToInetAddress(remoteAddress).getHostAddress(),
161 IpSecManager.INVALID_SECURITY_PARAMETER_INDEX,
162 new Binder());
163 return spi.resourceId;
164 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700165
Benedict Wong0febe5e2017-08-22 21:42:33 -0700166 private void addDefaultSpisAndRemoteAddrToIpSecConfig(IpSecConfig config) throws Exception {
167 config.setSpiResourceId(
168 IpSecTransform.DIRECTION_OUT,
169 getNewSpiResourceId(IpSecTransform.DIRECTION_OUT, mRemoteAddr, TEST_SPI_OUT));
170 config.setSpiResourceId(
171 IpSecTransform.DIRECTION_IN,
172 getNewSpiResourceId(IpSecTransform.DIRECTION_IN, mRemoteAddr, TEST_SPI_IN));
Nathan Harold2e9a5202017-09-26 11:44:23 -0700173 config.setRemoteAddress(mRemoteAddr);
Benedict Wong0febe5e2017-08-22 21:42:33 -0700174 }
175
176 private void addAuthAndCryptToIpSecConfig(IpSecConfig config) throws Exception {
177 for (int direction : DIRECTIONS) {
178 config.setEncryption(direction, CRYPT_ALGO);
179 config.setAuthentication(direction, AUTH_ALGO);
180 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700181 }
182
183 @Test
184 public void testCreateTransportModeTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700185 IpSecConfig ipSecConfig = new IpSecConfig();
186 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
187 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700188
189 IpSecTransformResponse createTransformResp =
190 mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
191 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
192
193 verify(mMockNetd)
194 .ipSecAddSecurityAssociation(
195 eq(createTransformResp.resourceId),
196 anyInt(),
197 eq(IpSecTransform.DIRECTION_OUT),
198 anyString(),
199 anyString(),
200 anyLong(),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700201 eq(TEST_SPI_OUT),
Nathan Harold2e9a5202017-09-26 11:44:23 -0700202 eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
203 eq(AUTH_KEY),
204 anyInt(),
205 eq(IpSecAlgorithm.CRYPT_AES_CBC),
206 eq(CRYPT_KEY),
207 anyInt(),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700208 eq(""),
209 isNull(),
210 eq(0),
211 anyInt(),
212 anyInt(),
213 anyInt());
214 verify(mMockNetd)
215 .ipSecAddSecurityAssociation(
216 eq(createTransformResp.resourceId),
217 anyInt(),
218 eq(IpSecTransform.DIRECTION_IN),
219 anyString(),
220 anyString(),
221 anyLong(),
222 eq(TEST_SPI_IN),
223 eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
224 eq(AUTH_KEY),
225 anyInt(),
226 eq(IpSecAlgorithm.CRYPT_AES_CBC),
227 eq(CRYPT_KEY),
228 anyInt(),
229 eq(""),
230 isNull(),
231 eq(0),
232 anyInt(),
233 anyInt(),
234 anyInt());
235 }
236
237 @Test
238 public void testCreateTransportModeTransformAead() throws Exception {
239 IpSecConfig ipSecConfig = new IpSecConfig();
240 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
241
242 ipSecConfig.setAuthenticatedEncryption(IpSecTransform.DIRECTION_OUT, AEAD_ALGO);
243 ipSecConfig.setAuthenticatedEncryption(IpSecTransform.DIRECTION_IN, AEAD_ALGO);
244
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(),
253 eq(IpSecTransform.DIRECTION_OUT),
254 anyString(),
255 anyString(),
256 anyLong(),
257 eq(TEST_SPI_OUT),
258 eq(""),
259 isNull(),
260 eq(0),
261 eq(""),
262 isNull(),
263 eq(0),
264 eq(IpSecAlgorithm.AUTH_CRYPT_AES_GCM),
265 eq(CRYPT_KEY),
266 anyInt(),
Nathan Harold2e9a5202017-09-26 11:44:23 -0700267 anyInt(),
268 anyInt(),
269 anyInt());
270 verify(mMockNetd)
271 .ipSecAddSecurityAssociation(
272 eq(createTransformResp.resourceId),
273 anyInt(),
274 eq(IpSecTransform.DIRECTION_IN),
275 anyString(),
276 anyString(),
277 anyLong(),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700278 eq(TEST_SPI_IN),
279 eq(""),
280 isNull(),
281 eq(0),
282 eq(""),
283 isNull(),
284 eq(0),
285 eq(IpSecAlgorithm.AUTH_CRYPT_AES_GCM),
Nathan Harold2e9a5202017-09-26 11:44:23 -0700286 eq(CRYPT_KEY),
287 anyInt(),
288 anyInt(),
289 anyInt(),
290 anyInt());
291 }
292
293 @Test
Benedict Wong0febe5e2017-08-22 21:42:33 -0700294 public void testCreateInvalidConfigAeadWithAuth() throws Exception {
295 IpSecConfig ipSecConfig = new IpSecConfig();
296 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
297
298 for (int direction : DIRECTIONS) {
299 ipSecConfig.setAuthentication(direction, AUTH_ALGO);
300 ipSecConfig.setAuthenticatedEncryption(direction, AEAD_ALGO);
301 }
302
303 try {
304 mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
305 fail(
306 "IpSecService should have thrown an error on authentication being"
307 + " enabled with authenticated encryption");
308 } catch (IllegalArgumentException expected) {
309 }
310 }
311
312 @Test
313 public void testCreateInvalidConfigAeadWithCrypt() throws Exception {
314 IpSecConfig ipSecConfig = new IpSecConfig();
315 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
316
317 for (int direction : DIRECTIONS) {
318 ipSecConfig.setEncryption(direction, CRYPT_ALGO);
319 ipSecConfig.setAuthenticatedEncryption(direction, AEAD_ALGO);
320 }
321
322 try {
323 mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
324 fail(
325 "IpSecService should have thrown an error on encryption being"
326 + " enabled with authenticated encryption");
327 } catch (IllegalArgumentException expected) {
328 }
329 }
330
331 @Test
332 public void testCreateInvalidConfigAeadWithAuthAndCrypt() throws Exception {
333 IpSecConfig ipSecConfig = new IpSecConfig();
334 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
335
336 for (int direction : DIRECTIONS) {
337 ipSecConfig.setAuthentication(direction, AUTH_ALGO);
338 ipSecConfig.setEncryption(direction, CRYPT_ALGO);
339 ipSecConfig.setAuthenticatedEncryption(direction, AEAD_ALGO);
340 }
341
342 try {
343 mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
344 fail(
345 "IpSecService should have thrown an error on authentication and encryption being"
346 + " enabled with authenticated encryption");
347 } catch (IllegalArgumentException expected) {
348 }
349 }
350
351 @Test
Nathan Harold2e9a5202017-09-26 11:44:23 -0700352 public void testDeleteTransportModeTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700353 IpSecConfig ipSecConfig = new IpSecConfig();
354 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
355 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700356
357 IpSecTransformResponse createTransformResp =
358 mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
359 mIpSecService.deleteTransportModeTransform(createTransformResp.resourceId);
360
361 verify(mMockNetd)
362 .ipSecDeleteSecurityAssociation(
363 eq(createTransformResp.resourceId),
364 eq(IpSecTransform.DIRECTION_OUT),
365 anyString(),
366 anyString(),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700367 eq(TEST_SPI_OUT));
Nathan Harold2e9a5202017-09-26 11:44:23 -0700368 verify(mMockNetd)
369 .ipSecDeleteSecurityAssociation(
370 eq(createTransformResp.resourceId),
371 eq(IpSecTransform.DIRECTION_IN),
372 anyString(),
373 anyString(),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700374 eq(TEST_SPI_IN));
Nathan Harold2e9a5202017-09-26 11:44:23 -0700375 }
376
377 @Test
378 public void testApplyTransportModeTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700379 IpSecConfig ipSecConfig = new IpSecConfig();
380 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
381 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700382
383 IpSecTransformResponse createTransformResp =
384 mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
385 ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
386
387 int resourceId = createTransformResp.resourceId;
388 mIpSecService.applyTransportModeTransform(pfd, resourceId);
389
390 verify(mMockNetd)
391 .ipSecApplyTransportModeTransform(
392 eq(pfd.getFileDescriptor()),
393 eq(resourceId),
394 eq(IpSecTransform.DIRECTION_OUT),
395 anyString(),
396 anyString(),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700397 eq(TEST_SPI_OUT));
Nathan Harold2e9a5202017-09-26 11:44:23 -0700398 verify(mMockNetd)
399 .ipSecApplyTransportModeTransform(
400 eq(pfd.getFileDescriptor()),
401 eq(resourceId),
402 eq(IpSecTransform.DIRECTION_IN),
403 anyString(),
404 anyString(),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700405 eq(TEST_SPI_IN));
Nathan Harold2e9a5202017-09-26 11:44:23 -0700406 }
407
408 @Test
409 public void testRemoveTransportModeTransform() throws Exception {
410 ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
411 mIpSecService.removeTransportModeTransform(pfd, 1);
412
413 verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
414 }
415}