blob: 5f79a3e22c3935d8a57ccb44573fd8adf80a4abb [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.net.cts;
import static android.net.IpSecAlgorithm.AUTH_AES_CMAC;
import static android.net.IpSecAlgorithm.AUTH_AES_XCBC;
import static android.net.IpSecAlgorithm.AUTH_CRYPT_AES_GCM;
import static android.net.IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305;
import static android.net.IpSecAlgorithm.AUTH_HMAC_MD5;
import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA1;
import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA256;
import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA384;
import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512;
import static android.net.IpSecAlgorithm.CRYPT_AES_CBC;
import static android.net.IpSecAlgorithm.CRYPT_AES_CTR;
import static android.net.cts.PacketUtils.AES_CBC_BLK_SIZE;
import static android.net.cts.PacketUtils.AES_CBC_IV_LEN;
import static android.net.cts.PacketUtils.AES_CMAC_ICV_LEN;
import static android.net.cts.PacketUtils.AES_CMAC_KEY_LEN;
import static android.net.cts.PacketUtils.AES_CTR_BLK_SIZE;
import static android.net.cts.PacketUtils.AES_CTR_IV_LEN;
import static android.net.cts.PacketUtils.AES_CTR_KEY_LEN_20;
import static android.net.cts.PacketUtils.AES_GCM_BLK_SIZE;
import static android.net.cts.PacketUtils.AES_GCM_IV_LEN;
import static android.net.cts.PacketUtils.AES_XCBC_ICV_LEN;
import static android.net.cts.PacketUtils.AES_XCBC_KEY_LEN;
import static android.net.cts.PacketUtils.CHACHA20_POLY1305_BLK_SIZE;
import static android.net.cts.PacketUtils.CHACHA20_POLY1305_ICV_LEN;
import static android.net.cts.PacketUtils.CHACHA20_POLY1305_IV_LEN;
import static android.net.cts.PacketUtils.HMAC_SHA512_ICV_LEN;
import static android.net.cts.PacketUtils.HMAC_SHA512_KEY_LEN;
import static android.net.cts.PacketUtils.IP4_HDRLEN;
import static android.net.cts.PacketUtils.IP6_HDRLEN;
import static android.net.cts.PacketUtils.TCP_HDRLEN_WITH_TIMESTAMP_OPT;
import static android.net.cts.PacketUtils.UDP_HDRLEN;
import static android.system.OsConstants.IPPROTO_TCP;
import static android.system.OsConstants.IPPROTO_UDP;
import static com.android.compatibility.common.util.PropertyUtil.getFirstApiLevel;
import static com.android.compatibility.common.util.PropertyUtil.getVendorApiLevel;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import android.net.IpSecAlgorithm;
import android.net.IpSecManager;
import android.net.IpSecTransform;
import android.net.TrafficStats;
import android.os.Build;
import android.platform.test.annotations.AppModeFull;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.SkipPresubmit;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.FileDescriptor;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@RunWith(AndroidJUnit4.class)
@AppModeFull(reason = "Socket cannot bind in instant app mode")
public class IpSecManagerTest extends IpSecBaseTest {
@Rule public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
private static final String TAG = IpSecManagerTest.class.getSimpleName();
private static final InetAddress GOOGLE_DNS_4 = InetAddress.parseNumericAddress("8.8.8.8");
private static final InetAddress GOOGLE_DNS_6 =
InetAddress.parseNumericAddress("2001:4860:4860::8888");
private static final InetAddress[] GOOGLE_DNS_LIST =
new InetAddress[] {GOOGLE_DNS_4, GOOGLE_DNS_6};
private static final int DROID_SPI = 0xD1201D;
private static final int MAX_PORT_BIND_ATTEMPTS = 10;
private static final byte[] AEAD_KEY = getKey(288);
/*
* Allocate a random SPI
* Allocate a specific SPI using previous randomly created SPI value
* Realloc the same SPI that was specifically created (expect SpiUnavailable)
* Close SPIs
*/
@Test
public void testAllocSpi() throws Exception {
for (InetAddress addr : GOOGLE_DNS_LIST) {
IpSecManager.SecurityParameterIndex randomSpi = null, droidSpi = null;
randomSpi = mISM.allocateSecurityParameterIndex(addr);
assertTrue(
"Failed to receive a valid SPI",
randomSpi.getSpi() != IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
droidSpi = mISM.allocateSecurityParameterIndex(addr, DROID_SPI);
assertTrue("Failed to allocate specified SPI, " + DROID_SPI,
droidSpi.getSpi() == DROID_SPI);
try {
mISM.allocateSecurityParameterIndex(addr, DROID_SPI);
fail("Duplicate SPI was allowed to be created");
} catch (IpSecManager.SpiUnavailableException expected) {
// This is a success case because we expect a dupe SPI to throw
}
randomSpi.close();
droidSpi.close();
}
}
/** This function finds an available port */
private static int findUnusedPort() throws Exception {
// Get an available port.
DatagramSocket s = new DatagramSocket();
int port = s.getLocalPort();
s.close();
return port;
}
private static FileDescriptor getBoundUdpSocket(InetAddress address) throws Exception {
FileDescriptor sock =
Os.socket(getDomain(address), OsConstants.SOCK_DGRAM, OsConstants.IPPROTO_UDP);
for (int i = 0; i < MAX_PORT_BIND_ATTEMPTS; i++) {
try {
int port = findUnusedPort();
Os.bind(sock, address, port);
break;
} catch (ErrnoException e) {
// Someone claimed the port since we called findUnusedPort.
if (e.errno == OsConstants.EADDRINUSE) {
if (i == MAX_PORT_BIND_ATTEMPTS - 1) {
fail("Failed " + MAX_PORT_BIND_ATTEMPTS + " attempts to bind to a port");
}
continue;
}
throw e.rethrowAsIOException();
}
}
return sock;
}
private void checkUnconnectedUdp(IpSecTransform transform, InetAddress local, int sendCount,
boolean useJavaSockets) throws Exception {
GenericUdpSocket sockLeft = null, sockRight = null;
if (useJavaSockets) {
SocketPair<JavaUdpSocket> sockets = getJavaUdpSocketPair(local, mISM, transform, false);
sockLeft = sockets.mLeftSock;
sockRight = sockets.mRightSock;
} else {
SocketPair<NativeUdpSocket> sockets =
getNativeUdpSocketPair(local, mISM, transform, false);
sockLeft = sockets.mLeftSock;
sockRight = sockets.mRightSock;
}
for (int i = 0; i < sendCount; i++) {
byte[] in;
sockLeft.sendTo(TEST_DATA, local, sockRight.getPort());
in = sockRight.receive();
assertArrayEquals("Left-to-right encrypted data did not match.", TEST_DATA, in);
sockRight.sendTo(TEST_DATA, local, sockLeft.getPort());
in = sockLeft.receive();
assertArrayEquals("Right-to-left encrypted data did not match.", TEST_DATA, in);
}
sockLeft.close();
sockRight.close();
}
private void checkTcp(IpSecTransform transform, InetAddress local, int sendCount,
boolean useJavaSockets) throws Exception {
GenericTcpSocket client = null, accepted = null;
if (useJavaSockets) {
SocketPair<JavaTcpSocket> sockets = getJavaTcpSocketPair(local, mISM, transform);
client = sockets.mLeftSock;
accepted = sockets.mRightSock;
} else {
SocketPair<NativeTcpSocket> sockets = getNativeTcpSocketPair(local, mISM, transform);
client = sockets.mLeftSock;
accepted = sockets.mRightSock;
}
// Wait for TCP handshake packets to be counted
StatsChecker.waitForNumPackets(3); // (SYN, SYN+ACK, ACK)
// Reset StatsChecker, to ignore negotiation overhead.
StatsChecker.initStatsChecker();
for (int i = 0; i < sendCount; i++) {
byte[] in;
client.send(TEST_DATA);
in = accepted.receive();
assertArrayEquals("Client-to-server encrypted data did not match.", TEST_DATA, in);
// Allow for newest data + ack packets to be returned before sending next packet
// Also add the number of expected packets in each of the previous runs (4 per run)
StatsChecker.waitForNumPackets(2 + (4 * i));
accepted.send(TEST_DATA);
in = client.receive();
assertArrayEquals("Server-to-client encrypted data did not match.", TEST_DATA, in);
// Allow for all data + ack packets to be returned before sending next packet
// Also add the number of expected packets in each of the previous runs (4 per run)
StatsChecker.waitForNumPackets(4 * (i + 1));
}
// Transforms should not be removed from the sockets, otherwise FIN packets will be sent
// unencrypted.
// This test also unfortunately happens to rely on a nuance of the cleanup order. By
// keeping the policy on the socket, but removing the SA before lingering FIN packets
// are sent (at an undetermined later time), the FIN packets are dropped. Without this,
// we run into all kinds of headaches trying to test data accounting (unsolicited
// packets mysteriously appearing and messing up our counters)
// The right way to close sockets is to set SO_LINGER to ensure synchronous closure,
// closing the sockets, and then closing the transforms. See documentation for the
// Socket or FileDescriptor flavors of applyTransportModeTransform() in IpSecManager
// for more details.
client.close();
accepted.close();
}
/*
* Alloc outbound SPI
* Alloc inbound SPI
* Create transport mode transform
* open socket
* apply transform to socket
* send data on socket
* release transform
* send data (expect exception)
*/
@Test
public void testCreateTransform() throws Exception {
InetAddress localAddr = InetAddress.getByName(IPV4_LOOPBACK);
IpSecManager.SecurityParameterIndex spi =
mISM.allocateSecurityParameterIndex(localAddr);
IpSecTransform transform =
new IpSecTransform.Builder(InstrumentationRegistry.getContext())
.setEncryption(new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
.setAuthentication(
new IpSecAlgorithm(
IpSecAlgorithm.AUTH_HMAC_SHA256,
AUTH_KEY,
AUTH_KEY.length * 8))
.buildTransportModeTransform(localAddr, spi);
final boolean [][] applyInApplyOut = {
{false, false}, {false, true}, {true, false}, {true,true}};
final byte[] data = new String("Best test data ever!").getBytes("UTF-8");
final DatagramPacket outPacket = new DatagramPacket(data, 0, data.length, localAddr, 0);
byte[] in = new byte[data.length];
DatagramPacket inPacket = new DatagramPacket(in, in.length);
DatagramSocket localSocket;
int localPort;
for(boolean[] io : applyInApplyOut) {
boolean applyIn = io[0];
boolean applyOut = io[1];
// Bind localSocket to a random available port.
localSocket = new DatagramSocket(0);
localPort = localSocket.getLocalPort();
localSocket.setSoTimeout(200);
outPacket.setPort(localPort);
if (applyIn) {
mISM.applyTransportModeTransform(
localSocket, IpSecManager.DIRECTION_IN, transform);
}
if (applyOut) {
mISM.applyTransportModeTransform(
localSocket, IpSecManager.DIRECTION_OUT, transform);
}
if (applyIn == applyOut) {
localSocket.send(outPacket);
localSocket.receive(inPacket);
assertTrue("Encapsulated data did not match.",
Arrays.equals(outPacket.getData(), inPacket.getData()));
mISM.removeTransportModeTransforms(localSocket);
localSocket.close();
} else {
try {
localSocket.send(outPacket);
localSocket.receive(inPacket);
} catch (IOException e) {
continue;
} finally {
mISM.removeTransportModeTransforms(localSocket);
localSocket.close();
}
// FIXME: This check is disabled because sockets currently receive data
// if there is a valid SA for decryption, even when the input policy is
// not applied to a socket.
// fail("Data IO should fail on asymmetrical transforms! + Input="
// + applyIn + " Output=" + applyOut);
}
}
transform.close();
}
/** Snapshot of TrafficStats as of initStatsChecker call for later comparisons */
private static class StatsChecker {
private static final double ERROR_MARGIN_BYTES = 1.05;
private static final double ERROR_MARGIN_PKTS = 1.05;
private static final int MAX_WAIT_TIME_MILLIS = 1000;
private static long uidTxBytes;
private static long uidRxBytes;
private static long uidTxPackets;
private static long uidRxPackets;
private static long ifaceTxBytes;
private static long ifaceRxBytes;
private static long ifaceTxPackets;
private static long ifaceRxPackets;
/**
* This method counts the number of incoming packets, polling intermittently up to
* MAX_WAIT_TIME_MILLIS.
*/
private static void waitForNumPackets(int numPackets) throws Exception {
long uidTxDelta = 0;
long uidRxDelta = 0;
for (int i = 0; i < 100; i++) {
uidTxDelta = TrafficStats.getUidTxPackets(Os.getuid()) - uidTxPackets;
uidRxDelta = TrafficStats.getUidRxPackets(Os.getuid()) - uidRxPackets;
// TODO: Check Rx packets as well once kernel security policy bug is fixed.
// (b/70635417)
if (uidTxDelta >= numPackets) {
return;
}
Thread.sleep(MAX_WAIT_TIME_MILLIS / 100);
}
fail(
"Not enough traffic was recorded to satisfy the provided conditions: wanted "
+ numPackets
+ ", got "
+ uidTxDelta
+ " tx and "
+ uidRxDelta
+ " rx packets");
}
private static void assertUidStatsDelta(
int expectedTxByteDelta,
int expectedTxPacketDelta,
int minRxByteDelta,
int maxRxByteDelta,
int expectedRxPacketDelta) {
long newUidTxBytes = TrafficStats.getUidTxBytes(Os.getuid());
long newUidRxBytes = TrafficStats.getUidRxBytes(Os.getuid());
long newUidTxPackets = TrafficStats.getUidTxPackets(Os.getuid());
long newUidRxPackets = TrafficStats.getUidRxPackets(Os.getuid());
assertEquals(expectedTxByteDelta, newUidTxBytes - uidTxBytes);
assertTrue(
newUidRxBytes - uidRxBytes >= minRxByteDelta
&& newUidRxBytes - uidRxBytes <= maxRxByteDelta);
assertEquals(expectedTxPacketDelta, newUidTxPackets - uidTxPackets);
assertEquals(expectedRxPacketDelta, newUidRxPackets - uidRxPackets);
}
private static void assertIfaceStatsDelta(
int expectedTxByteDelta,
int expectedTxPacketDelta,
int expectedRxByteDelta,
int expectedRxPacketDelta)
throws IOException {
long newIfaceTxBytes = TrafficStats.getLoopbackTxBytes();
long newIfaceRxBytes = TrafficStats.getLoopbackRxBytes();
long newIfaceTxPackets = TrafficStats.getLoopbackTxPackets();
long newIfaceRxPackets = TrafficStats.getLoopbackRxPackets();
// Check that iface stats are within an acceptable range; data might be sent
// on the local interface by other apps.
assertApproxEquals(
ifaceTxBytes, newIfaceTxBytes, expectedTxByteDelta, ERROR_MARGIN_BYTES);
assertApproxEquals(
ifaceRxBytes, newIfaceRxBytes, expectedRxByteDelta, ERROR_MARGIN_BYTES);
assertApproxEquals(
ifaceTxPackets, newIfaceTxPackets, expectedTxPacketDelta, ERROR_MARGIN_PKTS);
assertApproxEquals(
ifaceRxPackets, newIfaceRxPackets, expectedRxPacketDelta, ERROR_MARGIN_PKTS);
}
private static void assertApproxEquals(
long oldStats, long newStats, int expectedDelta, double errorMargin) {
assertTrue(expectedDelta <= newStats - oldStats);
assertTrue((expectedDelta * errorMargin) > newStats - oldStats);
}
private static void initStatsChecker() throws Exception {
uidTxBytes = TrafficStats.getUidTxBytes(Os.getuid());
uidRxBytes = TrafficStats.getUidRxBytes(Os.getuid());
uidTxPackets = TrafficStats.getUidTxPackets(Os.getuid());
uidRxPackets = TrafficStats.getUidRxPackets(Os.getuid());
ifaceTxBytes = TrafficStats.getLoopbackTxBytes();
ifaceRxBytes = TrafficStats.getLoopbackRxBytes();
ifaceTxPackets = TrafficStats.getLoopbackTxPackets();
ifaceRxPackets = TrafficStats.getLoopbackRxPackets();
}
}
private int getTruncLenBits(IpSecAlgorithm authOrAead) {
return authOrAead == null ? 0 : authOrAead.getTruncationLengthBits();
}
private int getIvLen(IpSecAlgorithm cryptOrAead) {
if (cryptOrAead == null) { return 0; }
switch (cryptOrAead.getName()) {
case IpSecAlgorithm.CRYPT_AES_CBC:
return AES_CBC_IV_LEN;
case IpSecAlgorithm.CRYPT_AES_CTR:
return AES_CTR_IV_LEN;
case IpSecAlgorithm.AUTH_CRYPT_AES_GCM:
return AES_GCM_IV_LEN;
case IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305:
return CHACHA20_POLY1305_IV_LEN;
default:
throw new IllegalArgumentException(
"IV length unknown for algorithm" + cryptOrAead.getName());
}
}
private int getBlkSize(IpSecAlgorithm cryptOrAead) {
// RFC 4303, section 2.4 states that ciphertext plus pad_len, next_header fields must
// terminate on a 4-byte boundary. Thus, the minimum ciphertext block size is 4 bytes.
if (cryptOrAead == null) { return 4; }
switch (cryptOrAead.getName()) {
case IpSecAlgorithm.CRYPT_AES_CBC:
return AES_CBC_BLK_SIZE;
case IpSecAlgorithm.CRYPT_AES_CTR:
return AES_CTR_BLK_SIZE;
case IpSecAlgorithm.AUTH_CRYPT_AES_GCM:
return AES_GCM_BLK_SIZE;
case IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305:
return CHACHA20_POLY1305_BLK_SIZE;
default:
throw new IllegalArgumentException(
"Blk size unknown for algorithm" + cryptOrAead.getName());
}
}
public void checkTransform(
int protocol,
String localAddress,
IpSecAlgorithm crypt,
IpSecAlgorithm auth,
IpSecAlgorithm aead,
boolean doUdpEncap,
int sendCount,
boolean useJavaSockets)
throws Exception {
StatsChecker.initStatsChecker();
InetAddress local = InetAddress.getByName(localAddress);
try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket();
IpSecManager.SecurityParameterIndex spi =
mISM.allocateSecurityParameterIndex(local)) {
IpSecTransform.Builder transformBuilder =
new IpSecTransform.Builder(InstrumentationRegistry.getContext());
if (crypt != null) {
transformBuilder.setEncryption(crypt);
}
if (auth != null) {
transformBuilder.setAuthentication(auth);
}
if (aead != null) {
transformBuilder.setAuthenticatedEncryption(aead);
}
if (doUdpEncap) {
transformBuilder =
transformBuilder.setIpv4Encapsulation(encapSocket, encapSocket.getPort());
}
int ipHdrLen = local instanceof Inet6Address ? IP6_HDRLEN : IP4_HDRLEN;
int transportHdrLen = 0;
int udpEncapLen = doUdpEncap ? UDP_HDRLEN : 0;
try (IpSecTransform transform =
transformBuilder.buildTransportModeTransform(local, spi)) {
if (protocol == IPPROTO_TCP) {
transportHdrLen = TCP_HDRLEN_WITH_TIMESTAMP_OPT;
checkTcp(transform, local, sendCount, useJavaSockets);
} else if (protocol == IPPROTO_UDP) {
transportHdrLen = UDP_HDRLEN;
// TODO: Also check connected udp.
checkUnconnectedUdp(transform, local, sendCount, useJavaSockets);
} else {
throw new IllegalArgumentException("Invalid protocol");
}
}
checkStatsChecker(
protocol,
ipHdrLen,
transportHdrLen,
udpEncapLen,
sendCount,
getIvLen(crypt != null ? crypt : aead),
getBlkSize(crypt != null ? crypt : aead),
getTruncLenBits(auth != null ? auth : aead));
}
}
private void checkStatsChecker(
int protocol,
int ipHdrLen,
int transportHdrLen,
int udpEncapLen,
int sendCount,
int ivLen,
int blkSize,
int truncLenBits)
throws Exception {
int innerPacketSize = TEST_DATA.length + transportHdrLen + ipHdrLen;
int outerPacketSize =
PacketUtils.calculateEspPacketSize(
TEST_DATA.length + transportHdrLen, ivLen, blkSize, truncLenBits)
+ udpEncapLen
+ ipHdrLen;
int expectedOuterBytes = outerPacketSize * sendCount;
int expectedInnerBytes = innerPacketSize * sendCount;
int expectedPackets = sendCount;
// Each run sends two packets, one in each direction.
sendCount *= 2;
expectedOuterBytes *= 2;
expectedInnerBytes *= 2;
expectedPackets *= 2;
// Add TCP ACKs for data packets
if (protocol == IPPROTO_TCP) {
int encryptedTcpPktSize =
PacketUtils.calculateEspPacketSize(
TCP_HDRLEN_WITH_TIMESTAMP_OPT, ivLen, blkSize, truncLenBits);
// Add data packet ACKs
expectedOuterBytes += (encryptedTcpPktSize + udpEncapLen + ipHdrLen) * (sendCount);
expectedInnerBytes += (TCP_HDRLEN_WITH_TIMESTAMP_OPT + ipHdrLen) * (sendCount);
expectedPackets += sendCount;
}
StatsChecker.waitForNumPackets(expectedPackets);
// eBPF only counts inner packets, whereas xt_qtaguid counts outer packets. Allow both
StatsChecker.assertUidStatsDelta(
expectedOuterBytes,
expectedPackets,
expectedInnerBytes,
expectedOuterBytes,
expectedPackets);
// Unreliable at low numbers due to potential interference from other processes.
if (sendCount >= 1000) {
StatsChecker.assertIfaceStatsDelta(
expectedOuterBytes, expectedPackets, expectedOuterBytes, expectedPackets);
}
}
private void checkIkePacket(
NativeUdpSocket wrappedEncapSocket, InetAddress localAddr) throws Exception {
StatsChecker.initStatsChecker();
try (NativeUdpSocket remoteSocket = new NativeUdpSocket(getBoundUdpSocket(localAddr))) {
// Append IKE/ESP header - 4 bytes of SPI, 4 bytes of seq number, all zeroed out
// If the first four bytes are zero, assume non-ESP (IKE traffic)
byte[] dataWithEspHeader = new byte[TEST_DATA.length + 8];
System.arraycopy(TEST_DATA, 0, dataWithEspHeader, 8, TEST_DATA.length);
// Send the IKE packet from remoteSocket to wrappedEncapSocket. Since IKE packets
// are multiplexed over the socket, we expect them to appear on the encap socket
// (as opposed to being decrypted and received on the non-encap socket)
remoteSocket.sendTo(dataWithEspHeader, localAddr, wrappedEncapSocket.getPort());
byte[] in = wrappedEncapSocket.receive();
assertArrayEquals("Encapsulated data did not match.", dataWithEspHeader, in);
// Also test that the IKE socket can send data out.
wrappedEncapSocket.sendTo(dataWithEspHeader, localAddr, remoteSocket.getPort());
in = remoteSocket.receive();
assertArrayEquals("Encapsulated data did not match.", dataWithEspHeader, in);
// Calculate expected packet sizes. Always use IPv4 header, since our kernels only
// guarantee support of UDP encap on IPv4.
int expectedNumPkts = 2;
int expectedPacketSize =
expectedNumPkts * (dataWithEspHeader.length + UDP_HDRLEN + IP4_HDRLEN);
StatsChecker.waitForNumPackets(expectedNumPkts);
StatsChecker.assertUidStatsDelta(
expectedPacketSize,
expectedNumPkts,
expectedPacketSize,
expectedPacketSize,
expectedNumPkts);
StatsChecker.assertIfaceStatsDelta(
expectedPacketSize, expectedNumPkts, expectedPacketSize, expectedNumPkts);
}
}
@Test
public void testIkeOverUdpEncapSocket() throws Exception {
// IPv6 not supported for UDP-encap-ESP
InetAddress local = InetAddress.getByName(IPV4_LOOPBACK);
try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
NativeUdpSocket wrappedEncapSocket =
new NativeUdpSocket(encapSocket.getFileDescriptor());
checkIkePacket(wrappedEncapSocket, local);
// Now try with a transform applied to a socket using this Encap socket
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
try (IpSecManager.SecurityParameterIndex spi =
mISM.allocateSecurityParameterIndex(local);
IpSecTransform transform =
new IpSecTransform.Builder(InstrumentationRegistry.getContext())
.setEncryption(crypt)
.setAuthentication(auth)
.setIpv4Encapsulation(encapSocket, encapSocket.getPort())
.buildTransportModeTransform(local, spi);
JavaUdpSocket localSocket = new JavaUdpSocket(local)) {
applyTransformBidirectionally(mISM, transform, localSocket);
checkIkePacket(wrappedEncapSocket, local);
}
}
}
// TODO: Check IKE over ESP sockets (IPv4, IPv6) - does this need SOCK_RAW?
/* TODO: Re-enable these when policy matcher works for reflected packets
*
* The issue here is that A sends to B, and everything is new; therefore PREROUTING counts
* correctly. But it appears that the security path is not cleared afterwards, thus when A
* sends an ACK back to B, the policy matcher flags it as a "IPSec" packet. See b/70635417
*/
// public void testInterfaceCountersTcp4() throws Exception {
// IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
// IpSecAlgorithm auth = new IpSecAlgorithm(
// IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
// checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, false, 1000);
// }
// public void testInterfaceCountersTcp6() throws Exception {
// IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
// IpSecAlgorithm auth = new IpSecAlgorithm(
// IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
// checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, false, 1000);
// }
// public void testInterfaceCountersTcp4UdpEncap() throws Exception {
// IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
// IpSecAlgorithm auth =
// new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
// checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, true, 1000);
// }
@IgnoreUpTo(Build.VERSION_CODES.R)
@Test
public void testGetSupportedAlgorithms() throws Exception {
final Map<String, Integer> algoToRequiredMinSdk = new HashMap<>();
algoToRequiredMinSdk.put(CRYPT_AES_CBC, Build.VERSION_CODES.P);
algoToRequiredMinSdk.put(AUTH_HMAC_MD5, Build.VERSION_CODES.P);
algoToRequiredMinSdk.put(AUTH_HMAC_SHA1, Build.VERSION_CODES.P);
algoToRequiredMinSdk.put(AUTH_HMAC_SHA256, Build.VERSION_CODES.P);
algoToRequiredMinSdk.put(AUTH_HMAC_SHA384, Build.VERSION_CODES.P);
algoToRequiredMinSdk.put(AUTH_HMAC_SHA512, Build.VERSION_CODES.P);
algoToRequiredMinSdk.put(AUTH_CRYPT_AES_GCM, Build.VERSION_CODES.P);
// TODO: b/170424293 Use Build.VERSION_CODES.S when is finalized
algoToRequiredMinSdk.put(CRYPT_AES_CTR, Build.VERSION_CODES.R + 1);
algoToRequiredMinSdk.put(AUTH_AES_CMAC, Build.VERSION_CODES.R + 1);
algoToRequiredMinSdk.put(AUTH_AES_XCBC, Build.VERSION_CODES.R + 1);
algoToRequiredMinSdk.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.R + 1);
final Set<String> supportedAlgos = IpSecAlgorithm.getSupportedAlgorithms();
// Verify all supported algorithms are valid
for (String algo : supportedAlgos) {
assertTrue("Found invalid algo " + algo, algoToRequiredMinSdk.keySet().contains(algo));
}
// Verify all mandatory algorithms are supported
for (Entry<String, Integer> entry : algoToRequiredMinSdk.entrySet()) {
if (Math.min(getFirstApiLevel(), getVendorApiLevel()) >= entry.getValue()) {
assertTrue(
"Fail to support " + entry.getKey(),
supportedAlgos.contains(entry.getKey()));
}
}
}
@Test
public void testInterfaceCountersUdp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1000, false);
}
@Test
public void testInterfaceCountersUdp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1000, false);
}
@Test
public void testInterfaceCountersUdp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1000, false);
}
@Test
public void testAesCbcHmacMd5Tcp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
@SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec")
public void testAesCbcHmacMd5Tcp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcHmacMd5Udp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcHmacMd5Udp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcHmacSha1Tcp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
@SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec")
public void testAesCbcHmacSha1Tcp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcHmacSha1Udp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcHmacSha1Udp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcHmacSha256Tcp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
@SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec")
public void testAesCbcHmacSha256Tcp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcHmacSha256Udp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcHmacSha256Udp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcHmacSha384Tcp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
@SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec")
public void testAesCbcHmacSha384Tcp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcHmacSha384Udp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcHmacSha384Udp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcHmacSha512Tcp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
@SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec")
public void testAesCbcHmacSha512Tcp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcHmacSha512Udp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcHmacSha512Udp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
private static IpSecAlgorithm buildCryptAesCtr() throws Exception {
return new IpSecAlgorithm(CRYPT_AES_CTR, getKeyBytes(AES_CTR_KEY_LEN_20));
}
private static IpSecAlgorithm buildAuthHmacSha512() throws Exception {
return new IpSecAlgorithm(
AUTH_HMAC_SHA512, getKeyBytes(HMAC_SHA512_KEY_LEN), HMAC_SHA512_ICV_LEN * 8);
}
@Test
public void testAesCtrHmacSha512Tcp4() throws Exception {
assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
final IpSecAlgorithm crypt = buildCryptAesCtr();
final IpSecAlgorithm auth = buildAuthHmacSha512();
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
@SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec")
public void testAesCtrHmacSha512Tcp6() throws Exception {
assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
final IpSecAlgorithm crypt = buildCryptAesCtr();
final IpSecAlgorithm auth = buildAuthHmacSha512();
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCtrHmacSha512Udp4() throws Exception {
assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
final IpSecAlgorithm crypt = buildCryptAesCtr();
final IpSecAlgorithm auth = buildAuthHmacSha512();
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCtrHmacSha512Udp6() throws Exception {
assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
final IpSecAlgorithm crypt = buildCryptAesCtr();
final IpSecAlgorithm auth = buildAuthHmacSha512();
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
private static IpSecAlgorithm buildCryptAesCbc() throws Exception {
return new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY);
}
private static IpSecAlgorithm buildAuthAesXcbc() throws Exception {
return new IpSecAlgorithm(
AUTH_AES_XCBC, getKeyBytes(AES_XCBC_KEY_LEN), AES_XCBC_ICV_LEN * 8);
}
private static IpSecAlgorithm buildAuthAesCmac() throws Exception {
return new IpSecAlgorithm(
AUTH_AES_CMAC, getKeyBytes(AES_CMAC_KEY_LEN), AES_CMAC_ICV_LEN * 8);
}
@Test
public void testAesCbcAesXCbcTcp4() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
final IpSecAlgorithm crypt = buildCryptAesCbc();
final IpSecAlgorithm auth = buildAuthAesXcbc();
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
@SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec")
public void testAesCbcAesXCbcTcp6() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
final IpSecAlgorithm crypt = buildCryptAesCbc();
final IpSecAlgorithm auth = buildAuthAesXcbc();
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcAesXCbcUdp4() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
final IpSecAlgorithm crypt = buildCryptAesCbc();
final IpSecAlgorithm auth = buildAuthAesXcbc();
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcAesXCbcUdp6() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
final IpSecAlgorithm crypt = buildCryptAesCbc();
final IpSecAlgorithm auth = buildAuthAesXcbc();
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcAesCmacTcp4() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
final IpSecAlgorithm crypt = buildCryptAesCbc();
final IpSecAlgorithm auth = buildAuthAesCmac();
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
@SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec")
public void testAesCbcAesCmacTcp6() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
final IpSecAlgorithm crypt = buildCryptAesCbc();
final IpSecAlgorithm auth = buildAuthAesCmac();
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcAesCmacUdp4() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
final IpSecAlgorithm crypt = buildCryptAesCbc();
final IpSecAlgorithm auth = buildAuthAesCmac();
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesCbcAesCmacUdp6() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
final IpSecAlgorithm crypt = buildCryptAesCbc();
final IpSecAlgorithm auth = buildAuthAesCmac();
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
}
@Test
public void testAesGcm64Tcp4() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
}
@Test
@SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec")
public void testAesGcm64Tcp6() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
}
@Test
public void testAesGcm64Udp4() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
}
@Test
public void testAesGcm64Udp6() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
}
@Test
public void testAesGcm96Tcp4() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
}
@Test
@SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec")
public void testAesGcm96Tcp6() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
}
@Test
public void testAesGcm96Udp4() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
}
@Test
public void testAesGcm96Udp6() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
}
@Test
public void testAesGcm128Tcp4() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
}
@Test
@SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec")
public void testAesGcm128Tcp6() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
}
@Test
public void testAesGcm128Udp4() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
}
@Test
public void testAesGcm128Udp6() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
}
private static IpSecAlgorithm buildAuthCryptChaCha20Poly1305() throws Exception {
return new IpSecAlgorithm(
AUTH_CRYPT_CHACHA20_POLY1305, AEAD_KEY, CHACHA20_POLY1305_ICV_LEN * 8);
}
@Test
public void testChaCha20Poly1305Tcp4() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
}
@Test
@SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec")
public void testChaCha20Poly1305Tcp6() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
}
@Test
public void testChaCha20Poly1305Udp4() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
}
@Test
public void testChaCha20Poly1305Udp6() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
}
@Test
public void testAesCbcHmacMd5Tcp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
@Test
public void testAesCbcHmacMd5Udp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
@Test
public void testAesCbcHmacSha1Tcp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
@Test
public void testAesCbcHmacSha1Udp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
@Test
public void testAesCbcHmacSha256Tcp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
@Test
public void testAesCbcHmacSha256Udp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
@Test
public void testAesCbcHmacSha384Tcp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
@Test
public void testAesCbcHmacSha384Udp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
@Test
public void testAesCbcHmacSha512Tcp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
@Test
public void testAesCbcHmacSha512Udp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
@Test
public void testAesCtrHmacSha512Tcp4UdpEncap() throws Exception {
assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
final IpSecAlgorithm crypt = buildCryptAesCtr();
final IpSecAlgorithm auth = buildAuthHmacSha512();
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
@Test
public void testAesCtrHmacSha512Udp4UdpEncap() throws Exception {
assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
final IpSecAlgorithm crypt = buildCryptAesCtr();
final IpSecAlgorithm auth = buildAuthHmacSha512();
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
@Test
public void testAesCbcAesXCbcTcp4UdpEncap() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
final IpSecAlgorithm crypt = new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY);
final IpSecAlgorithm auth = new IpSecAlgorithm(AUTH_AES_XCBC, getKey(128), 96);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
@Test
public void testAesCbcAesXCbcUdp4UdpEncap() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
final IpSecAlgorithm crypt = new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY);
final IpSecAlgorithm auth = new IpSecAlgorithm(AUTH_AES_XCBC, getKey(128), 96);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
@Test
public void testAesCbcAesCmacTcp4UdpEncap() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
final IpSecAlgorithm crypt = new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY);
final IpSecAlgorithm auth = new IpSecAlgorithm(AUTH_AES_CMAC, getKey(128), 96);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
@Test
public void testAesCbcAesCmacUdp4UdpEncap() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
final IpSecAlgorithm crypt = new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY);
final IpSecAlgorithm auth = new IpSecAlgorithm(AUTH_AES_CMAC, getKey(128), 96);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
}
@Test
public void testAesGcm64Tcp4UdpEncap() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
}
@Test
public void testAesGcm64Udp4UdpEncap() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
}
@Test
public void testAesGcm96Tcp4UdpEncap() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
}
@Test
public void testAesGcm96Udp4UdpEncap() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
}
@Test
public void testAesGcm128Tcp4UdpEncap() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
}
@Test
public void testAesGcm128Udp4UdpEncap() throws Exception {
IpSecAlgorithm authCrypt =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
}
@Test
public void testChaCha20Poly1305Tcp4UdpEncap() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
}
@Test
public void testChaCha20Poly1305Udp4UdpEncap() throws Exception {
assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
}
@Test
public void testCryptUdp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, false, 1, true);
}
@Test
public void testAuthUdp4() throws Exception {
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, false, 1, true);
}
@Test
public void testCryptUdp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, null, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, null, null, false, 1, true);
}
@Test
public void testAuthUdp6() throws Exception {
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, auth, null, false, 1, false);
checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, auth, null, false, 1, true);
}
@Test
public void testCryptTcp4() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, false, 1, true);
}
@Test
public void testAuthTcp4() throws Exception {
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, false, 1, true);
}
@Test
@SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec")
public void testCryptTcp6() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, null, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, null, null, false, 1, true);
}
@Test
@SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec")
public void testAuthTcp6() throws Exception {
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, auth, null, false, 1, false);
checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, auth, null, false, 1, true);
}
@Test
public void testCryptUdp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, true, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, true, 1, true);
}
@Test
public void testAuthUdp4UdpEncap() throws Exception {
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, true, 1, false);
checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, true, 1, true);
}
@Test
public void testCryptTcp4UdpEncap() throws Exception {
IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, true, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, true, 1, true);
}
@Test
public void testAuthTcp4UdpEncap() throws Exception {
IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, true, 1, false);
checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, true, 1, true);
}
@Test
public void testOpenUdpEncapSocketSpecificPort() throws Exception {
IpSecManager.UdpEncapsulationSocket encapSocket = null;
int port = -1;
for (int i = 0; i < MAX_PORT_BIND_ATTEMPTS; i++) {
try {
port = findUnusedPort();
encapSocket = mISM.openUdpEncapsulationSocket(port);
break;
} catch (ErrnoException e) {
if (e.errno == OsConstants.EADDRINUSE) {
// Someone claimed the port since we called findUnusedPort.
continue;
}
throw e;
} finally {
if (encapSocket != null) {
encapSocket.close();
}
}
}
if (encapSocket == null) {
fail("Failed " + MAX_PORT_BIND_ATTEMPTS + " attempts to bind to a port");
}
assertTrue("Returned invalid port", encapSocket.getPort() == port);
}
@Test
public void testOpenUdpEncapSocketRandomPort() throws Exception {
try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
assertTrue("Returned invalid port", encapSocket.getPort() != 0);
}
}
}