Loading services/core/java/com/android/server/IpSecService.java +35 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ package com.android.server; import static android.Manifest.permission.DUMP; import static android.net.IpSecManager.INVALID_RESOURCE_ID; import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.AF_INET6; import static android.system.OsConstants.AF_UNSPEC; import static android.system.OsConstants.EINVAL; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; Loading Loading @@ -63,6 +65,8 @@ import com.android.internal.util.Preconditions; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; Loading Loading @@ -1426,6 +1430,17 @@ public class IpSecService extends IIpSecService.Stub { + "or Encryption algorithms"); } private int getFamily(String inetAddress) { int family = AF_UNSPEC; InetAddress checkAddress = NetworkUtils.numericToInetAddress(inetAddress); if (checkAddress instanceof Inet4Address) { family = AF_INET; } else if (checkAddress instanceof Inet6Address) { family = AF_INET6; } return family; } /** * Checks an IpSecConfig parcel to ensure that the contents are sane and throws an * IllegalArgumentException if they are not. Loading Loading @@ -1479,6 +1494,26 @@ public class IpSecService extends IIpSecService.Stub { // Require a valid source address for all transforms. checkInetAddress(config.getSourceAddress()); // Check to ensure source and destination have the same address family. String sourceAddress = config.getSourceAddress(); String destinationAddress = config.getDestinationAddress(); int sourceFamily = getFamily(sourceAddress); int destinationFamily = getFamily(destinationAddress); if (sourceFamily != destinationFamily) { throw new IllegalArgumentException( "Source address (" + sourceAddress + ") and destination address (" + destinationAddress + ") have different address families."); } // Throw an error if UDP Encapsulation is not used in IPv4. if (config.getEncapType() != IpSecTransform.ENCAP_NONE && sourceFamily != AF_INET) { throw new IllegalArgumentException( "UDP Encapsulation is not supported for this address family"); } switch (config.getMode()) { case IpSecTransform.MODE_TRANSPORT: break; Loading tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +108 −48 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server; import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.AF_INET6; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; Loading @@ -34,8 +36,10 @@ import android.net.IpSecAlgorithm; import android.net.IpSecConfig; import android.net.IpSecManager; import android.net.IpSecSpiResponse; import android.net.IpSecTransform; import android.net.IpSecTransformResponse; import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecUdpEncapResponse; import android.net.LinkAddress; import android.net.Network; import android.net.NetworkUtils; Loading @@ -62,16 +66,17 @@ public class IpSecServiceParameterizedTest { private static final int TEST_SPI = 0xD1201D; private final String mDestinationAddr; private final String mSourceAddr; private final String mDestinationAddr; private final LinkAddress mLocalInnerAddress; private final int mFamily; @Parameterized.Parameters public static Collection ipSecConfigs() { return Arrays.asList( new Object[][] { {"1.2.3.4", "8.8.4.4", "10.0.1.1/24"}, {"2601::2", "2601::10", "2001:db8::1/64"} {"1.2.3.4", "8.8.4.4", "10.0.1.1/24", AF_INET}, {"2601::2", "2601::10", "2001:db8::1/64", AF_INET6} }); } Loading Loading @@ -129,12 +134,14 @@ public class IpSecServiceParameterizedTest { new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); private static final IpSecAlgorithm AEAD_ALGO = new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128); private static final int REMOTE_ENCAP_PORT = 4500; public IpSecServiceParameterizedTest( String sourceAddr, String destAddr, String localInnerAddr) { String sourceAddr, String destAddr, String localInnerAddr, int family) { mSourceAddr = sourceAddr; mDestinationAddr = destAddr; mLocalInnerAddress = new LinkAddress(localInnerAddr); mFamily = family; } @Before Loading @@ -157,6 +164,8 @@ public class IpSecServiceParameterizedTest { .thenReturn(AppOpsManager.MODE_IGNORED); } //TODO: Add a test to verify SPI. @Test public void testIpSecServiceReserveSpi() throws Exception { when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI))) Loading Loading @@ -257,6 +266,47 @@ public class IpSecServiceParameterizedTest { config.setAuthentication(AUTH_ALGO); } private void addEncapSocketToIpSecConfig(int resourceId, IpSecConfig config) throws Exception { config.setEncapType(IpSecTransform.ENCAP_ESPINUDP); config.setEncapSocketResourceId(resourceId); config.setEncapRemotePort(REMOTE_ENCAP_PORT); } private void verifyTransformNetdCalledForCreatingSA( IpSecConfig config, IpSecTransformResponse resp) throws Exception { verifyTransformNetdCalledForCreatingSA(config, resp, 0); } private void verifyTransformNetdCalledForCreatingSA( IpSecConfig config, IpSecTransformResponse resp, int encapSocketPort) throws Exception { IpSecAlgorithm auth = config.getAuthentication(); IpSecAlgorithm crypt = config.getEncryption(); IpSecAlgorithm authCrypt = config.getAuthenticatedEncryption(); verify(mMockNetd, times(1)) .ipSecAddSecurityAssociation( eq(mUid), eq(config.getMode()), eq(config.getSourceAddress()), eq(config.getDestinationAddress()), eq((config.getNetwork() != null) ? config.getNetwork().netId : 0), eq(TEST_SPI), eq(0), eq(0), eq((auth != null) ? auth.getName() : ""), eq((auth != null) ? auth.getKey() : new byte[] {}), eq((auth != null) ? auth.getTruncationLengthBits() : 0), eq((crypt != null) ? crypt.getName() : ""), eq((crypt != null) ? crypt.getKey() : new byte[] {}), eq((crypt != null) ? crypt.getTruncationLengthBits() : 0), eq((authCrypt != null) ? authCrypt.getName() : ""), eq((authCrypt != null) ? authCrypt.getKey() : new byte[] {}), eq((authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0), eq(config.getEncapType()), eq(encapSocketPort), eq(config.getEncapRemotePort())); } @Test public void testCreateTransform() throws Exception { IpSecConfig ipSecConfig = new IpSecConfig(); Loading @@ -267,28 +317,7 @@ public class IpSecServiceParameterizedTest { mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); assertEquals(IpSecManager.Status.OK, createTransformResp.status); verify(mMockNetd) .ipSecAddSecurityAssociation( eq(mUid), anyInt(), anyString(), anyString(), anyInt(), eq(TEST_SPI), anyInt(), anyInt(), eq(IpSecAlgorithm.AUTH_HMAC_SHA256), eq(AUTH_KEY), anyInt(), eq(IpSecAlgorithm.CRYPT_AES_CBC), eq(CRYPT_KEY), anyInt(), eq(""), eq(new byte[] {}), eq(0), anyInt(), anyInt(), anyInt()); verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); } @Test Loading @@ -302,28 +331,59 @@ public class IpSecServiceParameterizedTest { mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); assertEquals(IpSecManager.Status.OK, createTransformResp.status); verify(mMockNetd) .ipSecAddSecurityAssociation( eq(mUid), anyInt(), anyString(), anyString(), anyInt(), eq(TEST_SPI), anyInt(), anyInt(), eq(""), eq(new byte[] {}), eq(0), eq(""), eq(new byte[] {}), eq(0), eq(IpSecAlgorithm.AUTH_CRYPT_AES_GCM), eq(AEAD_KEY), anyInt(), anyInt(), anyInt(), anyInt()); verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); } @Test public void testCreateTransportModeTransformWithEncap() throws Exception { IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder()); IpSecConfig ipSecConfig = new IpSecConfig(); ipSecConfig.setMode(IpSecTransform.MODE_TRANSPORT); addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); addAuthAndCryptToIpSecConfig(ipSecConfig); addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig); if (mFamily == AF_INET) { IpSecTransformResponse createTransformResp = mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); assertEquals(IpSecManager.Status.OK, createTransformResp.status); verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port); } else { try { IpSecTransformResponse createTransformResp = mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6"); } catch (IllegalArgumentException expected) { } } } @Test public void testCreateTunnelModeTransformWithEncap() throws Exception { IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder()); IpSecConfig ipSecConfig = new IpSecConfig(); ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL); addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); addAuthAndCryptToIpSecConfig(ipSecConfig); addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig); if (mFamily == AF_INET) { IpSecTransformResponse createTransformResp = mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); assertEquals(IpSecManager.Status.OK, createTransformResp.status); verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port); } else { try { IpSecTransformResponse createTransformResp = mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6"); } catch (IllegalArgumentException expected) { } } } @Test Loading Loading
services/core/java/com/android/server/IpSecService.java +35 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ package com.android.server; import static android.Manifest.permission.DUMP; import static android.net.IpSecManager.INVALID_RESOURCE_ID; import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.AF_INET6; import static android.system.OsConstants.AF_UNSPEC; import static android.system.OsConstants.EINVAL; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; Loading Loading @@ -63,6 +65,8 @@ import com.android.internal.util.Preconditions; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; Loading Loading @@ -1426,6 +1430,17 @@ public class IpSecService extends IIpSecService.Stub { + "or Encryption algorithms"); } private int getFamily(String inetAddress) { int family = AF_UNSPEC; InetAddress checkAddress = NetworkUtils.numericToInetAddress(inetAddress); if (checkAddress instanceof Inet4Address) { family = AF_INET; } else if (checkAddress instanceof Inet6Address) { family = AF_INET6; } return family; } /** * Checks an IpSecConfig parcel to ensure that the contents are sane and throws an * IllegalArgumentException if they are not. Loading Loading @@ -1479,6 +1494,26 @@ public class IpSecService extends IIpSecService.Stub { // Require a valid source address for all transforms. checkInetAddress(config.getSourceAddress()); // Check to ensure source and destination have the same address family. String sourceAddress = config.getSourceAddress(); String destinationAddress = config.getDestinationAddress(); int sourceFamily = getFamily(sourceAddress); int destinationFamily = getFamily(destinationAddress); if (sourceFamily != destinationFamily) { throw new IllegalArgumentException( "Source address (" + sourceAddress + ") and destination address (" + destinationAddress + ") have different address families."); } // Throw an error if UDP Encapsulation is not used in IPv4. if (config.getEncapType() != IpSecTransform.ENCAP_NONE && sourceFamily != AF_INET) { throw new IllegalArgumentException( "UDP Encapsulation is not supported for this address family"); } switch (config.getMode()) { case IpSecTransform.MODE_TRANSPORT: break; Loading
tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +108 −48 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server; import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.AF_INET6; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; Loading @@ -34,8 +36,10 @@ import android.net.IpSecAlgorithm; import android.net.IpSecConfig; import android.net.IpSecManager; import android.net.IpSecSpiResponse; import android.net.IpSecTransform; import android.net.IpSecTransformResponse; import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecUdpEncapResponse; import android.net.LinkAddress; import android.net.Network; import android.net.NetworkUtils; Loading @@ -62,16 +66,17 @@ public class IpSecServiceParameterizedTest { private static final int TEST_SPI = 0xD1201D; private final String mDestinationAddr; private final String mSourceAddr; private final String mDestinationAddr; private final LinkAddress mLocalInnerAddress; private final int mFamily; @Parameterized.Parameters public static Collection ipSecConfigs() { return Arrays.asList( new Object[][] { {"1.2.3.4", "8.8.4.4", "10.0.1.1/24"}, {"2601::2", "2601::10", "2001:db8::1/64"} {"1.2.3.4", "8.8.4.4", "10.0.1.1/24", AF_INET}, {"2601::2", "2601::10", "2001:db8::1/64", AF_INET6} }); } Loading Loading @@ -129,12 +134,14 @@ public class IpSecServiceParameterizedTest { new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); private static final IpSecAlgorithm AEAD_ALGO = new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128); private static final int REMOTE_ENCAP_PORT = 4500; public IpSecServiceParameterizedTest( String sourceAddr, String destAddr, String localInnerAddr) { String sourceAddr, String destAddr, String localInnerAddr, int family) { mSourceAddr = sourceAddr; mDestinationAddr = destAddr; mLocalInnerAddress = new LinkAddress(localInnerAddr); mFamily = family; } @Before Loading @@ -157,6 +164,8 @@ public class IpSecServiceParameterizedTest { .thenReturn(AppOpsManager.MODE_IGNORED); } //TODO: Add a test to verify SPI. @Test public void testIpSecServiceReserveSpi() throws Exception { when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI))) Loading Loading @@ -257,6 +266,47 @@ public class IpSecServiceParameterizedTest { config.setAuthentication(AUTH_ALGO); } private void addEncapSocketToIpSecConfig(int resourceId, IpSecConfig config) throws Exception { config.setEncapType(IpSecTransform.ENCAP_ESPINUDP); config.setEncapSocketResourceId(resourceId); config.setEncapRemotePort(REMOTE_ENCAP_PORT); } private void verifyTransformNetdCalledForCreatingSA( IpSecConfig config, IpSecTransformResponse resp) throws Exception { verifyTransformNetdCalledForCreatingSA(config, resp, 0); } private void verifyTransformNetdCalledForCreatingSA( IpSecConfig config, IpSecTransformResponse resp, int encapSocketPort) throws Exception { IpSecAlgorithm auth = config.getAuthentication(); IpSecAlgorithm crypt = config.getEncryption(); IpSecAlgorithm authCrypt = config.getAuthenticatedEncryption(); verify(mMockNetd, times(1)) .ipSecAddSecurityAssociation( eq(mUid), eq(config.getMode()), eq(config.getSourceAddress()), eq(config.getDestinationAddress()), eq((config.getNetwork() != null) ? config.getNetwork().netId : 0), eq(TEST_SPI), eq(0), eq(0), eq((auth != null) ? auth.getName() : ""), eq((auth != null) ? auth.getKey() : new byte[] {}), eq((auth != null) ? auth.getTruncationLengthBits() : 0), eq((crypt != null) ? crypt.getName() : ""), eq((crypt != null) ? crypt.getKey() : new byte[] {}), eq((crypt != null) ? crypt.getTruncationLengthBits() : 0), eq((authCrypt != null) ? authCrypt.getName() : ""), eq((authCrypt != null) ? authCrypt.getKey() : new byte[] {}), eq((authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0), eq(config.getEncapType()), eq(encapSocketPort), eq(config.getEncapRemotePort())); } @Test public void testCreateTransform() throws Exception { IpSecConfig ipSecConfig = new IpSecConfig(); Loading @@ -267,28 +317,7 @@ public class IpSecServiceParameterizedTest { mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); assertEquals(IpSecManager.Status.OK, createTransformResp.status); verify(mMockNetd) .ipSecAddSecurityAssociation( eq(mUid), anyInt(), anyString(), anyString(), anyInt(), eq(TEST_SPI), anyInt(), anyInt(), eq(IpSecAlgorithm.AUTH_HMAC_SHA256), eq(AUTH_KEY), anyInt(), eq(IpSecAlgorithm.CRYPT_AES_CBC), eq(CRYPT_KEY), anyInt(), eq(""), eq(new byte[] {}), eq(0), anyInt(), anyInt(), anyInt()); verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); } @Test Loading @@ -302,28 +331,59 @@ public class IpSecServiceParameterizedTest { mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); assertEquals(IpSecManager.Status.OK, createTransformResp.status); verify(mMockNetd) .ipSecAddSecurityAssociation( eq(mUid), anyInt(), anyString(), anyString(), anyInt(), eq(TEST_SPI), anyInt(), anyInt(), eq(""), eq(new byte[] {}), eq(0), eq(""), eq(new byte[] {}), eq(0), eq(IpSecAlgorithm.AUTH_CRYPT_AES_GCM), eq(AEAD_KEY), anyInt(), anyInt(), anyInt(), anyInt()); verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); } @Test public void testCreateTransportModeTransformWithEncap() throws Exception { IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder()); IpSecConfig ipSecConfig = new IpSecConfig(); ipSecConfig.setMode(IpSecTransform.MODE_TRANSPORT); addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); addAuthAndCryptToIpSecConfig(ipSecConfig); addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig); if (mFamily == AF_INET) { IpSecTransformResponse createTransformResp = mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); assertEquals(IpSecManager.Status.OK, createTransformResp.status); verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port); } else { try { IpSecTransformResponse createTransformResp = mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6"); } catch (IllegalArgumentException expected) { } } } @Test public void testCreateTunnelModeTransformWithEncap() throws Exception { IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder()); IpSecConfig ipSecConfig = new IpSecConfig(); ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL); addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); addAuthAndCryptToIpSecConfig(ipSecConfig); addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig); if (mFamily == AF_INET) { IpSecTransformResponse createTransformResp = mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); assertEquals(IpSecManager.Status.OK, createTransformResp.status); verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port); } else { try { IpSecTransformResponse createTransformResp = mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6"); } catch (IllegalArgumentException expected) { } } } @Test Loading