• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.net.IpSecAlgorithm.AUTH_AES_CMAC;
20 import static android.net.IpSecAlgorithm.AUTH_AES_XCBC;
21 import static android.net.IpSecAlgorithm.AUTH_CRYPT_AES_GCM;
22 import static android.net.IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305;
23 import static android.net.IpSecAlgorithm.AUTH_HMAC_MD5;
24 import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA1;
25 import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA256;
26 import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA384;
27 import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512;
28 import static android.net.IpSecAlgorithm.CRYPT_AES_CBC;
29 import static android.net.IpSecAlgorithm.CRYPT_AES_CTR;
30 import static android.net.cts.PacketUtils.AES_CBC_BLK_SIZE;
31 import static android.net.cts.PacketUtils.AES_CBC_IV_LEN;
32 import static android.net.cts.PacketUtils.AES_CMAC_ICV_LEN;
33 import static android.net.cts.PacketUtils.AES_CMAC_KEY_LEN;
34 import static android.net.cts.PacketUtils.AES_CTR_BLK_SIZE;
35 import static android.net.cts.PacketUtils.AES_CTR_IV_LEN;
36 import static android.net.cts.PacketUtils.AES_CTR_KEY_LEN_20;
37 import static android.net.cts.PacketUtils.AES_GCM_BLK_SIZE;
38 import static android.net.cts.PacketUtils.AES_GCM_IV_LEN;
39 import static android.net.cts.PacketUtils.AES_XCBC_ICV_LEN;
40 import static android.net.cts.PacketUtils.AES_XCBC_KEY_LEN;
41 import static android.net.cts.PacketUtils.CHACHA20_POLY1305_BLK_SIZE;
42 import static android.net.cts.PacketUtils.CHACHA20_POLY1305_ICV_LEN;
43 import static android.net.cts.PacketUtils.CHACHA20_POLY1305_IV_LEN;
44 import static android.net.cts.PacketUtils.HMAC_SHA512_ICV_LEN;
45 import static android.net.cts.PacketUtils.HMAC_SHA512_KEY_LEN;
46 import static android.net.cts.PacketUtils.IP4_HDRLEN;
47 import static android.net.cts.PacketUtils.IP6_HDRLEN;
48 import static android.net.cts.PacketUtils.TCP_HDRLEN_WITH_TIMESTAMP_OPT;
49 import static android.net.cts.PacketUtils.UDP_HDRLEN;
50 import static android.system.OsConstants.IPPROTO_TCP;
51 import static android.system.OsConstants.IPPROTO_UDP;
52 
53 import static com.android.compatibility.common.util.PropertyUtil.getFirstApiLevel;
54 import static com.android.compatibility.common.util.PropertyUtil.getVendorApiLevel;
55 import static com.android.testutils.MiscAsserts.assertThrows;
56 
57 import static org.junit.Assert.assertArrayEquals;
58 import static org.junit.Assert.assertEquals;
59 import static org.junit.Assert.assertTrue;
60 import static org.junit.Assert.fail;
61 import static org.junit.Assume.assumeTrue;
62 
63 import android.net.IpSecAlgorithm;
64 import android.net.IpSecManager;
65 import android.net.IpSecTransform;
66 import android.net.TrafficStats;
67 import android.os.Build;
68 import android.platform.test.annotations.AppModeFull;
69 import android.system.ErrnoException;
70 import android.system.Os;
71 import android.system.OsConstants;
72 
73 import androidx.test.InstrumentationRegistry;
74 import androidx.test.runner.AndroidJUnit4;
75 
76 import com.android.testutils.DevSdkIgnoreRule;
77 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
78 
79 import org.junit.Rule;
80 import org.junit.Test;
81 import org.junit.runner.RunWith;
82 
83 import java.io.FileDescriptor;
84 import java.io.IOException;
85 import java.net.DatagramPacket;
86 import java.net.DatagramSocket;
87 import java.net.Inet6Address;
88 import java.net.InetAddress;
89 import java.util.Arrays;
90 import java.util.HashMap;
91 import java.util.Map;
92 import java.util.Map.Entry;
93 import java.util.Set;
94 
95 @RunWith(AndroidJUnit4.class)
96 @AppModeFull(reason = "Socket cannot bind in instant app mode")
97 public class IpSecManagerTest extends IpSecBaseTest {
98     @Rule public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
99 
100     private static final String TAG = IpSecManagerTest.class.getSimpleName();
101 
102     private static final InetAddress GOOGLE_DNS_4 = InetAddress.parseNumericAddress("8.8.8.8");
103     private static final InetAddress GOOGLE_DNS_6 =
104             InetAddress.parseNumericAddress("2001:4860:4860::8888");
105 
106     private static final InetAddress[] GOOGLE_DNS_LIST =
107             new InetAddress[] {GOOGLE_DNS_4, GOOGLE_DNS_6};
108 
109     private static final int DROID_SPI = 0xD1201D;
110     private static final int MAX_PORT_BIND_ATTEMPTS = 10;
111 
112     private static final byte[] AEAD_KEY = getKey(288);
113 
114     /*
115      * Allocate a random SPI
116      * Allocate a specific SPI using previous randomly created SPI value
117      * Realloc the same SPI that was specifically created (expect SpiUnavailable)
118      * Close SPIs
119      */
120     @Test
testAllocSpi()121     public void testAllocSpi() throws Exception {
122         for (InetAddress addr : GOOGLE_DNS_LIST) {
123             IpSecManager.SecurityParameterIndex randomSpi = null, droidSpi = null;
124             randomSpi = mISM.allocateSecurityParameterIndex(addr);
125             assertTrue(
126                     "Failed to receive a valid SPI",
127                     randomSpi.getSpi() != IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
128 
129             droidSpi = mISM.allocateSecurityParameterIndex(addr, DROID_SPI);
130             assertTrue("Failed to allocate specified SPI, " + DROID_SPI,
131                     droidSpi.getSpi() == DROID_SPI);
132 
133             IpSecManager.SpiUnavailableException expectedException =
134                     assertThrows("Duplicate SPI was allowed to be created",
135                             IpSecManager.SpiUnavailableException.class,
136                             () -> mISM.allocateSecurityParameterIndex(addr, DROID_SPI));
137             assertEquals(expectedException.getSpi(), droidSpi.getSpi());
138 
139             randomSpi.close();
140             droidSpi.close();
141         }
142     }
143 
144     /** This function finds an available port */
findUnusedPort()145     private static int findUnusedPort() throws Exception {
146         // Get an available port.
147         DatagramSocket s = new DatagramSocket();
148         int port = s.getLocalPort();
149         s.close();
150         return port;
151     }
152 
getBoundUdpSocket(InetAddress address)153     private static FileDescriptor getBoundUdpSocket(InetAddress address) throws Exception {
154         FileDescriptor sock =
155                 Os.socket(getDomain(address), OsConstants.SOCK_DGRAM, OsConstants.IPPROTO_UDP);
156 
157         for (int i = 0; i < MAX_PORT_BIND_ATTEMPTS; i++) {
158             try {
159                 int port = findUnusedPort();
160                 Os.bind(sock, address, port);
161                 break;
162             } catch (ErrnoException e) {
163                 // Someone claimed the port since we called findUnusedPort.
164                 if (e.errno == OsConstants.EADDRINUSE) {
165                     if (i == MAX_PORT_BIND_ATTEMPTS - 1) {
166 
167                         fail("Failed " + MAX_PORT_BIND_ATTEMPTS + " attempts to bind to a port");
168                     }
169                     continue;
170                 }
171                 throw e.rethrowAsIOException();
172             }
173         }
174         return sock;
175     }
176 
checkUnconnectedUdp(IpSecTransform transform, InetAddress local, int sendCount, boolean useJavaSockets)177     private void checkUnconnectedUdp(IpSecTransform transform, InetAddress local, int sendCount,
178                                      boolean useJavaSockets) throws Exception {
179         GenericUdpSocket sockLeft = null, sockRight = null;
180         if (useJavaSockets) {
181             SocketPair<JavaUdpSocket> sockets = getJavaUdpSocketPair(local, mISM, transform, false);
182             sockLeft = sockets.mLeftSock;
183             sockRight = sockets.mRightSock;
184         } else {
185             SocketPair<NativeUdpSocket> sockets =
186                     getNativeUdpSocketPair(local, mISM, transform, false);
187             sockLeft = sockets.mLeftSock;
188             sockRight = sockets.mRightSock;
189         }
190 
191         for (int i = 0; i < sendCount; i++) {
192             byte[] in;
193 
194             sockLeft.sendTo(TEST_DATA, local, sockRight.getPort());
195             in = sockRight.receive();
196             assertArrayEquals("Left-to-right encrypted data did not match.", TEST_DATA, in);
197 
198             sockRight.sendTo(TEST_DATA, local, sockLeft.getPort());
199             in = sockLeft.receive();
200             assertArrayEquals("Right-to-left encrypted data did not match.", TEST_DATA, in);
201         }
202 
203         sockLeft.close();
204         sockRight.close();
205     }
206 
checkTcp(IpSecTransform transform, InetAddress local, int sendCount, boolean useJavaSockets)207     private void checkTcp(IpSecTransform transform, InetAddress local, int sendCount,
208                           boolean useJavaSockets) throws Exception {
209         GenericTcpSocket client = null, accepted = null;
210         if (useJavaSockets) {
211             SocketPair<JavaTcpSocket> sockets = getJavaTcpSocketPair(local, mISM, transform);
212             client = sockets.mLeftSock;
213             accepted = sockets.mRightSock;
214         } else {
215             SocketPair<NativeTcpSocket> sockets = getNativeTcpSocketPair(local, mISM, transform);
216             client = sockets.mLeftSock;
217             accepted = sockets.mRightSock;
218         }
219 
220         // Wait for TCP handshake packets to be counted
221         StatsChecker.waitForNumPackets(3); // (SYN, SYN+ACK, ACK)
222 
223         // Reset StatsChecker, to ignore negotiation overhead.
224         StatsChecker.initStatsChecker();
225         for (int i = 0; i < sendCount; i++) {
226             byte[] in;
227 
228             client.send(TEST_DATA);
229             in = accepted.receive();
230             assertArrayEquals("Client-to-server encrypted data did not match.", TEST_DATA, in);
231 
232             // Allow for newest data + ack packets to be returned before sending next packet
233             // Also add the number of expected packets in each of the previous runs (4 per run)
234             StatsChecker.waitForNumPackets(2 + (4 * i));
235 
236             accepted.send(TEST_DATA);
237             in = client.receive();
238             assertArrayEquals("Server-to-client encrypted data did not match.", TEST_DATA, in);
239 
240             // Allow for all data + ack packets to be returned before sending next packet
241             // Also add the number of expected packets in each of the previous runs (4 per run)
242             StatsChecker.waitForNumPackets(4 * (i + 1));
243         }
244 
245         // Transforms should not be removed from the sockets, otherwise FIN packets will be sent
246         //     unencrypted.
247         // This test also unfortunately happens to rely on a nuance of the cleanup order. By
248         //     keeping the policy on the socket, but removing the SA before lingering FIN packets
249         //     are sent (at an undetermined later time), the FIN packets are dropped. Without this,
250         //     we run into all kinds of headaches trying to test data accounting (unsolicited
251         //     packets mysteriously appearing and messing up our counters)
252         // The right way to close sockets is to set SO_LINGER to ensure synchronous closure,
253         //     closing the sockets, and then closing the transforms. See documentation for the
254         //     Socket or FileDescriptor flavors of applyTransportModeTransform() in IpSecManager
255         //     for more details.
256 
257         client.close();
258         accepted.close();
259     }
260 
261     /*
262      * Alloc outbound SPI
263      * Alloc inbound SPI
264      * Create transport mode transform
265      * open socket
266      * apply transform to socket
267      * send data on socket
268      * release transform
269      * send data (expect exception)
270      */
271     @Test
testCreateTransform()272     public void testCreateTransform() throws Exception {
273         InetAddress localAddr = InetAddress.getByName(IPV4_LOOPBACK);
274         IpSecManager.SecurityParameterIndex spi =
275                 mISM.allocateSecurityParameterIndex(localAddr);
276 
277         IpSecTransform transform =
278                 new IpSecTransform.Builder(InstrumentationRegistry.getContext())
279                         .setEncryption(new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
280                         .setAuthentication(
281                                 new IpSecAlgorithm(
282                                         IpSecAlgorithm.AUTH_HMAC_SHA256,
283                                         AUTH_KEY,
284                                         AUTH_KEY.length * 8))
285                         .buildTransportModeTransform(localAddr, spi);
286 
287         final boolean [][] applyInApplyOut = {
288                 {false, false}, {false, true}, {true, false}, {true,true}};
289         final byte[] data = new String("Best test data ever!").getBytes("UTF-8");
290         final DatagramPacket outPacket = new DatagramPacket(data, 0, data.length, localAddr, 0);
291 
292         byte[] in = new byte[data.length];
293         DatagramPacket inPacket = new DatagramPacket(in, in.length);
294         DatagramSocket localSocket;
295         int localPort;
296 
297         for(boolean[] io : applyInApplyOut) {
298             boolean applyIn = io[0];
299             boolean applyOut = io[1];
300             // Bind localSocket to a random available port.
301             localSocket = new DatagramSocket(0);
302             localPort = localSocket.getLocalPort();
303             localSocket.setSoTimeout(200);
304             outPacket.setPort(localPort);
305             if (applyIn) {
306                 mISM.applyTransportModeTransform(
307                         localSocket, IpSecManager.DIRECTION_IN, transform);
308             }
309             if (applyOut) {
310                 mISM.applyTransportModeTransform(
311                         localSocket, IpSecManager.DIRECTION_OUT, transform);
312             }
313             if (applyIn == applyOut) {
314                 localSocket.send(outPacket);
315                 localSocket.receive(inPacket);
316                 assertTrue("Encapsulated data did not match.",
317                         Arrays.equals(outPacket.getData(), inPacket.getData()));
318                 mISM.removeTransportModeTransforms(localSocket);
319                 localSocket.close();
320             } else {
321                 try {
322                     localSocket.send(outPacket);
323                     localSocket.receive(inPacket);
324                 } catch (IOException e) {
325                     continue;
326                 } finally {
327                     mISM.removeTransportModeTransforms(localSocket);
328                     localSocket.close();
329                 }
330                 // FIXME: This check is disabled because sockets currently receive data
331                 // if there is a valid SA for decryption, even when the input policy is
332                 // not applied to a socket.
333                 //  fail("Data IO should fail on asymmetrical transforms! + Input="
334                 //          + applyIn + " Output=" + applyOut);
335             }
336         }
337         transform.close();
338     }
339 
340     /** Snapshot of TrafficStats as of initStatsChecker call for later comparisons */
341     private static class StatsChecker {
342         private static final double ERROR_MARGIN_BYTES = 1.05;
343         private static final double ERROR_MARGIN_PKTS = 1.05;
344         private static final int MAX_WAIT_TIME_MILLIS = 1000;
345 
346         private static long uidTxBytes;
347         private static long uidRxBytes;
348         private static long uidTxPackets;
349         private static long uidRxPackets;
350 
351         private static long ifaceTxBytes;
352         private static long ifaceRxBytes;
353         private static long ifaceTxPackets;
354         private static long ifaceRxPackets;
355 
356         /**
357          * This method counts the number of incoming packets, polling intermittently up to
358          * MAX_WAIT_TIME_MILLIS.
359          */
waitForNumPackets(int numPackets)360         private static void waitForNumPackets(int numPackets) throws Exception {
361             long uidTxDelta = 0;
362             long uidRxDelta = 0;
363             for (int i = 0; i < 100; i++) {
364                 uidTxDelta = TrafficStats.getUidTxPackets(Os.getuid()) - uidTxPackets;
365                 uidRxDelta = TrafficStats.getUidRxPackets(Os.getuid()) - uidRxPackets;
366 
367                 // TODO: Check Rx packets as well once kernel security policy bug is fixed.
368                 // (b/70635417)
369                 if (uidTxDelta >= numPackets) {
370                     return;
371                 }
372                 Thread.sleep(MAX_WAIT_TIME_MILLIS / 100);
373             }
374             fail(
375                     "Not enough traffic was recorded to satisfy the provided conditions: wanted "
376                             + numPackets
377                             + ", got "
378                             + uidTxDelta
379                             + " tx and "
380                             + uidRxDelta
381                             + " rx packets");
382         }
383 
assertUidStatsDelta( int expectedTxByteDelta, int expectedTxPacketDelta, int minRxByteDelta, int maxRxByteDelta, int expectedRxPacketDelta)384         private static void assertUidStatsDelta(
385                 int expectedTxByteDelta,
386                 int expectedTxPacketDelta,
387                 int minRxByteDelta,
388                 int maxRxByteDelta,
389                 int expectedRxPacketDelta) {
390             long newUidTxBytes = TrafficStats.getUidTxBytes(Os.getuid());
391             long newUidRxBytes = TrafficStats.getUidRxBytes(Os.getuid());
392             long newUidTxPackets = TrafficStats.getUidTxPackets(Os.getuid());
393             long newUidRxPackets = TrafficStats.getUidRxPackets(Os.getuid());
394 
395             assertEquals(expectedTxByteDelta, newUidTxBytes - uidTxBytes);
396             assertTrue(
397                     newUidRxBytes - uidRxBytes >= minRxByteDelta
398                             && newUidRxBytes - uidRxBytes <= maxRxByteDelta);
399             assertEquals(expectedTxPacketDelta, newUidTxPackets - uidTxPackets);
400             assertEquals(expectedRxPacketDelta, newUidRxPackets - uidRxPackets);
401         }
402 
assertIfaceStatsDelta( int expectedTxByteDelta, int expectedTxPacketDelta, int expectedRxByteDelta, int expectedRxPacketDelta)403         private static void assertIfaceStatsDelta(
404                 int expectedTxByteDelta,
405                 int expectedTxPacketDelta,
406                 int expectedRxByteDelta,
407                 int expectedRxPacketDelta)
408                 throws IOException {
409             long newIfaceTxBytes = TrafficStats.getLoopbackTxBytes();
410             long newIfaceRxBytes = TrafficStats.getLoopbackRxBytes();
411             long newIfaceTxPackets = TrafficStats.getLoopbackTxPackets();
412             long newIfaceRxPackets = TrafficStats.getLoopbackRxPackets();
413 
414             // Check that iface stats are within an acceptable range; data might be sent
415             // on the local interface by other apps.
416             assertApproxEquals("TX bytes", ifaceTxBytes, newIfaceTxBytes, expectedTxByteDelta,
417                     ERROR_MARGIN_BYTES);
418             assertApproxEquals("RX bytes", ifaceRxBytes, newIfaceRxBytes, expectedRxByteDelta,
419                     ERROR_MARGIN_BYTES);
420             assertApproxEquals("TX packets", ifaceTxPackets, newIfaceTxPackets,
421                     expectedTxPacketDelta, ERROR_MARGIN_PKTS);
422             assertApproxEquals("RX packets",  ifaceRxPackets, newIfaceRxPackets,
423                     expectedRxPacketDelta, ERROR_MARGIN_PKTS);
424         }
425 
assertApproxEquals( String what, long oldStats, long newStats, int expectedDelta, double errorMargin)426         private static void assertApproxEquals(
427                 String what, long oldStats, long newStats, int expectedDelta, double errorMargin) {
428             assertTrue(
429                     "Expected at least " + expectedDelta + " " + what
430                             + ", got "  + (newStats - oldStats),
431                     newStats - oldStats >= expectedDelta);
432             assertTrue(
433                     "Expected at most " + errorMargin + " * " + expectedDelta + " " + what
434                             + ", got " + (newStats - oldStats),
435                     newStats - oldStats < (expectedDelta * errorMargin));
436         }
437 
initStatsChecker()438         private static void initStatsChecker() throws Exception {
439             uidTxBytes = TrafficStats.getUidTxBytes(Os.getuid());
440             uidRxBytes = TrafficStats.getUidRxBytes(Os.getuid());
441             uidTxPackets = TrafficStats.getUidTxPackets(Os.getuid());
442             uidRxPackets = TrafficStats.getUidRxPackets(Os.getuid());
443 
444             ifaceTxBytes = TrafficStats.getLoopbackTxBytes();
445             ifaceRxBytes = TrafficStats.getLoopbackRxBytes();
446             ifaceTxPackets = TrafficStats.getLoopbackTxPackets();
447             ifaceRxPackets = TrafficStats.getLoopbackRxPackets();
448         }
449     }
450 
getTruncLenBits(IpSecAlgorithm authOrAead)451     private int getTruncLenBits(IpSecAlgorithm authOrAead) {
452         return authOrAead == null ? 0 : authOrAead.getTruncationLengthBits();
453     }
454 
getIvLen(IpSecAlgorithm cryptOrAead)455     private int getIvLen(IpSecAlgorithm cryptOrAead) {
456         if (cryptOrAead == null) { return 0; }
457 
458         switch (cryptOrAead.getName()) {
459             case IpSecAlgorithm.CRYPT_AES_CBC:
460                 return AES_CBC_IV_LEN;
461             case IpSecAlgorithm.CRYPT_AES_CTR:
462                 return AES_CTR_IV_LEN;
463             case IpSecAlgorithm.AUTH_CRYPT_AES_GCM:
464                 return AES_GCM_IV_LEN;
465             case IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305:
466                 return CHACHA20_POLY1305_IV_LEN;
467             default:
468                 throw new IllegalArgumentException(
469                         "IV length unknown for algorithm" + cryptOrAead.getName());
470         }
471     }
472 
getBlkSize(IpSecAlgorithm cryptOrAead)473     private int getBlkSize(IpSecAlgorithm cryptOrAead) {
474         // RFC 4303, section 2.4 states that ciphertext plus pad_len, next_header fields must
475         //     terminate on a 4-byte boundary. Thus, the minimum ciphertext block size is 4 bytes.
476         if (cryptOrAead == null) { return 4; }
477 
478         switch (cryptOrAead.getName()) {
479             case IpSecAlgorithm.CRYPT_AES_CBC:
480                 return AES_CBC_BLK_SIZE;
481             case IpSecAlgorithm.CRYPT_AES_CTR:
482                 return AES_CTR_BLK_SIZE;
483             case IpSecAlgorithm.AUTH_CRYPT_AES_GCM:
484                 return AES_GCM_BLK_SIZE;
485             case IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305:
486                 return CHACHA20_POLY1305_BLK_SIZE;
487             default:
488                 throw new IllegalArgumentException(
489                         "Blk size unknown for algorithm" + cryptOrAead.getName());
490         }
491     }
492 
checkTransform( int protocol, String localAddress, IpSecAlgorithm crypt, IpSecAlgorithm auth, IpSecAlgorithm aead, boolean doUdpEncap, int sendCount, boolean useJavaSockets)493     public void checkTransform(
494             int protocol,
495             String localAddress,
496             IpSecAlgorithm crypt,
497             IpSecAlgorithm auth,
498             IpSecAlgorithm aead,
499             boolean doUdpEncap,
500             int sendCount,
501             boolean useJavaSockets)
502             throws Exception {
503         StatsChecker.initStatsChecker();
504         InetAddress local = InetAddress.getByName(localAddress);
505 
506         try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket();
507                 IpSecManager.SecurityParameterIndex spi =
508                         mISM.allocateSecurityParameterIndex(local)) {
509 
510             IpSecTransform.Builder transformBuilder =
511                     new IpSecTransform.Builder(InstrumentationRegistry.getContext());
512             if (crypt != null) {
513                 transformBuilder.setEncryption(crypt);
514             }
515             if (auth != null) {
516                 transformBuilder.setAuthentication(auth);
517             }
518             if (aead != null) {
519                 transformBuilder.setAuthenticatedEncryption(aead);
520             }
521 
522             if (doUdpEncap) {
523                 transformBuilder =
524                         transformBuilder.setIpv4Encapsulation(encapSocket, encapSocket.getPort());
525             }
526 
527             int ipHdrLen = local instanceof Inet6Address ? IP6_HDRLEN : IP4_HDRLEN;
528             int transportHdrLen = 0;
529             int udpEncapLen = doUdpEncap ? UDP_HDRLEN : 0;
530 
531             try (IpSecTransform transform =
532                         transformBuilder.buildTransportModeTransform(local, spi)) {
533                 if (protocol == IPPROTO_TCP) {
534                     transportHdrLen = TCP_HDRLEN_WITH_TIMESTAMP_OPT;
535                     checkTcp(transform, local, sendCount, useJavaSockets);
536                 } else if (protocol == IPPROTO_UDP) {
537                     transportHdrLen = UDP_HDRLEN;
538 
539                     // TODO: Also check connected udp.
540                     checkUnconnectedUdp(transform, local, sendCount, useJavaSockets);
541                 } else {
542                     throw new IllegalArgumentException("Invalid protocol");
543                 }
544             }
545 
546             checkStatsChecker(
547                     protocol,
548                     ipHdrLen,
549                     transportHdrLen,
550                     udpEncapLen,
551                     sendCount,
552                     getIvLen(crypt != null ? crypt : aead),
553                     getBlkSize(crypt != null ? crypt : aead),
554                     getTruncLenBits(auth != null ? auth : aead));
555         }
556     }
557 
checkStatsChecker( int protocol, int ipHdrLen, int transportHdrLen, int udpEncapLen, int sendCount, int ivLen, int blkSize, int truncLenBits)558     private void checkStatsChecker(
559             int protocol,
560             int ipHdrLen,
561             int transportHdrLen,
562             int udpEncapLen,
563             int sendCount,
564             int ivLen,
565             int blkSize,
566             int truncLenBits)
567             throws Exception {
568         int innerPacketSize = TEST_DATA.length + transportHdrLen + ipHdrLen;
569         int outerPacketSize =
570                 PacketUtils.calculateEspPacketSize(
571                                 TEST_DATA.length + transportHdrLen, ivLen, blkSize, truncLenBits)
572                         + udpEncapLen
573                         + ipHdrLen;
574 
575         int expectedOuterBytes = outerPacketSize * sendCount;
576         int expectedInnerBytes = innerPacketSize * sendCount;
577         int expectedPackets = sendCount;
578 
579         // Each run sends two packets, one in each direction.
580         sendCount *= 2;
581         expectedOuterBytes *= 2;
582         expectedInnerBytes *= 2;
583         expectedPackets *= 2;
584 
585         // Add TCP ACKs for data packets
586         if (protocol == IPPROTO_TCP) {
587             int encryptedTcpPktSize =
588                     PacketUtils.calculateEspPacketSize(
589                             TCP_HDRLEN_WITH_TIMESTAMP_OPT, ivLen, blkSize, truncLenBits);
590 
591             // Add data packet ACKs
592             expectedOuterBytes += (encryptedTcpPktSize + udpEncapLen + ipHdrLen) * (sendCount);
593             expectedInnerBytes += (TCP_HDRLEN_WITH_TIMESTAMP_OPT + ipHdrLen) * (sendCount);
594             expectedPackets += sendCount;
595         }
596 
597         StatsChecker.waitForNumPackets(expectedPackets);
598 
599         // eBPF only counts inner packets, whereas xt_qtaguid counts outer packets. Allow both
600         StatsChecker.assertUidStatsDelta(
601                 expectedOuterBytes,
602                 expectedPackets,
603                 expectedInnerBytes,
604                 expectedOuterBytes,
605                 expectedPackets);
606 
607         // Unreliable at low numbers due to potential interference from other processes.
608         if (sendCount >= 1000) {
609             StatsChecker.assertIfaceStatsDelta(
610                     expectedOuterBytes, expectedPackets, expectedOuterBytes, expectedPackets);
611         }
612     }
613 
checkIkePacket( NativeUdpSocket wrappedEncapSocket, InetAddress localAddr)614     private void checkIkePacket(
615             NativeUdpSocket wrappedEncapSocket, InetAddress localAddr) throws Exception {
616         StatsChecker.initStatsChecker();
617 
618         try (NativeUdpSocket remoteSocket = new NativeUdpSocket(getBoundUdpSocket(localAddr))) {
619 
620             // Append IKE/ESP header - 4 bytes of SPI, 4 bytes of seq number, all zeroed out
621             // If the first four bytes are zero, assume non-ESP (IKE traffic)
622             byte[] dataWithEspHeader = new byte[TEST_DATA.length + 8];
623             System.arraycopy(TEST_DATA, 0, dataWithEspHeader, 8, TEST_DATA.length);
624 
625             // Send the IKE packet from remoteSocket to wrappedEncapSocket. Since IKE packets
626             // are multiplexed over the socket, we expect them to appear on the encap socket
627             // (as opposed to being decrypted and received on the non-encap socket)
628             remoteSocket.sendTo(dataWithEspHeader, localAddr, wrappedEncapSocket.getPort());
629             byte[] in = wrappedEncapSocket.receive();
630             assertArrayEquals("Encapsulated data did not match.", dataWithEspHeader, in);
631 
632             // Also test that the IKE socket can send data out.
633             wrappedEncapSocket.sendTo(dataWithEspHeader, localAddr, remoteSocket.getPort());
634             in = remoteSocket.receive();
635             assertArrayEquals("Encapsulated data did not match.", dataWithEspHeader, in);
636 
637             // Calculate expected packet sizes. Always use IPv4 header, since our kernels only
638             // guarantee support of UDP encap on IPv4.
639             int expectedNumPkts = 2;
640             int expectedPacketSize =
641                     expectedNumPkts * (dataWithEspHeader.length + UDP_HDRLEN + IP4_HDRLEN);
642 
643             StatsChecker.waitForNumPackets(expectedNumPkts);
644             StatsChecker.assertUidStatsDelta(
645                     expectedPacketSize,
646                     expectedNumPkts,
647                     expectedPacketSize,
648                     expectedPacketSize,
649                     expectedNumPkts);
650             StatsChecker.assertIfaceStatsDelta(
651                     expectedPacketSize, expectedNumPkts, expectedPacketSize, expectedNumPkts);
652         }
653     }
654 
655     @Test
testIkeOverUdpEncapSocket()656     public void testIkeOverUdpEncapSocket() throws Exception {
657         // IPv6 not supported for UDP-encap-ESP
658         InetAddress local = InetAddress.getByName(IPV4_LOOPBACK);
659         try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
660             NativeUdpSocket wrappedEncapSocket =
661                     new NativeUdpSocket(encapSocket.getFileDescriptor());
662             checkIkePacket(wrappedEncapSocket, local);
663 
664             // Now try with a transform applied to a socket using this Encap socket
665             IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
666             IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
667 
668             try (IpSecManager.SecurityParameterIndex spi =
669                             mISM.allocateSecurityParameterIndex(local);
670                     IpSecTransform transform =
671                             new IpSecTransform.Builder(InstrumentationRegistry.getContext())
672                                     .setEncryption(crypt)
673                                     .setAuthentication(auth)
674                                     .setIpv4Encapsulation(encapSocket, encapSocket.getPort())
675                                     .buildTransportModeTransform(local, spi);
676                     JavaUdpSocket localSocket = new JavaUdpSocket(local)) {
677                 applyTransformBidirectionally(mISM, transform, localSocket);
678 
679                 checkIkePacket(wrappedEncapSocket, local);
680             }
681         }
682     }
683 
684     // TODO: Check IKE over ESP sockets (IPv4, IPv6) - does this need SOCK_RAW?
685 
686     /* TODO: Re-enable these when policy matcher works for reflected packets
687      *
688      * The issue here is that A sends to B, and everything is new; therefore PREROUTING counts
689      * correctly. But it appears that the security path is not cleared afterwards, thus when A
690      * sends an ACK back to B, the policy matcher flags it as a "IPSec" packet. See b/70635417
691      */
692 
693     // public void testInterfaceCountersTcp4() throws Exception {
694     //     IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
695     //     IpSecAlgorithm auth = new IpSecAlgorithm(
696     //             IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
697     //     checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, false, 1000);
698     // }
699 
700     // public void testInterfaceCountersTcp6() throws Exception {
701     //     IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
702     //     IpSecAlgorithm auth = new IpSecAlgorithm(
703     //             IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
704     //     checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, false, 1000);
705     // }
706 
707     // public void testInterfaceCountersTcp4UdpEncap() throws Exception {
708     //     IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
709     //     IpSecAlgorithm auth =
710     //             new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
711     //     checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, true, 1000);
712     // }
713 
714     @IgnoreUpTo(Build.VERSION_CODES.R)
715     @Test
testGetSupportedAlgorithms()716     public void testGetSupportedAlgorithms() throws Exception {
717         final Map<String, Integer> algoToRequiredMinSdk = new HashMap<>();
718         algoToRequiredMinSdk.put(CRYPT_AES_CBC, Build.VERSION_CODES.P);
719         algoToRequiredMinSdk.put(AUTH_HMAC_MD5, Build.VERSION_CODES.P);
720         algoToRequiredMinSdk.put(AUTH_HMAC_SHA1, Build.VERSION_CODES.P);
721         algoToRequiredMinSdk.put(AUTH_HMAC_SHA256, Build.VERSION_CODES.P);
722         algoToRequiredMinSdk.put(AUTH_HMAC_SHA384, Build.VERSION_CODES.P);
723         algoToRequiredMinSdk.put(AUTH_HMAC_SHA512, Build.VERSION_CODES.P);
724         algoToRequiredMinSdk.put(AUTH_CRYPT_AES_GCM, Build.VERSION_CODES.P);
725 
726         algoToRequiredMinSdk.put(CRYPT_AES_CTR, Build.VERSION_CODES.S);
727         algoToRequiredMinSdk.put(AUTH_AES_CMAC, Build.VERSION_CODES.S);
728         algoToRequiredMinSdk.put(AUTH_AES_XCBC, Build.VERSION_CODES.S);
729         algoToRequiredMinSdk.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.S);
730 
731         final Set<String> supportedAlgos = IpSecAlgorithm.getSupportedAlgorithms();
732 
733         // Verify all supported algorithms are valid
734         for (String algo : supportedAlgos) {
735             assertTrue("Found invalid algo " + algo, algoToRequiredMinSdk.keySet().contains(algo));
736         }
737 
738         // Verify all mandatory algorithms are supported
739         for (Entry<String, Integer> entry : algoToRequiredMinSdk.entrySet()) {
740             if (Math.min(getFirstApiLevel(), getVendorApiLevel()) >= entry.getValue()) {
741                 assertTrue(
742                         "Fail to support " + entry.getKey(),
743                         supportedAlgos.contains(entry.getKey()));
744             }
745         }
746     }
747 
748     @Test
testInterfaceCountersUdp4()749     public void testInterfaceCountersUdp4() throws Exception {
750         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
751         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
752         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1000, false);
753     }
754 
755     @Test
testInterfaceCountersUdp6()756     public void testInterfaceCountersUdp6() throws Exception {
757         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
758         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
759         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1000, false);
760     }
761 
762     @Test
testInterfaceCountersUdp4UdpEncap()763     public void testInterfaceCountersUdp4UdpEncap() throws Exception {
764         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
765         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
766         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1000, false);
767     }
768 
769     @Test
testAesCbcHmacMd5Tcp4()770     public void testAesCbcHmacMd5Tcp4() throws Exception {
771         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
772         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
773         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
774         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
775     }
776 
777     @Test
testAesCbcHmacMd5Tcp6()778     public void testAesCbcHmacMd5Tcp6() throws Exception {
779         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
780         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
781         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
782         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
783     }
784 
785     @Test
testAesCbcHmacMd5Udp4()786     public void testAesCbcHmacMd5Udp4() throws Exception {
787         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
788         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
789         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
790         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
791     }
792 
793     @Test
testAesCbcHmacMd5Udp6()794     public void testAesCbcHmacMd5Udp6() throws Exception {
795         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
796         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
797         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
798         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
799     }
800 
801     @Test
testAesCbcHmacSha1Tcp4()802     public void testAesCbcHmacSha1Tcp4() throws Exception {
803         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
804         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
805         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
806         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
807     }
808 
809     @Test
testAesCbcHmacSha1Tcp6()810     public void testAesCbcHmacSha1Tcp6() throws Exception {
811         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
812         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
813         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
814         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
815     }
816 
817     @Test
testAesCbcHmacSha1Udp4()818     public void testAesCbcHmacSha1Udp4() throws Exception {
819         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
820         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
821         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
822         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
823     }
824 
825     @Test
testAesCbcHmacSha1Udp6()826     public void testAesCbcHmacSha1Udp6() throws Exception {
827         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
828         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
829         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
830         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
831     }
832 
833     @Test
testAesCbcHmacSha256Tcp4()834     public void testAesCbcHmacSha256Tcp4() throws Exception {
835         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
836         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
837         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
838         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
839     }
840 
841     @Test
testAesCbcHmacSha256Tcp6()842     public void testAesCbcHmacSha256Tcp6() throws Exception {
843         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
844         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
845         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
846         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
847     }
848 
849     @Test
testAesCbcHmacSha256Udp4()850     public void testAesCbcHmacSha256Udp4() throws Exception {
851         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
852         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
853         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
854         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
855     }
856 
857     @Test
testAesCbcHmacSha256Udp6()858     public void testAesCbcHmacSha256Udp6() throws Exception {
859         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
860         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
861         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
862         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
863     }
864 
865     @Test
testAesCbcHmacSha384Tcp4()866     public void testAesCbcHmacSha384Tcp4() throws Exception {
867         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
868         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
869         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
870         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
871     }
872 
873     @Test
testAesCbcHmacSha384Tcp6()874     public void testAesCbcHmacSha384Tcp6() throws Exception {
875         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
876         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
877         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
878         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
879     }
880 
881     @Test
testAesCbcHmacSha384Udp4()882     public void testAesCbcHmacSha384Udp4() throws Exception {
883         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
884         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
885         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
886         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
887     }
888 
889     @Test
testAesCbcHmacSha384Udp6()890     public void testAesCbcHmacSha384Udp6() throws Exception {
891         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
892         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
893         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
894         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
895     }
896 
897     @Test
testAesCbcHmacSha512Tcp4()898     public void testAesCbcHmacSha512Tcp4() throws Exception {
899         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
900         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
901         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
902         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
903     }
904 
905     @Test
testAesCbcHmacSha512Tcp6()906     public void testAesCbcHmacSha512Tcp6() throws Exception {
907         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
908         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
909         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
910         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
911     }
912 
913     @Test
testAesCbcHmacSha512Udp4()914     public void testAesCbcHmacSha512Udp4() throws Exception {
915         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
916         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
917         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
918         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
919     }
920 
921     @Test
testAesCbcHmacSha512Udp6()922     public void testAesCbcHmacSha512Udp6() throws Exception {
923         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
924         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
925         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
926         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
927     }
928 
buildCryptAesCtr()929     private static IpSecAlgorithm buildCryptAesCtr() throws Exception {
930         return new IpSecAlgorithm(CRYPT_AES_CTR, getKeyBytes(AES_CTR_KEY_LEN_20));
931     }
932 
buildAuthHmacSha512()933     private static IpSecAlgorithm buildAuthHmacSha512() throws Exception {
934         return new IpSecAlgorithm(
935                 AUTH_HMAC_SHA512, getKeyBytes(HMAC_SHA512_KEY_LEN), HMAC_SHA512_ICV_LEN * 8);
936     }
937 
938     @Test
testAesCtrHmacSha512Tcp4()939     public void testAesCtrHmacSha512Tcp4() throws Exception {
940         assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
941 
942         final IpSecAlgorithm crypt = buildCryptAesCtr();
943         final IpSecAlgorithm auth = buildAuthHmacSha512();
944         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
945         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
946     }
947 
948     @Test
testAesCtrHmacSha512Tcp6()949     public void testAesCtrHmacSha512Tcp6() throws Exception {
950         assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
951 
952         final IpSecAlgorithm crypt = buildCryptAesCtr();
953         final IpSecAlgorithm auth = buildAuthHmacSha512();
954         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
955         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
956     }
957 
958     @Test
testAesCtrHmacSha512Udp4()959     public void testAesCtrHmacSha512Udp4() throws Exception {
960         assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
961 
962         final IpSecAlgorithm crypt = buildCryptAesCtr();
963         final IpSecAlgorithm auth = buildAuthHmacSha512();
964         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
965         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
966     }
967 
968     @Test
testAesCtrHmacSha512Udp6()969     public void testAesCtrHmacSha512Udp6() throws Exception {
970         assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
971 
972         final IpSecAlgorithm crypt = buildCryptAesCtr();
973         final IpSecAlgorithm auth = buildAuthHmacSha512();
974         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
975         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
976     }
977 
buildCryptAesCbc()978     private static IpSecAlgorithm buildCryptAesCbc() throws Exception {
979         return new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY);
980     }
981 
buildAuthAesXcbc()982     private static IpSecAlgorithm buildAuthAesXcbc() throws Exception {
983         return new IpSecAlgorithm(
984                 AUTH_AES_XCBC, getKeyBytes(AES_XCBC_KEY_LEN), AES_XCBC_ICV_LEN * 8);
985     }
986 
buildAuthAesCmac()987     private static IpSecAlgorithm buildAuthAesCmac() throws Exception {
988         return new IpSecAlgorithm(
989                 AUTH_AES_CMAC, getKeyBytes(AES_CMAC_KEY_LEN), AES_CMAC_ICV_LEN * 8);
990     }
991 
992     @Test
testAesCbcAesXCbcTcp4()993     public void testAesCbcAesXCbcTcp4() throws Exception {
994         assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
995 
996         final IpSecAlgorithm crypt = buildCryptAesCbc();
997         final IpSecAlgorithm auth = buildAuthAesXcbc();
998         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
999         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
1000     }
1001 
1002     @Test
testAesCbcAesXCbcTcp6()1003     public void testAesCbcAesXCbcTcp6() throws Exception {
1004         assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
1005 
1006         final IpSecAlgorithm crypt = buildCryptAesCbc();
1007         final IpSecAlgorithm auth = buildAuthAesXcbc();
1008         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
1009         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
1010     }
1011 
1012     @Test
testAesCbcAesXCbcUdp4()1013     public void testAesCbcAesXCbcUdp4() throws Exception {
1014         assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
1015 
1016         final IpSecAlgorithm crypt = buildCryptAesCbc();
1017         final IpSecAlgorithm auth = buildAuthAesXcbc();
1018         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
1019         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
1020     }
1021 
1022     @Test
testAesCbcAesXCbcUdp6()1023     public void testAesCbcAesXCbcUdp6() throws Exception {
1024         assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
1025 
1026         final IpSecAlgorithm crypt = buildCryptAesCbc();
1027         final IpSecAlgorithm auth = buildAuthAesXcbc();
1028         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
1029         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
1030     }
1031 
1032     @Test
testAesCbcAesCmacTcp4()1033     public void testAesCbcAesCmacTcp4() throws Exception {
1034         assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
1035 
1036         final IpSecAlgorithm crypt = buildCryptAesCbc();
1037         final IpSecAlgorithm auth = buildAuthAesCmac();
1038         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
1039         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
1040     }
1041 
1042     @Test
testAesCbcAesCmacTcp6()1043     public void testAesCbcAesCmacTcp6() throws Exception {
1044         assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
1045 
1046         final IpSecAlgorithm crypt = buildCryptAesCbc();
1047         final IpSecAlgorithm auth = buildAuthAesCmac();
1048         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
1049         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
1050     }
1051 
1052     @Test
testAesCbcAesCmacUdp4()1053     public void testAesCbcAesCmacUdp4() throws Exception {
1054         assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
1055 
1056         final IpSecAlgorithm crypt = buildCryptAesCbc();
1057         final IpSecAlgorithm auth = buildAuthAesCmac();
1058         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
1059         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
1060     }
1061 
1062     @Test
testAesCbcAesCmacUdp6()1063     public void testAesCbcAesCmacUdp6() throws Exception {
1064         assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
1065 
1066         final IpSecAlgorithm crypt = buildCryptAesCbc();
1067         final IpSecAlgorithm auth = buildAuthAesCmac();
1068         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
1069         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
1070     }
1071 
1072     @Test
testAesGcm64Tcp4()1073     public void testAesGcm64Tcp4() throws Exception {
1074         IpSecAlgorithm authCrypt =
1075                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
1076         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
1077         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
1078     }
1079 
1080     @Test
testAesGcm64Tcp6()1081     public void testAesGcm64Tcp6() throws Exception {
1082         IpSecAlgorithm authCrypt =
1083                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
1084         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
1085         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
1086     }
1087 
1088     @Test
testAesGcm64Udp4()1089     public void testAesGcm64Udp4() throws Exception {
1090         IpSecAlgorithm authCrypt =
1091                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
1092         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
1093         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
1094     }
1095 
1096     @Test
testAesGcm64Udp6()1097     public void testAesGcm64Udp6() throws Exception {
1098         IpSecAlgorithm authCrypt =
1099                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
1100         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
1101         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
1102     }
1103 
1104     @Test
testAesGcm96Tcp4()1105     public void testAesGcm96Tcp4() throws Exception {
1106         IpSecAlgorithm authCrypt =
1107                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
1108         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
1109         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
1110     }
1111 
1112     @Test
testAesGcm96Tcp6()1113     public void testAesGcm96Tcp6() throws Exception {
1114         IpSecAlgorithm authCrypt =
1115                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
1116         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
1117         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
1118     }
1119 
1120     @Test
testAesGcm96Udp4()1121     public void testAesGcm96Udp4() throws Exception {
1122         IpSecAlgorithm authCrypt =
1123                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
1124         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
1125         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
1126     }
1127 
1128     @Test
testAesGcm96Udp6()1129     public void testAesGcm96Udp6() throws Exception {
1130         IpSecAlgorithm authCrypt =
1131                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
1132         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
1133         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
1134     }
1135 
1136     @Test
testAesGcm128Tcp4()1137     public void testAesGcm128Tcp4() throws Exception {
1138         IpSecAlgorithm authCrypt =
1139                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
1140         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
1141         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
1142     }
1143 
1144     @Test
testAesGcm128Tcp6()1145     public void testAesGcm128Tcp6() throws Exception {
1146         IpSecAlgorithm authCrypt =
1147                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
1148         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
1149         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
1150     }
1151 
1152     @Test
testAesGcm128Udp4()1153     public void testAesGcm128Udp4() throws Exception {
1154         IpSecAlgorithm authCrypt =
1155                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
1156         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
1157         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
1158     }
1159 
1160     @Test
testAesGcm128Udp6()1161     public void testAesGcm128Udp6() throws Exception {
1162         IpSecAlgorithm authCrypt =
1163                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
1164         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
1165         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
1166     }
1167 
buildAuthCryptChaCha20Poly1305()1168     private static IpSecAlgorithm buildAuthCryptChaCha20Poly1305() throws Exception {
1169         return new IpSecAlgorithm(
1170                 AUTH_CRYPT_CHACHA20_POLY1305, AEAD_KEY, CHACHA20_POLY1305_ICV_LEN * 8);
1171     }
1172 
1173     @Test
testChaCha20Poly1305Tcp4()1174     public void testChaCha20Poly1305Tcp4() throws Exception {
1175         assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
1176 
1177         final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
1178         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
1179         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
1180     }
1181 
1182     @Test
testChaCha20Poly1305Tcp6()1183     public void testChaCha20Poly1305Tcp6() throws Exception {
1184         assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
1185 
1186         final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
1187         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
1188         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
1189     }
1190 
1191     @Test
testChaCha20Poly1305Udp4()1192     public void testChaCha20Poly1305Udp4() throws Exception {
1193         assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
1194 
1195         final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
1196         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
1197         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
1198     }
1199 
1200     @Test
testChaCha20Poly1305Udp6()1201     public void testChaCha20Poly1305Udp6() throws Exception {
1202         assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
1203 
1204         final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
1205         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
1206         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
1207     }
1208 
1209     @Test
testAesCbcHmacMd5Tcp4UdpEncap()1210     public void testAesCbcHmacMd5Tcp4UdpEncap() throws Exception {
1211         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1212         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
1213         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1214         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1215     }
1216 
1217     @Test
testAesCbcHmacMd5Udp4UdpEncap()1218     public void testAesCbcHmacMd5Udp4UdpEncap() throws Exception {
1219         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1220         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
1221         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1222         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1223     }
1224 
1225     @Test
testAesCbcHmacSha1Tcp4UdpEncap()1226     public void testAesCbcHmacSha1Tcp4UdpEncap() throws Exception {
1227         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1228         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
1229         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1230         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1231     }
1232 
1233     @Test
testAesCbcHmacSha1Udp4UdpEncap()1234     public void testAesCbcHmacSha1Udp4UdpEncap() throws Exception {
1235         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1236         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
1237         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1238         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1239     }
1240 
1241     @Test
testAesCbcHmacSha256Tcp4UdpEncap()1242     public void testAesCbcHmacSha256Tcp4UdpEncap() throws Exception {
1243         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1244         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
1245         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1246         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1247     }
1248 
1249     @Test
testAesCbcHmacSha256Udp4UdpEncap()1250     public void testAesCbcHmacSha256Udp4UdpEncap() throws Exception {
1251         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1252         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
1253         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1254         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1255     }
1256 
1257     @Test
testAesCbcHmacSha384Tcp4UdpEncap()1258     public void testAesCbcHmacSha384Tcp4UdpEncap() throws Exception {
1259         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1260         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
1261         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1262         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1263     }
1264 
1265     @Test
testAesCbcHmacSha384Udp4UdpEncap()1266     public void testAesCbcHmacSha384Udp4UdpEncap() throws Exception {
1267         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1268         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
1269         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1270         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1271     }
1272 
1273     @Test
testAesCbcHmacSha512Tcp4UdpEncap()1274     public void testAesCbcHmacSha512Tcp4UdpEncap() throws Exception {
1275         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1276         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
1277         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1278         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1279     }
1280 
1281     @Test
testAesCbcHmacSha512Udp4UdpEncap()1282     public void testAesCbcHmacSha512Udp4UdpEncap() throws Exception {
1283         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1284         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
1285         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1286         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1287     }
1288 
1289     @Test
testAesCtrHmacSha512Tcp4UdpEncap()1290     public void testAesCtrHmacSha512Tcp4UdpEncap() throws Exception {
1291         assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
1292 
1293         final IpSecAlgorithm crypt = buildCryptAesCtr();
1294         final IpSecAlgorithm auth = buildAuthHmacSha512();
1295         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1296         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1297     }
1298 
1299     @Test
testAesCtrHmacSha512Udp4UdpEncap()1300     public void testAesCtrHmacSha512Udp4UdpEncap() throws Exception {
1301         assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
1302 
1303         final IpSecAlgorithm crypt = buildCryptAesCtr();
1304         final IpSecAlgorithm auth = buildAuthHmacSha512();
1305         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1306         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1307     }
1308 
1309     @Test
testAesCbcAesXCbcTcp4UdpEncap()1310     public void testAesCbcAesXCbcTcp4UdpEncap() throws Exception {
1311         assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
1312 
1313         final IpSecAlgorithm crypt = new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY);
1314         final IpSecAlgorithm auth = new IpSecAlgorithm(AUTH_AES_XCBC, getKey(128), 96);
1315         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1316         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1317     }
1318 
1319     @Test
testAesCbcAesXCbcUdp4UdpEncap()1320     public void testAesCbcAesXCbcUdp4UdpEncap() throws Exception {
1321         assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
1322 
1323         final IpSecAlgorithm crypt = new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY);
1324         final IpSecAlgorithm auth = new IpSecAlgorithm(AUTH_AES_XCBC, getKey(128), 96);
1325         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1326         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1327     }
1328 
1329     @Test
testAesCbcAesCmacTcp4UdpEncap()1330     public void testAesCbcAesCmacTcp4UdpEncap() throws Exception {
1331         assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
1332 
1333         final IpSecAlgorithm crypt = new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY);
1334         final IpSecAlgorithm auth = new IpSecAlgorithm(AUTH_AES_CMAC, getKey(128), 96);
1335         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1336         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1337     }
1338 
1339     @Test
testAesCbcAesCmacUdp4UdpEncap()1340     public void testAesCbcAesCmacUdp4UdpEncap() throws Exception {
1341         assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
1342 
1343         final IpSecAlgorithm crypt = new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY);
1344         final IpSecAlgorithm auth = new IpSecAlgorithm(AUTH_AES_CMAC, getKey(128), 96);
1345         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1346         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1347     }
1348 
1349     @Test
testAesGcm64Tcp4UdpEncap()1350     public void testAesGcm64Tcp4UdpEncap() throws Exception {
1351         IpSecAlgorithm authCrypt =
1352                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
1353         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
1354         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
1355     }
1356 
1357     @Test
testAesGcm64Udp4UdpEncap()1358     public void testAesGcm64Udp4UdpEncap() throws Exception {
1359         IpSecAlgorithm authCrypt =
1360                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
1361         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
1362         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
1363     }
1364 
1365     @Test
testAesGcm96Tcp4UdpEncap()1366     public void testAesGcm96Tcp4UdpEncap() throws Exception {
1367         IpSecAlgorithm authCrypt =
1368                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
1369         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
1370         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
1371     }
1372 
1373     @Test
testAesGcm96Udp4UdpEncap()1374     public void testAesGcm96Udp4UdpEncap() throws Exception {
1375         IpSecAlgorithm authCrypt =
1376                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
1377         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
1378         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
1379     }
1380 
1381     @Test
testAesGcm128Tcp4UdpEncap()1382     public void testAesGcm128Tcp4UdpEncap() throws Exception {
1383         IpSecAlgorithm authCrypt =
1384                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
1385         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
1386         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
1387     }
1388 
1389     @Test
testAesGcm128Udp4UdpEncap()1390     public void testAesGcm128Udp4UdpEncap() throws Exception {
1391         IpSecAlgorithm authCrypt =
1392                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
1393         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
1394         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
1395     }
1396 
1397     @Test
testChaCha20Poly1305Tcp4UdpEncap()1398     public void testChaCha20Poly1305Tcp4UdpEncap() throws Exception {
1399         assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
1400 
1401         final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
1402         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
1403         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
1404     }
1405 
1406     @Test
testChaCha20Poly1305Udp4UdpEncap()1407     public void testChaCha20Poly1305Udp4UdpEncap() throws Exception {
1408         assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
1409 
1410         final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
1411         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
1412         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
1413     }
1414 
1415     @Test
testCryptUdp4()1416     public void testCryptUdp4() throws Exception {
1417         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1418         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, false, 1, false);
1419         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, false, 1, true);
1420     }
1421 
1422     @Test
testAuthUdp4()1423     public void testAuthUdp4() throws Exception {
1424         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
1425         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, false, 1, false);
1426         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, false, 1, true);
1427     }
1428 
1429     @Test
testCryptUdp6()1430     public void testCryptUdp6() throws Exception {
1431         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1432         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, null, null, false, 1, false);
1433         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, null, null, false, 1, true);
1434     }
1435 
1436     @Test
testAuthUdp6()1437     public void testAuthUdp6() throws Exception {
1438         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
1439         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, auth, null, false, 1, false);
1440         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, auth, null, false, 1, true);
1441     }
1442 
1443     @Test
testCryptTcp4()1444     public void testCryptTcp4() throws Exception {
1445         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1446         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, false, 1, false);
1447         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, false, 1, true);
1448     }
1449 
1450     @Test
testAuthTcp4()1451     public void testAuthTcp4() throws Exception {
1452         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
1453         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, false, 1, false);
1454         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, false, 1, true);
1455     }
1456 
1457     @Test
testCryptTcp6()1458     public void testCryptTcp6() throws Exception {
1459         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1460         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, null, null, false, 1, false);
1461         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, null, null, false, 1, true);
1462     }
1463 
1464     @Test
testAuthTcp6()1465     public void testAuthTcp6() throws Exception {
1466         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
1467         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, auth, null, false, 1, false);
1468         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, auth, null, false, 1, true);
1469     }
1470 
1471     @Test
testCryptUdp4UdpEncap()1472     public void testCryptUdp4UdpEncap() throws Exception {
1473         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1474         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, true, 1, false);
1475         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, true, 1, true);
1476     }
1477 
1478     @Test
testAuthUdp4UdpEncap()1479     public void testAuthUdp4UdpEncap() throws Exception {
1480         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
1481         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, true, 1, false);
1482         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, true, 1, true);
1483     }
1484 
1485     @Test
testCryptTcp4UdpEncap()1486     public void testCryptTcp4UdpEncap() throws Exception {
1487         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1488         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, true, 1, false);
1489         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, true, 1, true);
1490     }
1491 
1492     @Test
testAuthTcp4UdpEncap()1493     public void testAuthTcp4UdpEncap() throws Exception {
1494         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
1495         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, true, 1, false);
1496         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, true, 1, true);
1497     }
1498 
1499     @Test
testOpenUdpEncapSocketSpecificPort()1500     public void testOpenUdpEncapSocketSpecificPort() throws Exception {
1501         IpSecManager.UdpEncapsulationSocket encapSocket = null;
1502         int port = -1;
1503         for (int i = 0; i < MAX_PORT_BIND_ATTEMPTS; i++) {
1504             try {
1505                 port = findUnusedPort();
1506                 encapSocket = mISM.openUdpEncapsulationSocket(port);
1507                 break;
1508             } catch (ErrnoException e) {
1509                 if (e.errno == OsConstants.EADDRINUSE) {
1510                     // Someone claimed the port since we called findUnusedPort.
1511                     continue;
1512                 }
1513                 throw e;
1514             } finally {
1515                 if (encapSocket != null) {
1516                     encapSocket.close();
1517                 }
1518             }
1519         }
1520 
1521         if (encapSocket == null) {
1522             fail("Failed " + MAX_PORT_BIND_ATTEMPTS + " attempts to bind to a port");
1523         }
1524 
1525         assertTrue("Returned invalid port", encapSocket.getPort() == port);
1526     }
1527 
1528     @Test
testOpenUdpEncapSocketRandomPort()1529     public void testOpenUdpEncapSocketRandomPort() throws Exception {
1530         try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
1531             assertTrue("Returned invalid port", encapSocket.getPort() != 0);
1532         }
1533     }
1534 }
1535