Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.net.cts;
     18 
     19 import static android.system.OsConstants.IPPROTO_TCP;
     20 import static android.system.OsConstants.IPPROTO_UDP;
     21 import static org.junit.Assert.assertArrayEquals;
     22 import static org.junit.Assert.assertTrue;
     23 
     24 import android.content.Context;
     25 import android.net.ConnectivityManager;
     26 import android.net.IpSecAlgorithm;
     27 import android.net.IpSecManager;
     28 import android.net.IpSecTransform;
     29 import android.net.TrafficStats;
     30 import android.system.ErrnoException;
     31 import android.system.Os;
     32 import android.system.OsConstants;
     33 
     34 import java.io.FileDescriptor;
     35 import java.io.IOException;
     36 import java.net.DatagramPacket;
     37 import java.net.DatagramSocket;
     38 import java.net.Inet6Address;
     39 import java.net.InetAddress;
     40 import java.net.UnknownHostException;
     41 import java.util.Arrays;
     42 
     43 public class IpSecManagerTest extends IpSecBaseTest {
     44 
     45     private static final String TAG = IpSecManagerTest.class.getSimpleName();
     46 
     47     private ConnectivityManager mCM;
     48 
     49     private static InetAddress IpAddress(String addrString) {
     50         try {
     51             return InetAddress.getByName(addrString);
     52         } catch (UnknownHostException e) {
     53             throw new IllegalArgumentException("Invalid IP address: " + e);
     54         }
     55     }
     56 
     57     private static final InetAddress GOOGLE_DNS_4 = IpAddress("8.8.8.8");
     58     private static final InetAddress GOOGLE_DNS_6 = IpAddress("2001:4860:4860::8888");
     59 
     60     private static final InetAddress[] GOOGLE_DNS_LIST =
     61             new InetAddress[] {GOOGLE_DNS_4, GOOGLE_DNS_6};
     62 
     63     private static final int DROID_SPI = 0xD1201D;
     64     private static final int MAX_PORT_BIND_ATTEMPTS = 10;
     65 
     66     private static final byte[] AEAD_KEY = getKey(288);
     67 
     68     private static final int TCP_HDRLEN_WITH_OPTIONS = 32;
     69     private static final int UDP_HDRLEN = 8;
     70     private static final int IP4_HDRLEN = 20;
     71     private static final int IP6_HDRLEN = 40;
     72 
     73     // Encryption parameters
     74     private static final int AES_GCM_IV_LEN = 8;
     75     private static final int AES_CBC_IV_LEN = 16;
     76     private static final int AES_GCM_BLK_SIZE = 4;
     77     private static final int AES_CBC_BLK_SIZE = 16;
     78 
     79     protected void setUp() throws Exception {
     80         super.setUp();
     81         mCM = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
     82     }
     83 
     84     /*
     85      * Allocate a random SPI
     86      * Allocate a specific SPI using previous randomly created SPI value
     87      * Realloc the same SPI that was specifically created (expect SpiUnavailable)
     88      * Close SPIs
     89      */
     90     public void testAllocSpi() throws Exception {
     91         for (InetAddress addr : GOOGLE_DNS_LIST) {
     92             IpSecManager.SecurityParameterIndex randomSpi = null, droidSpi = null;
     93             randomSpi = mISM.allocateSecurityParameterIndex(addr);
     94             assertTrue(
     95                     "Failed to receive a valid SPI",
     96                     randomSpi.getSpi() != IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
     97 
     98             droidSpi = mISM.allocateSecurityParameterIndex(addr, DROID_SPI);
     99             assertTrue("Failed to allocate specified SPI, " + DROID_SPI,
    100                     droidSpi.getSpi() == DROID_SPI);
    101 
    102             try {
    103                 mISM.allocateSecurityParameterIndex(addr, DROID_SPI);
    104                 fail("Duplicate SPI was allowed to be created");
    105             } catch (IpSecManager.SpiUnavailableException expected) {
    106                 // This is a success case because we expect a dupe SPI to throw
    107             }
    108 
    109             randomSpi.close();
    110             droidSpi.close();
    111         }
    112     }
    113 
    114     /** This function finds an available port */
    115     private static int findUnusedPort() throws Exception {
    116         // Get an available port.
    117         DatagramSocket s = new DatagramSocket();
    118         int port = s.getLocalPort();
    119         s.close();
    120         return port;
    121     }
    122 
    123     private static FileDescriptor getBoundUdpSocket(InetAddress address) throws Exception {
    124         FileDescriptor sock =
    125                 Os.socket(getDomain(address), OsConstants.SOCK_DGRAM, OsConstants.IPPROTO_UDP);
    126 
    127         for (int i = 0; i < MAX_PORT_BIND_ATTEMPTS; i++) {
    128             try {
    129                 int port = findUnusedPort();
    130                 Os.bind(sock, address, port);
    131                 break;
    132             } catch (ErrnoException e) {
    133                 // Someone claimed the port since we called findUnusedPort.
    134                 if (e.errno == OsConstants.EADDRINUSE) {
    135                     if (i == MAX_PORT_BIND_ATTEMPTS - 1) {
    136 
    137                         fail("Failed " + MAX_PORT_BIND_ATTEMPTS + " attempts to bind to a port");
    138                     }
    139                     continue;
    140                 }
    141                 throw e.rethrowAsIOException();
    142             }
    143         }
    144         return sock;
    145     }
    146 
    147     private void checkUnconnectedUdp(IpSecTransform transform, InetAddress local, int sendCount,
    148                                      boolean useJavaSockets) throws Exception {
    149         GenericUdpSocket sockLeft = null, sockRight = null;
    150         if (useJavaSockets) {
    151             SocketPair<JavaUdpSocket> sockets = getJavaUdpSocketPair(local, mISM, transform, false);
    152             sockLeft = sockets.mLeftSock;
    153             sockRight = sockets.mRightSock;
    154         } else {
    155             SocketPair<NativeUdpSocket> sockets =
    156                     getNativeUdpSocketPair(local, mISM, transform, false);
    157             sockLeft = sockets.mLeftSock;
    158             sockRight = sockets.mRightSock;
    159         }
    160 
    161         for (int i = 0; i < sendCount; i++) {
    162             byte[] in;
    163 
    164             sockLeft.sendTo(TEST_DATA, local, sockRight.getPort());
    165             in = sockRight.receive();
    166             assertArrayEquals("Left-to-right encrypted data did not match.", TEST_DATA, in);
    167 
    168             sockRight.sendTo(TEST_DATA, local, sockLeft.getPort());
    169             in = sockLeft.receive();
    170             assertArrayEquals("Right-to-left encrypted data did not match.", TEST_DATA, in);
    171         }
    172 
    173         sockLeft.close();
    174         sockRight.close();
    175     }
    176 
    177     private void checkTcp(IpSecTransform transform, InetAddress local, int sendCount,
    178                           boolean useJavaSockets) throws Exception {
    179         GenericTcpSocket client = null, accepted = null;
    180         if (useJavaSockets) {
    181             SocketPair<JavaTcpSocket> sockets = getJavaTcpSocketPair(local, mISM, transform);
    182             client = sockets.mLeftSock;
    183             accepted = sockets.mRightSock;
    184         } else {
    185             SocketPair<NativeTcpSocket> sockets = getNativeTcpSocketPair(local, mISM, transform);
    186             client = sockets.mLeftSock;
    187             accepted = sockets.mRightSock;
    188         }
    189 
    190         // Wait for TCP handshake packets to be counted
    191         StatsChecker.waitForNumPackets(3); // (SYN, SYN+ACK, ACK)
    192 
    193         // Reset StatsChecker, to ignore negotiation overhead.
    194         StatsChecker.initStatsChecker();
    195         for (int i = 0; i < sendCount; i++) {
    196             byte[] in;
    197 
    198             client.send(TEST_DATA);
    199             in = accepted.receive();
    200             assertArrayEquals("Client-to-server encrypted data did not match.", TEST_DATA, in);
    201 
    202             // Allow for newest data + ack packets to be returned before sending next packet
    203             // Also add the number of expected packets in each of the previous runs (4 per run)
    204             StatsChecker.waitForNumPackets(2 + (4 * i));
    205 
    206             accepted.send(TEST_DATA);
    207             in = client.receive();
    208             assertArrayEquals("Server-to-client encrypted data did not match.", TEST_DATA, in);
    209 
    210             // Allow for all data + ack packets to be returned before sending next packet
    211             // Also add the number of expected packets in each of the previous runs (4 per run)
    212             StatsChecker.waitForNumPackets(4 * (i + 1));
    213         }
    214 
    215         // Transforms should not be removed from the sockets, otherwise FIN packets will be sent
    216         //     unencrypted.
    217         // This test also unfortunately happens to rely on a nuance of the cleanup order. By
    218         //     keeping the policy on the socket, but removing the SA before lingering FIN packets
    219         //     are sent (at an undetermined later time), the FIN packets are dropped. Without this,
    220         //     we run into all kinds of headaches trying to test data accounting (unsolicited
    221         //     packets mysteriously appearing and messing up our counters)
    222         // The right way to close sockets is to set SO_LINGER to ensure synchronous closure,
    223         //     closing the sockets, and then closing the transforms. See documentation for the
    224         //     Socket or FileDescriptor flavors of applyTransportModeTransform() in IpSecManager
    225         //     for more details.
    226 
    227         client.close();
    228         accepted.close();
    229     }
    230 
    231     /*
    232      * Alloc outbound SPI
    233      * Alloc inbound SPI
    234      * Create transport mode transform
    235      * open socket
    236      * apply transform to socket
    237      * send data on socket
    238      * release transform
    239      * send data (expect exception)
    240      */
    241     public void testCreateTransform() throws Exception {
    242         InetAddress localAddr = InetAddress.getByName(IPV4_LOOPBACK);
    243         IpSecManager.SecurityParameterIndex spi =
    244                 mISM.allocateSecurityParameterIndex(localAddr);
    245 
    246         IpSecTransform transform =
    247                 new IpSecTransform.Builder(mContext)
    248                         .setEncryption(new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
    249                         .setAuthentication(
    250                                 new IpSecAlgorithm(
    251                                         IpSecAlgorithm.AUTH_HMAC_SHA256,
    252                                         AUTH_KEY,
    253                                         AUTH_KEY.length * 8))
    254                         .buildTransportModeTransform(localAddr, spi);
    255 
    256         final boolean [][] applyInApplyOut = {
    257                 {false, false}, {false, true}, {true, false}, {true,true}};
    258         final byte[] data = new String("Best test data ever!").getBytes("UTF-8");
    259         final DatagramPacket outPacket = new DatagramPacket(data, 0, data.length, localAddr, 0);
    260 
    261         byte[] in = new byte[data.length];
    262         DatagramPacket inPacket = new DatagramPacket(in, in.length);
    263         DatagramSocket localSocket;
    264         int localPort;
    265 
    266         for(boolean[] io : applyInApplyOut) {
    267             boolean applyIn = io[0];
    268             boolean applyOut = io[1];
    269             // Bind localSocket to a random available port.
    270             localSocket = new DatagramSocket(0);
    271             localPort = localSocket.getLocalPort();
    272             localSocket.setSoTimeout(200);
    273             outPacket.setPort(localPort);
    274             if (applyIn) {
    275                 mISM.applyTransportModeTransform(
    276                         localSocket, IpSecManager.DIRECTION_IN, transform);
    277             }
    278             if (applyOut) {
    279                 mISM.applyTransportModeTransform(
    280                         localSocket, IpSecManager.DIRECTION_OUT, transform);
    281             }
    282             if (applyIn == applyOut) {
    283                 localSocket.send(outPacket);
    284                 localSocket.receive(inPacket);
    285                 assertTrue("Encapsulated data did not match.",
    286                         Arrays.equals(outPacket.getData(), inPacket.getData()));
    287                 mISM.removeTransportModeTransforms(localSocket);
    288                 localSocket.close();
    289             } else {
    290                 try {
    291                     localSocket.send(outPacket);
    292                     localSocket.receive(inPacket);
    293                 } catch (IOException e) {
    294                     continue;
    295                 } finally {
    296                     mISM.removeTransportModeTransforms(localSocket);
    297                     localSocket.close();
    298                 }
    299                 // FIXME: This check is disabled because sockets currently receive data
    300                 // if there is a valid SA for decryption, even when the input policy is
    301                 // not applied to a socket.
    302                 //  fail("Data IO should fail on asymmetrical transforms! + Input="
    303                 //          + applyIn + " Output=" + applyOut);
    304             }
    305         }
    306         transform.close();
    307     }
    308 
    309     /** Snapshot of TrafficStats as of initStatsChecker call for later comparisons */
    310     private static class StatsChecker {
    311         private static final double ERROR_MARGIN_BYTES = 1.05;
    312         private static final double ERROR_MARGIN_PKTS = 1.05;
    313         private static final int MAX_WAIT_TIME_MILLIS = 1000;
    314 
    315         private static long uidTxBytes;
    316         private static long uidRxBytes;
    317         private static long uidTxPackets;
    318         private static long uidRxPackets;
    319 
    320         private static long ifaceTxBytes;
    321         private static long ifaceRxBytes;
    322         private static long ifaceTxPackets;
    323         private static long ifaceRxPackets;
    324 
    325         /**
    326          * This method counts the number of incoming packets, polling intermittently up to
    327          * MAX_WAIT_TIME_MILLIS.
    328          */
    329         private static void waitForNumPackets(int numPackets) throws Exception {
    330             long uidTxDelta = 0;
    331             long uidRxDelta = 0;
    332             for (int i = 0; i < 100; i++) {
    333                 uidTxDelta = TrafficStats.getUidTxPackets(Os.getuid()) - uidTxPackets;
    334                 uidRxDelta = TrafficStats.getUidRxPackets(Os.getuid()) - uidRxPackets;
    335 
    336                 // TODO: Check Rx packets as well once kernel security policy bug is fixed.
    337                 // (b/70635417)
    338                 if (uidTxDelta >= numPackets) {
    339                     return;
    340                 }
    341                 Thread.sleep(MAX_WAIT_TIME_MILLIS / 100);
    342             }
    343             fail(
    344                     "Not enough traffic was recorded to satisfy the provided conditions: wanted "
    345                             + numPackets
    346                             + ", got "
    347                             + uidTxDelta
    348                             + " tx and "
    349                             + uidRxDelta
    350                             + " rx packets");
    351         }
    352 
    353         private static void assertUidStatsDelta(
    354                 int expectedTxByteDelta,
    355                 int expectedTxPacketDelta,
    356                 int minRxByteDelta,
    357                 int maxRxByteDelta,
    358                 int expectedRxPacketDelta) {
    359             long newUidTxBytes = TrafficStats.getUidTxBytes(Os.getuid());
    360             long newUidRxBytes = TrafficStats.getUidRxBytes(Os.getuid());
    361             long newUidTxPackets = TrafficStats.getUidTxPackets(Os.getuid());
    362             long newUidRxPackets = TrafficStats.getUidRxPackets(Os.getuid());
    363 
    364             assertEquals(expectedTxByteDelta, newUidTxBytes - uidTxBytes);
    365             assertTrue(
    366                     newUidRxBytes - uidRxBytes >= minRxByteDelta
    367                             && newUidRxBytes - uidRxBytes <= maxRxByteDelta);
    368             assertEquals(expectedTxPacketDelta, newUidTxPackets - uidTxPackets);
    369             assertEquals(expectedRxPacketDelta, newUidRxPackets - uidRxPackets);
    370         }
    371 
    372         private static void assertIfaceStatsDelta(
    373                 int expectedTxByteDelta,
    374                 int expectedTxPacketDelta,
    375                 int expectedRxByteDelta,
    376                 int expectedRxPacketDelta)
    377                 throws IOException {
    378             long newIfaceTxBytes = TrafficStats.getLoopbackTxBytes();
    379             long newIfaceRxBytes = TrafficStats.getLoopbackRxBytes();
    380             long newIfaceTxPackets = TrafficStats.getLoopbackTxPackets();
    381             long newIfaceRxPackets = TrafficStats.getLoopbackRxPackets();
    382 
    383             // Check that iface stats are within an acceptable range; data might be sent
    384             // on the local interface by other apps.
    385             assertApproxEquals(
    386                     ifaceTxBytes, newIfaceTxBytes, expectedTxByteDelta, ERROR_MARGIN_BYTES);
    387             assertApproxEquals(
    388                     ifaceRxBytes, newIfaceRxBytes, expectedRxByteDelta, ERROR_MARGIN_BYTES);
    389             assertApproxEquals(
    390                     ifaceTxPackets, newIfaceTxPackets, expectedTxPacketDelta, ERROR_MARGIN_PKTS);
    391             assertApproxEquals(
    392                     ifaceRxPackets, newIfaceRxPackets, expectedRxPacketDelta, ERROR_MARGIN_PKTS);
    393         }
    394 
    395         private static void assertApproxEquals(
    396                 long oldStats, long newStats, int expectedDelta, double errorMargin) {
    397             assertTrue(expectedDelta <= newStats - oldStats);
    398             assertTrue((expectedDelta * errorMargin) > newStats - oldStats);
    399         }
    400 
    401         private static void initStatsChecker() throws Exception {
    402             uidTxBytes = TrafficStats.getUidTxBytes(Os.getuid());
    403             uidRxBytes = TrafficStats.getUidRxBytes(Os.getuid());
    404             uidTxPackets = TrafficStats.getUidTxPackets(Os.getuid());
    405             uidRxPackets = TrafficStats.getUidRxPackets(Os.getuid());
    406 
    407             ifaceTxBytes = TrafficStats.getLoopbackTxBytes();
    408             ifaceRxBytes = TrafficStats.getLoopbackRxBytes();
    409             ifaceTxPackets = TrafficStats.getLoopbackTxPackets();
    410             ifaceRxPackets = TrafficStats.getLoopbackRxPackets();
    411         }
    412     }
    413 
    414     private int getTruncLenBits(IpSecAlgorithm authOrAead) {
    415         return authOrAead == null ? 0 : authOrAead.getTruncationLengthBits();
    416     }
    417 
    418     private int getIvLen(IpSecAlgorithm cryptOrAead) {
    419         if (cryptOrAead == null) { return 0; }
    420 
    421         switch (cryptOrAead.getName()) {
    422             case IpSecAlgorithm.CRYPT_AES_CBC:
    423                 return AES_CBC_IV_LEN;
    424             case IpSecAlgorithm.AUTH_CRYPT_AES_GCM:
    425                 return AES_GCM_IV_LEN;
    426             default:
    427                 throw new IllegalArgumentException(
    428                         "IV length unknown for algorithm" + cryptOrAead.getName());
    429         }
    430     }
    431 
    432     private int getBlkSize(IpSecAlgorithm cryptOrAead) {
    433         // RFC 4303, section 2.4 states that ciphertext plus pad_len, next_header fields must
    434         //     terminate on a 4-byte boundary. Thus, the minimum ciphertext block size is 4 bytes.
    435         if (cryptOrAead == null) { return 4; }
    436 
    437         switch (cryptOrAead.getName()) {
    438             case IpSecAlgorithm.CRYPT_AES_CBC:
    439                 return AES_CBC_BLK_SIZE;
    440             case IpSecAlgorithm.AUTH_CRYPT_AES_GCM:
    441                 return AES_GCM_BLK_SIZE;
    442             default:
    443                 throw new IllegalArgumentException(
    444                         "Blk size unknown for algorithm" + cryptOrAead.getName());
    445         }
    446     }
    447 
    448     /** Helper function to calculate expected ESP packet size. */
    449     private int calculateEspPacketSize(
    450             int payloadLen, int cryptIvLength, int cryptBlockSize, int authTruncLen) {
    451         final int ESP_HDRLEN = 4 + 4; // SPI + Seq#
    452         final int ICV_LEN = authTruncLen / 8; // Auth trailer; based on truncation length
    453         payloadLen += cryptIvLength; // Initialization Vector
    454         payloadLen += 2; // ESP trailer
    455 
    456         // Align to block size of encryption algorithm
    457         payloadLen += (cryptBlockSize - (payloadLen % cryptBlockSize)) % cryptBlockSize;
    458         return payloadLen + ESP_HDRLEN + ICV_LEN;
    459     }
    460 
    461     public void checkTransform(
    462             int protocol,
    463             String localAddress,
    464             IpSecAlgorithm crypt,
    465             IpSecAlgorithm auth,
    466             IpSecAlgorithm aead,
    467             boolean doUdpEncap,
    468             int sendCount,
    469             boolean useJavaSockets)
    470             throws Exception {
    471         StatsChecker.initStatsChecker();
    472         InetAddress local = InetAddress.getByName(localAddress);
    473 
    474         try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket();
    475                 IpSecManager.SecurityParameterIndex spi =
    476                         mISM.allocateSecurityParameterIndex(local)) {
    477 
    478             IpSecTransform.Builder transformBuilder = new IpSecTransform.Builder(mContext);
    479             if (crypt != null) {
    480                 transformBuilder.setEncryption(crypt);
    481             }
    482             if (auth != null) {
    483                 transformBuilder.setAuthentication(auth);
    484             }
    485             if (aead != null) {
    486                 transformBuilder.setAuthenticatedEncryption(aead);
    487             }
    488 
    489             if (doUdpEncap) {
    490                 transformBuilder =
    491                         transformBuilder.setIpv4Encapsulation(encapSocket, encapSocket.getPort());
    492             }
    493 
    494             int ipHdrLen = local instanceof Inet6Address ? IP6_HDRLEN : IP4_HDRLEN;
    495             int transportHdrLen = 0;
    496             int udpEncapLen = doUdpEncap ? UDP_HDRLEN : 0;
    497 
    498             try (IpSecTransform transform =
    499                         transformBuilder.buildTransportModeTransform(local, spi)) {
    500                 if (protocol == IPPROTO_TCP) {
    501                     transportHdrLen = TCP_HDRLEN_WITH_OPTIONS;
    502                     checkTcp(transform, local, sendCount, useJavaSockets);
    503                 } else if (protocol == IPPROTO_UDP) {
    504                     transportHdrLen = UDP_HDRLEN;
    505 
    506                     // TODO: Also check connected udp.
    507                     checkUnconnectedUdp(transform, local, sendCount, useJavaSockets);
    508                 } else {
    509                     throw new IllegalArgumentException("Invalid protocol");
    510                 }
    511             }
    512 
    513             checkStatsChecker(
    514                     protocol,
    515                     ipHdrLen,
    516                     transportHdrLen,
    517                     udpEncapLen,
    518                     sendCount,
    519                     getIvLen(crypt != null ? crypt : aead),
    520                     getBlkSize(crypt != null ? crypt : aead),
    521                     getTruncLenBits(auth != null ? auth : aead));
    522         }
    523     }
    524 
    525     private void checkStatsChecker(
    526             int protocol,
    527             int ipHdrLen,
    528             int transportHdrLen,
    529             int udpEncapLen,
    530             int sendCount,
    531             int ivLen,
    532             int blkSize,
    533             int truncLenBits)
    534             throws Exception {
    535 
    536         int innerPacketSize = TEST_DATA.length + transportHdrLen + ipHdrLen;
    537         int outerPacketSize =
    538                 calculateEspPacketSize(
    539                                 TEST_DATA.length + transportHdrLen, ivLen, blkSize, truncLenBits)
    540                         + udpEncapLen
    541                         + ipHdrLen;
    542 
    543         int expectedOuterBytes = outerPacketSize * sendCount;
    544         int expectedInnerBytes = innerPacketSize * sendCount;
    545         int expectedPackets = sendCount;
    546 
    547         // Each run sends two packets, one in each direction.
    548         sendCount *= 2;
    549         expectedOuterBytes *= 2;
    550         expectedInnerBytes *= 2;
    551         expectedPackets *= 2;
    552 
    553         // Add TCP ACKs for data packets
    554         if (protocol == IPPROTO_TCP) {
    555             int encryptedTcpPktSize =
    556                     calculateEspPacketSize(TCP_HDRLEN_WITH_OPTIONS, ivLen, blkSize, truncLenBits);
    557 
    558 
    559                 // Add data packet ACKs
    560                 expectedOuterBytes += (encryptedTcpPktSize + udpEncapLen + ipHdrLen) * (sendCount);
    561                 expectedInnerBytes += (TCP_HDRLEN_WITH_OPTIONS + ipHdrLen) * (sendCount);
    562                 expectedPackets += sendCount;
    563         }
    564 
    565         StatsChecker.waitForNumPackets(expectedPackets);
    566 
    567         // eBPF only counts inner packets, whereas xt_qtaguid counts outer packets. Allow both
    568         StatsChecker.assertUidStatsDelta(
    569                 expectedOuterBytes,
    570                 expectedPackets,
    571                 expectedInnerBytes,
    572                 expectedOuterBytes,
    573                 expectedPackets);
    574 
    575         // Unreliable at low numbers due to potential interference from other processes.
    576         if (sendCount >= 1000) {
    577             StatsChecker.assertIfaceStatsDelta(
    578                     expectedOuterBytes, expectedPackets, expectedOuterBytes, expectedPackets);
    579         }
    580     }
    581 
    582     private void checkIkePacket(
    583             NativeUdpSocket wrappedEncapSocket, InetAddress localAddr) throws Exception {
    584         StatsChecker.initStatsChecker();
    585 
    586         try (NativeUdpSocket remoteSocket = new NativeUdpSocket(getBoundUdpSocket(localAddr))) {
    587 
    588             // Append IKE/ESP header - 4 bytes of SPI, 4 bytes of seq number, all zeroed out
    589             // If the first four bytes are zero, assume non-ESP (IKE traffic)
    590             byte[] dataWithEspHeader = new byte[TEST_DATA.length + 8];
    591             System.arraycopy(TEST_DATA, 0, dataWithEspHeader, 8, TEST_DATA.length);
    592 
    593             // Send the IKE packet from remoteSocket to wrappedEncapSocket. Since IKE packets
    594             // are multiplexed over the socket, we expect them to appear on the encap socket
    595             // (as opposed to being decrypted and received on the non-encap socket)
    596             remoteSocket.sendTo(dataWithEspHeader, localAddr, wrappedEncapSocket.getPort());
    597             byte[] in = wrappedEncapSocket.receive();
    598             assertArrayEquals("Encapsulated data did not match.", dataWithEspHeader, in);
    599 
    600             // Also test that the IKE socket can send data out.
    601             wrappedEncapSocket.sendTo(dataWithEspHeader, localAddr, remoteSocket.getPort());
    602             in = remoteSocket.receive();
    603             assertArrayEquals("Encapsulated data did not match.", dataWithEspHeader, in);
    604 
    605             // Calculate expected packet sizes. Always use IPv4 header, since our kernels only
    606             // guarantee support of UDP encap on IPv4.
    607             int expectedNumPkts = 2;
    608             int expectedPacketSize =
    609                     expectedNumPkts * (dataWithEspHeader.length + UDP_HDRLEN + IP4_HDRLEN);
    610 
    611             StatsChecker.waitForNumPackets(expectedNumPkts);
    612             StatsChecker.assertUidStatsDelta(
    613                     expectedPacketSize,
    614                     expectedNumPkts,
    615                     expectedPacketSize,
    616                     expectedPacketSize,
    617                     expectedNumPkts);
    618             StatsChecker.assertIfaceStatsDelta(
    619                     expectedPacketSize, expectedNumPkts, expectedPacketSize, expectedNumPkts);
    620         }
    621     }
    622 
    623     public void testIkeOverUdpEncapSocket() throws Exception {
    624         // IPv6 not supported for UDP-encap-ESP
    625         InetAddress local = InetAddress.getByName(IPV4_LOOPBACK);
    626         try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
    627             NativeUdpSocket wrappedEncapSocket =
    628                     new NativeUdpSocket(encapSocket.getFileDescriptor());
    629             checkIkePacket(wrappedEncapSocket, local);
    630 
    631             // Now try with a transform applied to a socket using this Encap socket
    632             IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    633             IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
    634 
    635             try (IpSecManager.SecurityParameterIndex spi =
    636                             mISM.allocateSecurityParameterIndex(local);
    637                     IpSecTransform transform =
    638                             new IpSecTransform.Builder(mContext)
    639                                     .setEncryption(crypt)
    640                                     .setAuthentication(auth)
    641                                     .setIpv4Encapsulation(encapSocket, encapSocket.getPort())
    642                                     .buildTransportModeTransform(local, spi);
    643                     JavaUdpSocket localSocket = new JavaUdpSocket(local)) {
    644                 applyTransformBidirectionally(mISM, transform, localSocket);
    645 
    646                 checkIkePacket(wrappedEncapSocket, local);
    647             }
    648         }
    649     }
    650 
    651     // TODO: Check IKE over ESP sockets (IPv4, IPv6) - does this need SOCK_RAW?
    652 
    653     /* TODO: Re-enable these when policy matcher works for reflected packets
    654      *
    655      * The issue here is that A sends to B, and everything is new; therefore PREROUTING counts
    656      * correctly. But it appears that the security path is not cleared afterwards, thus when A
    657      * sends an ACK back to B, the policy matcher flags it as a "IPSec" packet. See b/70635417
    658      */
    659 
    660     // public void testInterfaceCountersTcp4() throws Exception {
    661     //     IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    662     //     IpSecAlgorithm auth = new IpSecAlgorithm(
    663     //             IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
    664     //     checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, false, 1000);
    665     // }
    666 
    667     // public void testInterfaceCountersTcp6() throws Exception {
    668     //     IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    669     //     IpSecAlgorithm auth = new IpSecAlgorithm(
    670     //             IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
    671     //     checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, false, 1000);
    672     // }
    673 
    674     // public void testInterfaceCountersTcp4UdpEncap() throws Exception {
    675     //     IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    676     //     IpSecAlgorithm auth =
    677     //             new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
    678     //     checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, true, 1000);
    679     // }
    680 
    681     public void testInterfaceCountersUdp4() throws Exception {
    682         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    683         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
    684         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1000, false);
    685     }
    686 
    687     public void testInterfaceCountersUdp6() throws Exception {
    688         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    689         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
    690         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1000, false);
    691     }
    692 
    693     public void testInterfaceCountersUdp4UdpEncap() throws Exception {
    694         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    695         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
    696         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1000, false);
    697     }
    698 
    699     public void testAesCbcHmacMd5Tcp4() throws Exception {
    700         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    701         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
    702         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
    703         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
    704     }
    705 
    706     public void testAesCbcHmacMd5Tcp6() throws Exception {
    707         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    708         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
    709         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
    710         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
    711     }
    712 
    713     public void testAesCbcHmacMd5Udp4() throws Exception {
    714         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    715         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
    716         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
    717         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
    718     }
    719 
    720     public void testAesCbcHmacMd5Udp6() throws Exception {
    721         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    722         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
    723         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
    724         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
    725     }
    726 
    727     public void testAesCbcHmacSha1Tcp4() throws Exception {
    728         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    729         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
    730         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
    731         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
    732     }
    733 
    734     public void testAesCbcHmacSha1Tcp6() throws Exception {
    735         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    736         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
    737         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
    738         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
    739     }
    740 
    741     public void testAesCbcHmacSha1Udp4() throws Exception {
    742         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    743         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
    744         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
    745         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
    746     }
    747 
    748     public void testAesCbcHmacSha1Udp6() throws Exception {
    749         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    750         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
    751         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
    752         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
    753     }
    754 
    755     public void testAesCbcHmacSha256Tcp4() throws Exception {
    756         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    757         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
    758         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
    759         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
    760     }
    761 
    762     public void testAesCbcHmacSha256Tcp6() throws Exception {
    763         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    764         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
    765         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
    766         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
    767     }
    768 
    769     public void testAesCbcHmacSha256Udp4() throws Exception {
    770         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    771         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
    772         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
    773         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
    774     }
    775 
    776     public void testAesCbcHmacSha256Udp6() throws Exception {
    777         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    778         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
    779         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
    780         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
    781     }
    782 
    783     public void testAesCbcHmacSha384Tcp4() throws Exception {
    784         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    785         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
    786         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
    787         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
    788     }
    789 
    790     public void testAesCbcHmacSha384Tcp6() throws Exception {
    791         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    792         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
    793         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
    794         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
    795     }
    796 
    797     public void testAesCbcHmacSha384Udp4() throws Exception {
    798         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    799         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
    800         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
    801         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
    802     }
    803 
    804     public void testAesCbcHmacSha384Udp6() throws Exception {
    805         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    806         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
    807         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
    808         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
    809     }
    810 
    811     public void testAesCbcHmacSha512Tcp4() throws Exception {
    812         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    813         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
    814         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
    815         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
    816     }
    817 
    818     public void testAesCbcHmacSha512Tcp6() throws Exception {
    819         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    820         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
    821         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
    822         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
    823     }
    824 
    825     public void testAesCbcHmacSha512Udp4() throws Exception {
    826         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    827         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
    828         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
    829         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
    830     }
    831 
    832     public void testAesCbcHmacSha512Udp6() throws Exception {
    833         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    834         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
    835         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
    836         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
    837     }
    838 
    839     public void testAesGcm64Tcp4() throws Exception {
    840         IpSecAlgorithm authCrypt =
    841                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
    842         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
    843         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
    844     }
    845 
    846     public void testAesGcm64Tcp6() throws Exception {
    847         IpSecAlgorithm authCrypt =
    848                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
    849         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
    850         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
    851     }
    852 
    853     public void testAesGcm64Udp4() throws Exception {
    854         IpSecAlgorithm authCrypt =
    855                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
    856         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
    857         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
    858     }
    859 
    860     public void testAesGcm64Udp6() throws Exception {
    861         IpSecAlgorithm authCrypt =
    862                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
    863         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
    864         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
    865     }
    866 
    867     public void testAesGcm96Tcp4() throws Exception {
    868         IpSecAlgorithm authCrypt =
    869                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
    870         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
    871         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
    872     }
    873 
    874     public void testAesGcm96Tcp6() throws Exception {
    875         IpSecAlgorithm authCrypt =
    876                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
    877         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
    878         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
    879     }
    880 
    881     public void testAesGcm96Udp4() throws Exception {
    882         IpSecAlgorithm authCrypt =
    883                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
    884         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
    885         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
    886     }
    887 
    888     public void testAesGcm96Udp6() throws Exception {
    889         IpSecAlgorithm authCrypt =
    890                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
    891         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
    892         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
    893     }
    894 
    895     public void testAesGcm128Tcp4() throws Exception {
    896         IpSecAlgorithm authCrypt =
    897                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
    898         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
    899         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
    900     }
    901 
    902     public void testAesGcm128Tcp6() throws Exception {
    903         IpSecAlgorithm authCrypt =
    904                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
    905         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
    906         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
    907     }
    908 
    909     public void testAesGcm128Udp4() throws Exception {
    910         IpSecAlgorithm authCrypt =
    911                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
    912         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
    913         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
    914     }
    915 
    916     public void testAesGcm128Udp6() throws Exception {
    917         IpSecAlgorithm authCrypt =
    918                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
    919         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
    920         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
    921     }
    922 
    923     public void testAesCbcHmacMd5Tcp4UdpEncap() throws Exception {
    924         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    925         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
    926         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
    927         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
    928     }
    929 
    930     public void testAesCbcHmacMd5Udp4UdpEncap() throws Exception {
    931         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    932         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
    933         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
    934         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
    935     }
    936 
    937     public void testAesCbcHmacSha1Tcp4UdpEncap() throws Exception {
    938         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    939         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
    940         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
    941         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
    942     }
    943 
    944     public void testAesCbcHmacSha1Udp4UdpEncap() throws Exception {
    945         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    946         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
    947         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
    948         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
    949     }
    950 
    951     public void testAesCbcHmacSha256Tcp4UdpEncap() throws Exception {
    952         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    953         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
    954         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
    955         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
    956     }
    957 
    958     public void testAesCbcHmacSha256Udp4UdpEncap() throws Exception {
    959         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    960         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
    961         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
    962         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
    963     }
    964 
    965     public void testAesCbcHmacSha384Tcp4UdpEncap() throws Exception {
    966         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    967         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
    968         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
    969         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
    970     }
    971 
    972     public void testAesCbcHmacSha384Udp4UdpEncap() throws Exception {
    973         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    974         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
    975         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
    976         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
    977     }
    978 
    979     public void testAesCbcHmacSha512Tcp4UdpEncap() throws Exception {
    980         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    981         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
    982         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
    983         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
    984     }
    985 
    986     public void testAesCbcHmacSha512Udp4UdpEncap() throws Exception {
    987         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
    988         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
    989         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
    990         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
    991     }
    992 
    993     public void testAesGcm64Tcp4UdpEncap() throws Exception {
    994         IpSecAlgorithm authCrypt =
    995                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
    996         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
    997         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
    998     }
    999 
   1000     public void testAesGcm64Udp4UdpEncap() throws Exception {
   1001         IpSecAlgorithm authCrypt =
   1002                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
   1003         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
   1004         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
   1005     }
   1006 
   1007     public void testAesGcm96Tcp4UdpEncap() throws Exception {
   1008         IpSecAlgorithm authCrypt =
   1009                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
   1010         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
   1011         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
   1012     }
   1013 
   1014     public void testAesGcm96Udp4UdpEncap() throws Exception {
   1015         IpSecAlgorithm authCrypt =
   1016                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
   1017         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
   1018         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
   1019     }
   1020 
   1021     public void testAesGcm128Tcp4UdpEncap() throws Exception {
   1022         IpSecAlgorithm authCrypt =
   1023                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
   1024         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
   1025         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
   1026     }
   1027 
   1028     public void testAesGcm128Udp4UdpEncap() throws Exception {
   1029         IpSecAlgorithm authCrypt =
   1030                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
   1031         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
   1032         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
   1033     }
   1034 
   1035     public void testCryptUdp4() throws Exception {
   1036         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
   1037         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, false, 1, false);
   1038         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, false, 1, true);
   1039     }
   1040 
   1041     public void testAuthUdp4() throws Exception {
   1042         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
   1043         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, false, 1, false);
   1044         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, false, 1, true);
   1045     }
   1046 
   1047     public void testCryptUdp6() throws Exception {
   1048         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
   1049         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, null, null, false, 1, false);
   1050         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, null, null, false, 1, true);
   1051     }
   1052 
   1053     public void testAuthUdp6() throws Exception {
   1054         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
   1055         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, auth, null, false, 1, false);
   1056         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, auth, null, false, 1, true);
   1057     }
   1058 
   1059     public void testCryptTcp4() throws Exception {
   1060         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
   1061         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, false, 1, false);
   1062         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, false, 1, true);
   1063     }
   1064 
   1065     public void testAuthTcp4() throws Exception {
   1066         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
   1067         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, false, 1, false);
   1068         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, false, 1, true);
   1069     }
   1070 
   1071     public void testCryptTcp6() throws Exception {
   1072         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
   1073         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, null, null, false, 1, false);
   1074         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, null, null, false, 1, true);
   1075     }
   1076 
   1077     public void testAuthTcp6() throws Exception {
   1078         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
   1079         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, auth, null, false, 1, false);
   1080         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, auth, null, false, 1, true);
   1081     }
   1082 
   1083     public void testCryptUdp4UdpEncap() throws Exception {
   1084         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
   1085         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, true, 1, false);
   1086         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, true, 1, true);
   1087     }
   1088 
   1089     public void testAuthUdp4UdpEncap() throws Exception {
   1090         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
   1091         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, true, 1, false);
   1092         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, true, 1, true);
   1093     }
   1094 
   1095     public void testCryptTcp4UdpEncap() throws Exception {
   1096         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
   1097         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, true, 1, false);
   1098         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, true, 1, true);
   1099     }
   1100 
   1101     public void testAuthTcp4UdpEncap() throws Exception {
   1102         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
   1103         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, true, 1, false);
   1104         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, true, 1, true);
   1105     }
   1106 
   1107     public void testOpenUdpEncapSocketSpecificPort() throws Exception {
   1108         IpSecManager.UdpEncapsulationSocket encapSocket = null;
   1109         int port = -1;
   1110         for (int i = 0; i < MAX_PORT_BIND_ATTEMPTS; i++) {
   1111             try {
   1112                 port = findUnusedPort();
   1113                 encapSocket = mISM.openUdpEncapsulationSocket(port);
   1114                 break;
   1115             } catch (ErrnoException e) {
   1116                 if (e.errno == OsConstants.EADDRINUSE) {
   1117                     // Someone claimed the port since we called findUnusedPort.
   1118                     continue;
   1119                 }
   1120                 throw e;
   1121             } finally {
   1122                 if (encapSocket != null) {
   1123                     encapSocket.close();
   1124                 }
   1125             }
   1126         }
   1127 
   1128         if (encapSocket == null) {
   1129             fail("Failed " + MAX_PORT_BIND_ATTEMPTS + " attempts to bind to a port");
   1130         }
   1131 
   1132         assertTrue("Returned invalid port", encapSocket.getPort() == port);
   1133     }
   1134 
   1135     public void testOpenUdpEncapSocketRandomPort() throws Exception {
   1136         try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
   1137             assertTrue("Returned invalid port", encapSocket.getPort() != 0);
   1138         }
   1139     }
   1140 }
   1141