Merge changes from topic "ipsec-tunnel-tests" into qt-dev
* changes:
Remove mContext from IpSecBaseTest
Add reflected-packet based data tests
Cleanup IPsec CTS tests
diff --git a/tests/cts/net/src/android/net/cts/IpSecBaseTest.java b/tests/cts/net/src/android/net/cts/IpSecBaseTest.java
index 26049cc..10e43e7 100644
--- a/tests/cts/net/src/android/net/cts/IpSecBaseTest.java
+++ b/tests/cts/net/src/android/net/cts/IpSecBaseTest.java
@@ -76,11 +76,9 @@
protected ConnectivityManager mCM;
protected IpSecManager mISM;
- protected Context mContext;
@Before
public void setUp() throws Exception {
- mContext = InstrumentationRegistry.getContext();
mISM =
(IpSecManager)
InstrumentationRegistry.getContext()
@@ -475,7 +473,7 @@
private IpSecTransform buildDefaultTransform(InetAddress localAddr) throws Exception {
try (IpSecManager.SecurityParameterIndex spi =
mISM.allocateSecurityParameterIndex(localAddr)) {
- return buildIpSecTransform(mContext, spi, null, localAddr);
+ return buildIpSecTransform(InstrumentationRegistry.getContext(), spi, null, localAddr);
}
}
diff --git a/tests/cts/net/src/android/net/cts/IpSecManagerTest.java b/tests/cts/net/src/android/net/cts/IpSecManagerTest.java
index 1241785..355b496 100644
--- a/tests/cts/net/src/android/net/cts/IpSecManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/IpSecManagerTest.java
@@ -41,6 +41,7 @@
import android.system.Os;
import android.system.OsConstants;
+import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import java.io.FileDescriptor;
@@ -73,12 +74,6 @@
private static final byte[] AEAD_KEY = getKey(288);
- @Before
- @Override
- public void setUp() throws Exception {
- super.setUp();
- }
-
/*
* Allocate a random SPI
* Allocate a specific SPI using previous randomly created SPI value
@@ -244,7 +239,7 @@
mISM.allocateSecurityParameterIndex(localAddr);
IpSecTransform transform =
- new IpSecTransform.Builder(mContext)
+ new IpSecTransform.Builder(InstrumentationRegistry.getContext())
.setEncryption(new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
.setAuthentication(
new IpSecAlgorithm(
@@ -462,7 +457,8 @@
IpSecManager.SecurityParameterIndex spi =
mISM.allocateSecurityParameterIndex(local)) {
- IpSecTransform.Builder transformBuilder = new IpSecTransform.Builder(mContext);
+ IpSecTransform.Builder transformBuilder =
+ new IpSecTransform.Builder(InstrumentationRegistry.getContext());
if (crypt != null) {
transformBuilder.setEncryption(crypt);
}
@@ -623,7 +619,7 @@
try (IpSecManager.SecurityParameterIndex spi =
mISM.allocateSecurityParameterIndex(local);
IpSecTransform transform =
- new IpSecTransform.Builder(mContext)
+ new IpSecTransform.Builder(InstrumentationRegistry.getContext())
.setEncryption(crypt)
.setAuthentication(auth)
.setIpv4Encapsulation(encapSocket, encapSocket.getPort())
diff --git a/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java b/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java
index ef6bfc0..999d2f1 100644
--- a/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java
+++ b/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java
@@ -129,15 +129,15 @@
// right appop permissions.
setAppop(OP_MANAGE_IPSEC_TUNNELS, true);
- TestNetworkInterface testIntf =
+ TestNetworkInterface testIface =
sTNM.createTunInterface(
new LinkAddress[] {
new LinkAddress(LOCAL_OUTER_4, IP4_PREFIX_LEN),
new LinkAddress(LOCAL_OUTER_6, IP6_PREFIX_LEN)
});
- sTunFd = testIntf.getFileDescriptor();
- sTunNetworkCallback = setupAndGetTestNetwork(testIntf.getInterfaceName());
+ sTunFd = testIface.getFileDescriptor();
+ sTunNetworkCallback = setupAndGetTestNetwork(testIface.getInterfaceName());
sTunNetwork = sTunNetworkCallback.getNetworkBlocking();
sTunUtils = new TunUtils(sTunFd);
@@ -242,8 +242,16 @@
}
/* Test runnables for callbacks after IPsec tunnels are set up. */
- private interface TestRunnable {
- void run(Network ipsecNetwork) throws Exception;
+ private abstract class IpSecTunnelTestRunnable {
+ /**
+ * Runs the test code, and returns the inner socket port, if any.
+ *
+ * @param ipsecNetwork The IPsec Interface based Network for binding sockets on
+ * @return the integer port of the inner socket if outbound, or 0 if inbound
+ * IpSecTunnelTestRunnable
+ * @throws Exception if any part of the test failed.
+ */
+ public abstract int run(Network ipsecNetwork) throws Exception;
}
private static class TestNetworkCallback extends ConnectivityManager.NetworkCallback {
@@ -290,8 +298,8 @@
return expectedPacketSize;
}
- private interface TestRunnableFactory {
- TestRunnable getTestRunnable(
+ private interface IpSecTunnelTestRunnableFactory {
+ IpSecTunnelTestRunnable getIpSecTunnelTestRunnable(
boolean transportInTunnelMode,
int spi,
InetAddress localInner,
@@ -301,12 +309,13 @@
IpSecTransform inTransportTransform,
IpSecTransform outTransportTransform,
int encapPort,
+ int innerSocketPort,
int expectedPacketSize)
throws Exception;
}
- private class OutputTestRunnableFactory implements TestRunnableFactory {
- public TestRunnable getTestRunnable(
+ private class OutputIpSecTunnelTestRunnableFactory implements IpSecTunnelTestRunnableFactory {
+ public IpSecTunnelTestRunnable getIpSecTunnelTestRunnable(
boolean transportInTunnelMode,
int spi,
InetAddress localInner,
@@ -316,13 +325,15 @@
IpSecTransform inTransportTransform,
IpSecTransform outTransportTransform,
int encapPort,
+ int unusedInnerSocketPort,
int expectedPacketSize) {
- return new TestRunnable() {
+ return new IpSecTunnelTestRunnable() {
@Override
- public void run(Network ipsecNetwork) throws Exception {
+ public int run(Network ipsecNetwork) throws Exception {
// Build a socket and send traffic
JavaUdpSocket socket = new JavaUdpSocket(localInner);
ipsecNetwork.bindSocket(socket.mSocket);
+ int innerSocketPort = socket.getPort();
// For Transport-In-Tunnel mode, apply transform to socket
if (transportInTunnelMode) {
@@ -335,19 +346,22 @@
socket.sendTo(TEST_DATA, remoteInner, socket.getPort());
// Verify that an encrypted packet is sent. As of right now, checking encrypted
- // body is not possible, due to our not knowing some of the fields of the
+ // body is not possible, due to the test not knowing some of the fields of the
// inner IP header (flow label, flags, etc)
sTunUtils.awaitEspPacketNoPlaintext(
spi, TEST_DATA, encapPort != 0, expectedPacketSize);
socket.close();
+
+ return innerSocketPort;
}
};
}
}
- private class InputPacketGeneratorTestRunnableFactory implements TestRunnableFactory {
- public TestRunnable getTestRunnable(
+ private class InputReflectedIpSecTunnelTestRunnableFactory
+ implements IpSecTunnelTestRunnableFactory {
+ public IpSecTunnelTestRunnable getIpSecTunnelTestRunnable(
boolean transportInTunnelMode,
int spi,
InetAddress localInner,
@@ -357,14 +371,57 @@
IpSecTransform inTransportTransform,
IpSecTransform outTransportTransform,
int encapPort,
+ int innerSocketPort,
int expectedPacketSize)
throws Exception {
- return new TestRunnable() {
+ return new IpSecTunnelTestRunnable() {
@Override
- public void run(Network ipsecNetwork) throws Exception {
+ public int run(Network ipsecNetwork) throws Exception {
+ // Build a socket and receive traffic
+ JavaUdpSocket socket = new JavaUdpSocket(localInner, innerSocketPort);
+ ipsecNetwork.bindSocket(socket.mSocket);
+
+ // For Transport-In-Tunnel mode, apply transform to socket
+ if (transportInTunnelMode) {
+ mISM.applyTransportModeTransform(
+ socket.mSocket, IpSecManager.DIRECTION_IN, outTransportTransform);
+ mISM.applyTransportModeTransform(
+ socket.mSocket, IpSecManager.DIRECTION_OUT, inTransportTransform);
+ }
+
+ sTunUtils.reflectPackets();
+
+ // Receive packet from socket, and validate that the payload is correct
+ receiveAndValidatePacket(socket);
+
+ socket.close();
+
+ return 0;
+ }
+ };
+ }
+ }
+
+ private class InputPacketGeneratorIpSecTunnelTestRunnableFactory
+ implements IpSecTunnelTestRunnableFactory {
+ public IpSecTunnelTestRunnable getIpSecTunnelTestRunnable(
+ boolean transportInTunnelMode,
+ int spi,
+ InetAddress localInner,
+ InetAddress remoteInner,
+ InetAddress localOuter,
+ InetAddress remoteOuter,
+ IpSecTransform inTransportTransform,
+ IpSecTransform outTransportTransform,
+ int encapPort,
+ int innerSocketPort,
+ int expectedPacketSize)
+ throws Exception {
+ return new IpSecTunnelTestRunnable() {
+ @Override
+ public int run(Network ipsecNetwork) throws Exception {
// Build a socket and receive traffic
JavaUdpSocket socket = new JavaUdpSocket(localInner);
- // JavaUdpSocket socket = new JavaUdpSocket(localInner, socketPort.get());
ipsecNetwork.bindSocket(socket.mSocket);
// For Transport-In-Tunnel mode, apply transform to socket
@@ -404,6 +461,8 @@
receiveAndValidatePacket(socket);
socket.close();
+
+ return 0;
}
};
}
@@ -417,7 +476,7 @@
outerFamily,
useEncap,
transportInTunnelMode,
- new OutputTestRunnableFactory());
+ new OutputIpSecTunnelTestRunnableFactory());
}
private void checkTunnelInput(
@@ -428,7 +487,91 @@
outerFamily,
useEncap,
transportInTunnelMode,
- new InputPacketGeneratorTestRunnableFactory());
+ new InputPacketGeneratorIpSecTunnelTestRunnableFactory());
+ }
+
+ /**
+ * Validates that the kernel can talk to itself.
+ *
+ * <p>This test takes an outbound IPsec packet, reflects it (by flipping IP src/dst), and
+ * injects it back into the TUN. This test then verifies that a packet with the correct payload
+ * is found on the specified socket/port.
+ */
+ public void checkTunnelReflected(
+ int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
+ throws Exception {
+ if (!hasTunnelsFeature()) return;
+
+ InetAddress localInner = innerFamily == AF_INET ? LOCAL_INNER_4 : LOCAL_INNER_6;
+ InetAddress remoteInner = innerFamily == AF_INET ? REMOTE_INNER_4 : REMOTE_INNER_6;
+
+ InetAddress localOuter = outerFamily == AF_INET ? LOCAL_OUTER_4 : LOCAL_OUTER_6;
+ InetAddress remoteOuter = outerFamily == AF_INET ? REMOTE_OUTER_4 : REMOTE_OUTER_6;
+
+ // Preselect both SPI and encap port, to be used for both inbound and outbound tunnels.
+ int spi = getRandomSpi(localOuter, remoteOuter);
+ int expectedPacketSize =
+ getPacketSize(innerFamily, outerFamily, useEncap, transportInTunnelMode);
+
+ try (IpSecManager.SecurityParameterIndex inTransportSpi =
+ mISM.allocateSecurityParameterIndex(localInner, spi);
+ IpSecManager.SecurityParameterIndex outTransportSpi =
+ mISM.allocateSecurityParameterIndex(remoteInner, spi);
+ IpSecTransform inTransportTransform =
+ buildIpSecTransform(sContext, inTransportSpi, null, remoteInner);
+ IpSecTransform outTransportTransform =
+ buildIpSecTransform(sContext, outTransportSpi, null, localInner);
+ UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
+
+ // Run output direction tests
+ IpSecTunnelTestRunnable outputIpSecTunnelTestRunnable =
+ new OutputIpSecTunnelTestRunnableFactory()
+ .getIpSecTunnelTestRunnable(
+ transportInTunnelMode,
+ spi,
+ localInner,
+ remoteInner,
+ localOuter,
+ remoteOuter,
+ inTransportTransform,
+ outTransportTransform,
+ useEncap ? encapSocket.getPort() : 0,
+ 0,
+ expectedPacketSize);
+ int innerSocketPort =
+ buildTunnelNetworkAndRunTests(
+ localInner,
+ remoteInner,
+ localOuter,
+ remoteOuter,
+ spi,
+ useEncap ? encapSocket : null,
+ outputIpSecTunnelTestRunnable);
+
+ // Input direction tests, with matching inner socket ports.
+ IpSecTunnelTestRunnable inputIpSecTunnelTestRunnable =
+ new InputReflectedIpSecTunnelTestRunnableFactory()
+ .getIpSecTunnelTestRunnable(
+ transportInTunnelMode,
+ spi,
+ remoteInner,
+ localInner,
+ localOuter,
+ remoteOuter,
+ inTransportTransform,
+ outTransportTransform,
+ useEncap ? encapSocket.getPort() : 0,
+ innerSocketPort,
+ expectedPacketSize);
+ buildTunnelNetworkAndRunTests(
+ remoteInner,
+ localInner,
+ localOuter,
+ remoteOuter,
+ spi,
+ useEncap ? encapSocket : null,
+ inputIpSecTunnelTestRunnable);
+ }
}
public void checkTunnel(
@@ -436,7 +579,7 @@
int outerFamily,
boolean useEncap,
boolean transportInTunnelMode,
- TestRunnableFactory factory)
+ IpSecTunnelTestRunnableFactory factory)
throws Exception {
if (!hasTunnelsFeature()) return;
@@ -463,14 +606,14 @@
buildIpSecTransform(sContext, outTransportSpi, null, localInner);
UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
- buildTunnelAndNetwork(
+ buildTunnelNetworkAndRunTests(
localInner,
remoteInner,
localOuter,
remoteOuter,
spi,
useEncap ? encapSocket : null,
- factory.getTestRunnable(
+ factory.getIpSecTunnelTestRunnable(
transportInTunnelMode,
spi,
localInner,
@@ -480,41 +623,42 @@
inTransportTransform,
outTransportTransform,
useEncap ? encapSocket.getPort() : 0,
+ 0,
expectedPacketSize));
}
}
- private void buildTunnelAndNetwork(
+ private int buildTunnelNetworkAndRunTests(
InetAddress localInner,
InetAddress remoteInner,
InetAddress localOuter,
InetAddress remoteOuter,
int spi,
UdpEncapsulationSocket encapSocket,
- TestRunnable test)
+ IpSecTunnelTestRunnable test)
throws Exception {
int innerPrefixLen = localInner instanceof Inet6Address ? IP6_PREFIX_LEN : IP4_PREFIX_LEN;
TestNetworkCallback testNetworkCb = null;
+ int innerSocketPort;
try (IpSecManager.SecurityParameterIndex inSpi =
mISM.allocateSecurityParameterIndex(localOuter, spi);
IpSecManager.SecurityParameterIndex outSpi =
mISM.allocateSecurityParameterIndex(remoteOuter, spi);
- IpSecManager.IpSecTunnelInterface tunnelIntf =
+ IpSecManager.IpSecTunnelInterface tunnelIface =
mISM.createIpSecTunnelInterface(localOuter, remoteOuter, sTunNetwork)) {
// Build the test network
- tunnelIntf.addAddress(localInner, innerPrefixLen);
- testNetworkCb = setupAndGetTestNetwork(tunnelIntf.getInterfaceName());
+ tunnelIface.addAddress(localInner, innerPrefixLen);
+ testNetworkCb = setupAndGetTestNetwork(tunnelIface.getInterfaceName());
Network testNetwork = testNetworkCb.getNetworkBlocking();
// Check interface was created
- NetworkInterface netIntf = NetworkInterface.getByName(tunnelIntf.getInterfaceName());
- assertNotNull(netIntf);
+ assertNotNull(NetworkInterface.getByName(tunnelIface.getInterfaceName()));
// Verify address was added
- netIntf = NetworkInterface.getByInetAddress(localInner);
- assertNotNull(netIntf);
- assertEquals(tunnelIntf.getInterfaceName(), netIntf.getDisplayName());
+ final NetworkInterface netIface = NetworkInterface.getByInetAddress(localInner);
+ assertNotNull(netIface);
+ assertEquals(tunnelIface.getInterfaceName(), netIface.getDisplayName());
// Configure Transform parameters
IpSecTransform.Builder transformBuilder = new IpSecTransform.Builder(sContext);
@@ -533,28 +677,31 @@
transformBuilder.buildTunnelModeTransform(remoteOuter, inSpi);
IpSecTransform outTransform =
transformBuilder.buildTunnelModeTransform(localOuter, outSpi)) {
- mISM.applyTunnelModeTransform(tunnelIntf, IpSecManager.DIRECTION_IN, inTransform);
- mISM.applyTunnelModeTransform(tunnelIntf, IpSecManager.DIRECTION_OUT, outTransform);
+ mISM.applyTunnelModeTransform(tunnelIface, IpSecManager.DIRECTION_IN, inTransform);
+ mISM.applyTunnelModeTransform(
+ tunnelIface, IpSecManager.DIRECTION_OUT, outTransform);
- test.run(testNetwork);
+ innerSocketPort = test.run(testNetwork);
}
// Teardown the test network
sTNM.teardownTestNetwork(testNetwork);
// Remove addresses and check that interface is still present, but fails lookup-by-addr
- tunnelIntf.removeAddress(localInner, innerPrefixLen);
- assertNotNull(NetworkInterface.getByName(tunnelIntf.getInterfaceName()));
+ tunnelIface.removeAddress(localInner, innerPrefixLen);
+ assertNotNull(NetworkInterface.getByName(tunnelIface.getInterfaceName()));
assertNull(NetworkInterface.getByInetAddress(localInner));
// Check interface was cleaned up
- tunnelIntf.close();
- assertNull(NetworkInterface.getByName(tunnelIntf.getInterfaceName()));
+ tunnelIface.close();
+ assertNull(NetworkInterface.getByName(tunnelIface.getInterfaceName()));
} finally {
if (testNetworkCb != null) {
sCM.unregisterNetworkCallback(testNetworkCb);
}
}
+
+ return innerSocketPort;
}
private static void receiveAndValidatePacket(JavaUdpSocket socket) throws Exception {
@@ -678,35 +825,65 @@
}
@Test
+ public void testTransportInTunnelModeV4InV4Reflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET, false, true);
+ }
+
+ @Test
public void testTransportInTunnelModeV4InV4UdpEncap() throws Exception {
checkTunnelOutput(AF_INET, AF_INET, true, true);
checkTunnelInput(AF_INET, AF_INET, true, true);
}
@Test
+ public void testTransportInTunnelModeV4InV4UdpEncapReflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET, false, true);
+ }
+
+ @Test
public void testTransportInTunnelModeV4InV6() throws Exception {
checkTunnelOutput(AF_INET, AF_INET6, false, true);
checkTunnelInput(AF_INET, AF_INET6, false, true);
}
@Test
+ public void testTransportInTunnelModeV4InV6Reflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET, false, true);
+ }
+
+ @Test
public void testTransportInTunnelModeV6InV4() throws Exception {
checkTunnelOutput(AF_INET6, AF_INET, false, true);
checkTunnelInput(AF_INET6, AF_INET, false, true);
}
@Test
+ public void testTransportInTunnelModeV6InV4Reflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET, false, true);
+ }
+
+ @Test
public void testTransportInTunnelModeV6InV4UdpEncap() throws Exception {
checkTunnelOutput(AF_INET6, AF_INET, true, true);
checkTunnelInput(AF_INET6, AF_INET, true, true);
}
@Test
+ public void testTransportInTunnelModeV6InV4UdpEncapReflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET, false, true);
+ }
+
+ @Test
public void testTransportInTunnelModeV6InV6() throws Exception {
checkTunnelOutput(AF_INET, AF_INET6, false, true);
checkTunnelInput(AF_INET, AF_INET6, false, true);
}
+ @Test
+ public void testTransportInTunnelModeV6InV6Reflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET, false, true);
+ }
+
// Tunnel mode tests
@Test
public void testTunnelV4InV4() throws Exception {
@@ -715,32 +892,62 @@
}
@Test
+ public void testTunnelV4InV4Reflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET, false, false);
+ }
+
+ @Test
public void testTunnelV4InV4UdpEncap() throws Exception {
checkTunnelOutput(AF_INET, AF_INET, true, false);
checkTunnelInput(AF_INET, AF_INET, true, false);
}
@Test
+ public void testTunnelV4InV4UdpEncapReflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET, true, false);
+ }
+
+ @Test
public void testTunnelV4InV6() throws Exception {
checkTunnelOutput(AF_INET, AF_INET6, false, false);
checkTunnelInput(AF_INET, AF_INET6, false, false);
}
@Test
+ public void testTunnelV4InV6Reflected() throws Exception {
+ checkTunnelReflected(AF_INET, AF_INET6, false, false);
+ }
+
+ @Test
public void testTunnelV6InV4() throws Exception {
checkTunnelOutput(AF_INET6, AF_INET, false, false);
checkTunnelInput(AF_INET6, AF_INET, false, false);
}
@Test
+ public void testTunnelV6InV4Reflected() throws Exception {
+ checkTunnelReflected(AF_INET6, AF_INET, false, false);
+ }
+
+ @Test
public void testTunnelV6InV4UdpEncap() throws Exception {
checkTunnelOutput(AF_INET6, AF_INET, true, false);
checkTunnelInput(AF_INET6, AF_INET, true, false);
}
@Test
+ public void testTunnelV6InV4UdpEncapReflected() throws Exception {
+ checkTunnelReflected(AF_INET6, AF_INET, true, false);
+ }
+
+ @Test
public void testTunnelV6InV6() throws Exception {
checkTunnelOutput(AF_INET6, AF_INET6, false, false);
checkTunnelInput(AF_INET6, AF_INET6, false, false);
}
+
+ @Test
+ public void testTunnelV6InV6Reflected() throws Exception {
+ checkTunnelReflected(AF_INET6, AF_INET6, false, false);
+ }
}