• 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 
56 import static org.junit.Assert.assertArrayEquals;
57 import static org.junit.Assert.assertEquals;
58 import static org.junit.Assert.assertTrue;
59 import static org.junit.Assert.fail;
60 import static org.junit.Assume.assumeTrue;
61 
62 import android.net.IpSecAlgorithm;
63 import android.net.IpSecManager;
64 import android.net.IpSecTransform;
65 import android.net.TrafficStats;
66 import android.os.Build;
67 import android.platform.test.annotations.AppModeFull;
68 import android.system.ErrnoException;
69 import android.system.Os;
70 import android.system.OsConstants;
71 
72 import androidx.test.InstrumentationRegistry;
73 import androidx.test.runner.AndroidJUnit4;
74 
75 import com.android.testutils.DevSdkIgnoreRule;
76 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
77 
78 import org.junit.Rule;
79 import org.junit.Test;
80 import org.junit.runner.RunWith;
81 
82 import java.io.FileDescriptor;
83 import java.io.IOException;
84 import java.net.DatagramPacket;
85 import java.net.DatagramSocket;
86 import java.net.Inet6Address;
87 import java.net.InetAddress;
88 import java.util.Arrays;
89 import java.util.HashMap;
90 import java.util.Map;
91 import java.util.Map.Entry;
92 import java.util.Set;
93 
94 @RunWith(AndroidJUnit4.class)
95 @AppModeFull(reason = "Socket cannot bind in instant app mode")
96 public class IpSecManagerTest extends IpSecBaseTest {
97     @Rule public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
98 
99     private static final String TAG = IpSecManagerTest.class.getSimpleName();
100 
101     private static final InetAddress GOOGLE_DNS_4 = InetAddress.parseNumericAddress("8.8.8.8");
102     private static final InetAddress GOOGLE_DNS_6 =
103             InetAddress.parseNumericAddress("2001:4860:4860::8888");
104 
105     private static final InetAddress[] GOOGLE_DNS_LIST =
106             new InetAddress[] {GOOGLE_DNS_4, GOOGLE_DNS_6};
107 
108     private static final int DROID_SPI = 0xD1201D;
109     private static final int MAX_PORT_BIND_ATTEMPTS = 10;
110 
111     private static final byte[] AEAD_KEY = getKey(288);
112 
113     /*
114      * Allocate a random SPI
115      * Allocate a specific SPI using previous randomly created SPI value
116      * Realloc the same SPI that was specifically created (expect SpiUnavailable)
117      * Close SPIs
118      */
119     @Test
testAllocSpi()120     public void testAllocSpi() throws Exception {
121         for (InetAddress addr : GOOGLE_DNS_LIST) {
122             IpSecManager.SecurityParameterIndex randomSpi = null, droidSpi = null;
123             randomSpi = mISM.allocateSecurityParameterIndex(addr);
124             assertTrue(
125                     "Failed to receive a valid SPI",
126                     randomSpi.getSpi() != IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
127 
128             droidSpi = mISM.allocateSecurityParameterIndex(addr, DROID_SPI);
129             assertTrue("Failed to allocate specified SPI, " + DROID_SPI,
130                     droidSpi.getSpi() == DROID_SPI);
131 
132             try {
133                 mISM.allocateSecurityParameterIndex(addr, DROID_SPI);
134                 fail("Duplicate SPI was allowed to be created");
135             } catch (IpSecManager.SpiUnavailableException expected) {
136                 // This is a success case because we expect a dupe SPI to throw
137             }
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(
417                     ifaceTxBytes, newIfaceTxBytes, expectedTxByteDelta, ERROR_MARGIN_BYTES);
418             assertApproxEquals(
419                     ifaceRxBytes, newIfaceRxBytes, expectedRxByteDelta, ERROR_MARGIN_BYTES);
420             assertApproxEquals(
421                     ifaceTxPackets, newIfaceTxPackets, expectedTxPacketDelta, ERROR_MARGIN_PKTS);
422             assertApproxEquals(
423                     ifaceRxPackets, newIfaceRxPackets, expectedRxPacketDelta, ERROR_MARGIN_PKTS);
424         }
425 
assertApproxEquals( long oldStats, long newStats, int expectedDelta, double errorMargin)426         private static void assertApproxEquals(
427                 long oldStats, long newStats, int expectedDelta, double errorMargin) {
428             assertTrue(expectedDelta <= newStats - oldStats);
429             assertTrue((expectedDelta * errorMargin) > newStats - oldStats);
430         }
431 
initStatsChecker()432         private static void initStatsChecker() throws Exception {
433             uidTxBytes = TrafficStats.getUidTxBytes(Os.getuid());
434             uidRxBytes = TrafficStats.getUidRxBytes(Os.getuid());
435             uidTxPackets = TrafficStats.getUidTxPackets(Os.getuid());
436             uidRxPackets = TrafficStats.getUidRxPackets(Os.getuid());
437 
438             ifaceTxBytes = TrafficStats.getLoopbackTxBytes();
439             ifaceRxBytes = TrafficStats.getLoopbackRxBytes();
440             ifaceTxPackets = TrafficStats.getLoopbackTxPackets();
441             ifaceRxPackets = TrafficStats.getLoopbackRxPackets();
442         }
443     }
444 
getTruncLenBits(IpSecAlgorithm authOrAead)445     private int getTruncLenBits(IpSecAlgorithm authOrAead) {
446         return authOrAead == null ? 0 : authOrAead.getTruncationLengthBits();
447     }
448 
getIvLen(IpSecAlgorithm cryptOrAead)449     private int getIvLen(IpSecAlgorithm cryptOrAead) {
450         if (cryptOrAead == null) { return 0; }
451 
452         switch (cryptOrAead.getName()) {
453             case IpSecAlgorithm.CRYPT_AES_CBC:
454                 return AES_CBC_IV_LEN;
455             case IpSecAlgorithm.CRYPT_AES_CTR:
456                 return AES_CTR_IV_LEN;
457             case IpSecAlgorithm.AUTH_CRYPT_AES_GCM:
458                 return AES_GCM_IV_LEN;
459             case IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305:
460                 return CHACHA20_POLY1305_IV_LEN;
461             default:
462                 throw new IllegalArgumentException(
463                         "IV length unknown for algorithm" + cryptOrAead.getName());
464         }
465     }
466 
getBlkSize(IpSecAlgorithm cryptOrAead)467     private int getBlkSize(IpSecAlgorithm cryptOrAead) {
468         // RFC 4303, section 2.4 states that ciphertext plus pad_len, next_header fields must
469         //     terminate on a 4-byte boundary. Thus, the minimum ciphertext block size is 4 bytes.
470         if (cryptOrAead == null) { return 4; }
471 
472         switch (cryptOrAead.getName()) {
473             case IpSecAlgorithm.CRYPT_AES_CBC:
474                 return AES_CBC_BLK_SIZE;
475             case IpSecAlgorithm.CRYPT_AES_CTR:
476                 return AES_CTR_BLK_SIZE;
477             case IpSecAlgorithm.AUTH_CRYPT_AES_GCM:
478                 return AES_GCM_BLK_SIZE;
479             case IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305:
480                 return CHACHA20_POLY1305_BLK_SIZE;
481             default:
482                 throw new IllegalArgumentException(
483                         "Blk size unknown for algorithm" + cryptOrAead.getName());
484         }
485     }
486 
checkTransform( int protocol, String localAddress, IpSecAlgorithm crypt, IpSecAlgorithm auth, IpSecAlgorithm aead, boolean doUdpEncap, int sendCount, boolean useJavaSockets)487     public void checkTransform(
488             int protocol,
489             String localAddress,
490             IpSecAlgorithm crypt,
491             IpSecAlgorithm auth,
492             IpSecAlgorithm aead,
493             boolean doUdpEncap,
494             int sendCount,
495             boolean useJavaSockets)
496             throws Exception {
497         StatsChecker.initStatsChecker();
498         InetAddress local = InetAddress.getByName(localAddress);
499 
500         try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket();
501                 IpSecManager.SecurityParameterIndex spi =
502                         mISM.allocateSecurityParameterIndex(local)) {
503 
504             IpSecTransform.Builder transformBuilder =
505                     new IpSecTransform.Builder(InstrumentationRegistry.getContext());
506             if (crypt != null) {
507                 transformBuilder.setEncryption(crypt);
508             }
509             if (auth != null) {
510                 transformBuilder.setAuthentication(auth);
511             }
512             if (aead != null) {
513                 transformBuilder.setAuthenticatedEncryption(aead);
514             }
515 
516             if (doUdpEncap) {
517                 transformBuilder =
518                         transformBuilder.setIpv4Encapsulation(encapSocket, encapSocket.getPort());
519             }
520 
521             int ipHdrLen = local instanceof Inet6Address ? IP6_HDRLEN : IP4_HDRLEN;
522             int transportHdrLen = 0;
523             int udpEncapLen = doUdpEncap ? UDP_HDRLEN : 0;
524 
525             try (IpSecTransform transform =
526                         transformBuilder.buildTransportModeTransform(local, spi)) {
527                 if (protocol == IPPROTO_TCP) {
528                     transportHdrLen = TCP_HDRLEN_WITH_TIMESTAMP_OPT;
529                     checkTcp(transform, local, sendCount, useJavaSockets);
530                 } else if (protocol == IPPROTO_UDP) {
531                     transportHdrLen = UDP_HDRLEN;
532 
533                     // TODO: Also check connected udp.
534                     checkUnconnectedUdp(transform, local, sendCount, useJavaSockets);
535                 } else {
536                     throw new IllegalArgumentException("Invalid protocol");
537                 }
538             }
539 
540             checkStatsChecker(
541                     protocol,
542                     ipHdrLen,
543                     transportHdrLen,
544                     udpEncapLen,
545                     sendCount,
546                     getIvLen(crypt != null ? crypt : aead),
547                     getBlkSize(crypt != null ? crypt : aead),
548                     getTruncLenBits(auth != null ? auth : aead));
549         }
550     }
551 
checkStatsChecker( int protocol, int ipHdrLen, int transportHdrLen, int udpEncapLen, int sendCount, int ivLen, int blkSize, int truncLenBits)552     private void checkStatsChecker(
553             int protocol,
554             int ipHdrLen,
555             int transportHdrLen,
556             int udpEncapLen,
557             int sendCount,
558             int ivLen,
559             int blkSize,
560             int truncLenBits)
561             throws Exception {
562         int innerPacketSize = TEST_DATA.length + transportHdrLen + ipHdrLen;
563         int outerPacketSize =
564                 PacketUtils.calculateEspPacketSize(
565                                 TEST_DATA.length + transportHdrLen, ivLen, blkSize, truncLenBits)
566                         + udpEncapLen
567                         + ipHdrLen;
568 
569         int expectedOuterBytes = outerPacketSize * sendCount;
570         int expectedInnerBytes = innerPacketSize * sendCount;
571         int expectedPackets = sendCount;
572 
573         // Each run sends two packets, one in each direction.
574         sendCount *= 2;
575         expectedOuterBytes *= 2;
576         expectedInnerBytes *= 2;
577         expectedPackets *= 2;
578 
579         // Add TCP ACKs for data packets
580         if (protocol == IPPROTO_TCP) {
581             int encryptedTcpPktSize =
582                     PacketUtils.calculateEspPacketSize(
583                             TCP_HDRLEN_WITH_TIMESTAMP_OPT, ivLen, blkSize, truncLenBits);
584 
585             // Add data packet ACKs
586             expectedOuterBytes += (encryptedTcpPktSize + udpEncapLen + ipHdrLen) * (sendCount);
587             expectedInnerBytes += (TCP_HDRLEN_WITH_TIMESTAMP_OPT + ipHdrLen) * (sendCount);
588             expectedPackets += sendCount;
589         }
590 
591         StatsChecker.waitForNumPackets(expectedPackets);
592 
593         // eBPF only counts inner packets, whereas xt_qtaguid counts outer packets. Allow both
594         StatsChecker.assertUidStatsDelta(
595                 expectedOuterBytes,
596                 expectedPackets,
597                 expectedInnerBytes,
598                 expectedOuterBytes,
599                 expectedPackets);
600 
601         // Unreliable at low numbers due to potential interference from other processes.
602         if (sendCount >= 1000) {
603             StatsChecker.assertIfaceStatsDelta(
604                     expectedOuterBytes, expectedPackets, expectedOuterBytes, expectedPackets);
605         }
606     }
607 
checkIkePacket( NativeUdpSocket wrappedEncapSocket, InetAddress localAddr)608     private void checkIkePacket(
609             NativeUdpSocket wrappedEncapSocket, InetAddress localAddr) throws Exception {
610         StatsChecker.initStatsChecker();
611 
612         try (NativeUdpSocket remoteSocket = new NativeUdpSocket(getBoundUdpSocket(localAddr))) {
613 
614             // Append IKE/ESP header - 4 bytes of SPI, 4 bytes of seq number, all zeroed out
615             // If the first four bytes are zero, assume non-ESP (IKE traffic)
616             byte[] dataWithEspHeader = new byte[TEST_DATA.length + 8];
617             System.arraycopy(TEST_DATA, 0, dataWithEspHeader, 8, TEST_DATA.length);
618 
619             // Send the IKE packet from remoteSocket to wrappedEncapSocket. Since IKE packets
620             // are multiplexed over the socket, we expect them to appear on the encap socket
621             // (as opposed to being decrypted and received on the non-encap socket)
622             remoteSocket.sendTo(dataWithEspHeader, localAddr, wrappedEncapSocket.getPort());
623             byte[] in = wrappedEncapSocket.receive();
624             assertArrayEquals("Encapsulated data did not match.", dataWithEspHeader, in);
625 
626             // Also test that the IKE socket can send data out.
627             wrappedEncapSocket.sendTo(dataWithEspHeader, localAddr, remoteSocket.getPort());
628             in = remoteSocket.receive();
629             assertArrayEquals("Encapsulated data did not match.", dataWithEspHeader, in);
630 
631             // Calculate expected packet sizes. Always use IPv4 header, since our kernels only
632             // guarantee support of UDP encap on IPv4.
633             int expectedNumPkts = 2;
634             int expectedPacketSize =
635                     expectedNumPkts * (dataWithEspHeader.length + UDP_HDRLEN + IP4_HDRLEN);
636 
637             StatsChecker.waitForNumPackets(expectedNumPkts);
638             StatsChecker.assertUidStatsDelta(
639                     expectedPacketSize,
640                     expectedNumPkts,
641                     expectedPacketSize,
642                     expectedPacketSize,
643                     expectedNumPkts);
644             StatsChecker.assertIfaceStatsDelta(
645                     expectedPacketSize, expectedNumPkts, expectedPacketSize, expectedNumPkts);
646         }
647     }
648 
649     @Test
testIkeOverUdpEncapSocket()650     public void testIkeOverUdpEncapSocket() throws Exception {
651         // IPv6 not supported for UDP-encap-ESP
652         InetAddress local = InetAddress.getByName(IPV4_LOOPBACK);
653         try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
654             NativeUdpSocket wrappedEncapSocket =
655                     new NativeUdpSocket(encapSocket.getFileDescriptor());
656             checkIkePacket(wrappedEncapSocket, local);
657 
658             // Now try with a transform applied to a socket using this Encap socket
659             IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
660             IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
661 
662             try (IpSecManager.SecurityParameterIndex spi =
663                             mISM.allocateSecurityParameterIndex(local);
664                     IpSecTransform transform =
665                             new IpSecTransform.Builder(InstrumentationRegistry.getContext())
666                                     .setEncryption(crypt)
667                                     .setAuthentication(auth)
668                                     .setIpv4Encapsulation(encapSocket, encapSocket.getPort())
669                                     .buildTransportModeTransform(local, spi);
670                     JavaUdpSocket localSocket = new JavaUdpSocket(local)) {
671                 applyTransformBidirectionally(mISM, transform, localSocket);
672 
673                 checkIkePacket(wrappedEncapSocket, local);
674             }
675         }
676     }
677 
678     // TODO: Check IKE over ESP sockets (IPv4, IPv6) - does this need SOCK_RAW?
679 
680     /* TODO: Re-enable these when policy matcher works for reflected packets
681      *
682      * The issue here is that A sends to B, and everything is new; therefore PREROUTING counts
683      * correctly. But it appears that the security path is not cleared afterwards, thus when A
684      * sends an ACK back to B, the policy matcher flags it as a "IPSec" packet. See b/70635417
685      */
686 
687     // public void testInterfaceCountersTcp4() throws Exception {
688     //     IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
689     //     IpSecAlgorithm auth = new IpSecAlgorithm(
690     //             IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
691     //     checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, false, 1000);
692     // }
693 
694     // public void testInterfaceCountersTcp6() throws Exception {
695     //     IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
696     //     IpSecAlgorithm auth = new IpSecAlgorithm(
697     //             IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
698     //     checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, false, 1000);
699     // }
700 
701     // public void testInterfaceCountersTcp4UdpEncap() throws Exception {
702     //     IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
703     //     IpSecAlgorithm auth =
704     //             new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
705     //     checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, true, 1000);
706     // }
707 
708     @IgnoreUpTo(Build.VERSION_CODES.R)
709     @Test
testGetSupportedAlgorithms()710     public void testGetSupportedAlgorithms() throws Exception {
711         final Map<String, Integer> algoToRequiredMinSdk = new HashMap<>();
712         algoToRequiredMinSdk.put(CRYPT_AES_CBC, Build.VERSION_CODES.P);
713         algoToRequiredMinSdk.put(AUTH_HMAC_MD5, Build.VERSION_CODES.P);
714         algoToRequiredMinSdk.put(AUTH_HMAC_SHA1, Build.VERSION_CODES.P);
715         algoToRequiredMinSdk.put(AUTH_HMAC_SHA256, Build.VERSION_CODES.P);
716         algoToRequiredMinSdk.put(AUTH_HMAC_SHA384, Build.VERSION_CODES.P);
717         algoToRequiredMinSdk.put(AUTH_HMAC_SHA512, Build.VERSION_CODES.P);
718         algoToRequiredMinSdk.put(AUTH_CRYPT_AES_GCM, Build.VERSION_CODES.P);
719 
720         // TODO: b/170424293 Use Build.VERSION_CODES.S when is finalized
721         algoToRequiredMinSdk.put(CRYPT_AES_CTR, Build.VERSION_CODES.R + 1);
722         algoToRequiredMinSdk.put(AUTH_AES_CMAC, Build.VERSION_CODES.R + 1);
723         algoToRequiredMinSdk.put(AUTH_AES_XCBC, Build.VERSION_CODES.R + 1);
724         algoToRequiredMinSdk.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.R + 1);
725 
726         final Set<String> supportedAlgos = IpSecAlgorithm.getSupportedAlgorithms();
727 
728         // Verify all supported algorithms are valid
729         for (String algo : supportedAlgos) {
730             assertTrue("Found invalid algo " + algo, algoToRequiredMinSdk.keySet().contains(algo));
731         }
732 
733         // Verify all mandatory algorithms are supported
734         for (Entry<String, Integer> entry : algoToRequiredMinSdk.entrySet()) {
735             if (Math.min(getFirstApiLevel(), getVendorApiLevel()) >= entry.getValue()) {
736                 assertTrue(
737                         "Fail to support " + entry.getKey(),
738                         supportedAlgos.contains(entry.getKey()));
739             }
740         }
741     }
742 
743     @Test
testInterfaceCountersUdp4()744     public void testInterfaceCountersUdp4() throws Exception {
745         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
746         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
747         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1000, false);
748     }
749 
750     @Test
testInterfaceCountersUdp6()751     public void testInterfaceCountersUdp6() throws Exception {
752         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
753         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
754         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1000, false);
755     }
756 
757     @Test
testInterfaceCountersUdp4UdpEncap()758     public void testInterfaceCountersUdp4UdpEncap() throws Exception {
759         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
760         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
761         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1000, false);
762     }
763 
764     @Test
testAesCbcHmacMd5Tcp4()765     public void testAesCbcHmacMd5Tcp4() throws Exception {
766         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
767         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
768         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
769         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
770     }
771 
772     @Test
testAesCbcHmacMd5Tcp6()773     public void testAesCbcHmacMd5Tcp6() throws Exception {
774         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
775         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
776         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
777         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
778     }
779 
780     @Test
testAesCbcHmacMd5Udp4()781     public void testAesCbcHmacMd5Udp4() throws Exception {
782         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
783         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
784         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
785         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
786     }
787 
788     @Test
testAesCbcHmacMd5Udp6()789     public void testAesCbcHmacMd5Udp6() throws Exception {
790         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
791         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
792         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
793         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
794     }
795 
796     @Test
testAesCbcHmacSha1Tcp4()797     public void testAesCbcHmacSha1Tcp4() throws Exception {
798         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
799         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
800         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
801         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
802     }
803 
804     @Test
testAesCbcHmacSha1Tcp6()805     public void testAesCbcHmacSha1Tcp6() throws Exception {
806         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
807         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
808         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
809         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
810     }
811 
812     @Test
testAesCbcHmacSha1Udp4()813     public void testAesCbcHmacSha1Udp4() throws Exception {
814         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
815         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
816         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
817         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
818     }
819 
820     @Test
testAesCbcHmacSha1Udp6()821     public void testAesCbcHmacSha1Udp6() throws Exception {
822         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
823         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
824         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
825         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
826     }
827 
828     @Test
testAesCbcHmacSha256Tcp4()829     public void testAesCbcHmacSha256Tcp4() throws Exception {
830         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
831         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
832         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
833         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
834     }
835 
836     @Test
testAesCbcHmacSha256Tcp6()837     public void testAesCbcHmacSha256Tcp6() throws Exception {
838         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
839         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
840         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
841         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
842     }
843 
844     @Test
testAesCbcHmacSha256Udp4()845     public void testAesCbcHmacSha256Udp4() throws Exception {
846         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
847         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
848         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
849         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
850     }
851 
852     @Test
testAesCbcHmacSha256Udp6()853     public void testAesCbcHmacSha256Udp6() throws Exception {
854         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
855         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
856         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
857         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
858     }
859 
860     @Test
testAesCbcHmacSha384Tcp4()861     public void testAesCbcHmacSha384Tcp4() throws Exception {
862         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
863         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
864         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
865         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
866     }
867 
868     @Test
testAesCbcHmacSha384Tcp6()869     public void testAesCbcHmacSha384Tcp6() throws Exception {
870         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
871         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
872         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
873         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
874     }
875 
876     @Test
testAesCbcHmacSha384Udp4()877     public void testAesCbcHmacSha384Udp4() throws Exception {
878         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
879         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
880         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
881         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
882     }
883 
884     @Test
testAesCbcHmacSha384Udp6()885     public void testAesCbcHmacSha384Udp6() throws Exception {
886         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
887         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
888         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
889         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
890     }
891 
892     @Test
testAesCbcHmacSha512Tcp4()893     public void testAesCbcHmacSha512Tcp4() throws Exception {
894         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
895         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
896         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
897         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
898     }
899 
900     @Test
testAesCbcHmacSha512Tcp6()901     public void testAesCbcHmacSha512Tcp6() throws Exception {
902         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
903         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
904         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
905         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
906     }
907 
908     @Test
testAesCbcHmacSha512Udp4()909     public void testAesCbcHmacSha512Udp4() throws Exception {
910         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
911         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
912         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
913         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
914     }
915 
916     @Test
testAesCbcHmacSha512Udp6()917     public void testAesCbcHmacSha512Udp6() throws Exception {
918         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
919         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
920         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
921         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
922     }
923 
buildCryptAesCtr()924     private static IpSecAlgorithm buildCryptAesCtr() throws Exception {
925         return new IpSecAlgorithm(CRYPT_AES_CTR, getKeyBytes(AES_CTR_KEY_LEN_20));
926     }
927 
buildAuthHmacSha512()928     private static IpSecAlgorithm buildAuthHmacSha512() throws Exception {
929         return new IpSecAlgorithm(
930                 AUTH_HMAC_SHA512, getKeyBytes(HMAC_SHA512_KEY_LEN), HMAC_SHA512_ICV_LEN * 8);
931     }
932 
933     @Test
testAesCtrHmacSha512Tcp4()934     public void testAesCtrHmacSha512Tcp4() throws Exception {
935         assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
936 
937         final IpSecAlgorithm crypt = buildCryptAesCtr();
938         final IpSecAlgorithm auth = buildAuthHmacSha512();
939         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
940         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
941     }
942 
943     @Test
testAesCtrHmacSha512Tcp6()944     public void testAesCtrHmacSha512Tcp6() throws Exception {
945         assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
946 
947         final IpSecAlgorithm crypt = buildCryptAesCtr();
948         final IpSecAlgorithm auth = buildAuthHmacSha512();
949         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
950         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
951     }
952 
953     @Test
testAesCtrHmacSha512Udp4()954     public void testAesCtrHmacSha512Udp4() throws Exception {
955         assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
956 
957         final IpSecAlgorithm crypt = buildCryptAesCtr();
958         final IpSecAlgorithm auth = buildAuthHmacSha512();
959         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
960         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
961     }
962 
963     @Test
testAesCtrHmacSha512Udp6()964     public void testAesCtrHmacSha512Udp6() throws Exception {
965         assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
966 
967         final IpSecAlgorithm crypt = buildCryptAesCtr();
968         final IpSecAlgorithm auth = buildAuthHmacSha512();
969         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
970         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
971     }
972 
buildCryptAesCbc()973     private static IpSecAlgorithm buildCryptAesCbc() throws Exception {
974         return new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY);
975     }
976 
buildAuthAesXcbc()977     private static IpSecAlgorithm buildAuthAesXcbc() throws Exception {
978         return new IpSecAlgorithm(
979                 AUTH_AES_XCBC, getKeyBytes(AES_XCBC_KEY_LEN), AES_XCBC_ICV_LEN * 8);
980     }
981 
buildAuthAesCmac()982     private static IpSecAlgorithm buildAuthAesCmac() throws Exception {
983         return new IpSecAlgorithm(
984                 AUTH_AES_CMAC, getKeyBytes(AES_CMAC_KEY_LEN), AES_CMAC_ICV_LEN * 8);
985     }
986 
987     @Test
testAesCbcAesXCbcTcp4()988     public void testAesCbcAesXCbcTcp4() throws Exception {
989         assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
990 
991         final IpSecAlgorithm crypt = buildCryptAesCbc();
992         final IpSecAlgorithm auth = buildAuthAesXcbc();
993         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
994         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
995     }
996 
997     @Test
testAesCbcAesXCbcTcp6()998     public void testAesCbcAesXCbcTcp6() throws Exception {
999         assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
1000 
1001         final IpSecAlgorithm crypt = buildCryptAesCbc();
1002         final IpSecAlgorithm auth = buildAuthAesXcbc();
1003         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
1004         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
1005     }
1006 
1007     @Test
testAesCbcAesXCbcUdp4()1008     public void testAesCbcAesXCbcUdp4() throws Exception {
1009         assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
1010 
1011         final IpSecAlgorithm crypt = buildCryptAesCbc();
1012         final IpSecAlgorithm auth = buildAuthAesXcbc();
1013         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
1014         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
1015     }
1016 
1017     @Test
testAesCbcAesXCbcUdp6()1018     public void testAesCbcAesXCbcUdp6() throws Exception {
1019         assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
1020 
1021         final IpSecAlgorithm crypt = buildCryptAesCbc();
1022         final IpSecAlgorithm auth = buildAuthAesXcbc();
1023         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
1024         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
1025     }
1026 
1027     @Test
testAesCbcAesCmacTcp4()1028     public void testAesCbcAesCmacTcp4() throws Exception {
1029         assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
1030 
1031         final IpSecAlgorithm crypt = buildCryptAesCbc();
1032         final IpSecAlgorithm auth = buildAuthAesCmac();
1033         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
1034         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
1035     }
1036 
1037     @Test
testAesCbcAesCmacTcp6()1038     public void testAesCbcAesCmacTcp6() throws Exception {
1039         assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
1040 
1041         final IpSecAlgorithm crypt = buildCryptAesCbc();
1042         final IpSecAlgorithm auth = buildAuthAesCmac();
1043         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
1044         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
1045     }
1046 
1047     @Test
testAesCbcAesCmacUdp4()1048     public void testAesCbcAesCmacUdp4() throws Exception {
1049         assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
1050 
1051         final IpSecAlgorithm crypt = buildCryptAesCbc();
1052         final IpSecAlgorithm auth = buildAuthAesCmac();
1053         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false);
1054         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true);
1055     }
1056 
1057     @Test
testAesCbcAesCmacUdp6()1058     public void testAesCbcAesCmacUdp6() throws Exception {
1059         assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
1060 
1061         final IpSecAlgorithm crypt = buildCryptAesCbc();
1062         final IpSecAlgorithm auth = buildAuthAesCmac();
1063         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false);
1064         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true);
1065     }
1066 
1067     @Test
testAesGcm64Tcp4()1068     public void testAesGcm64Tcp4() throws Exception {
1069         IpSecAlgorithm authCrypt =
1070                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
1071         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
1072         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
1073     }
1074 
1075     @Test
testAesGcm64Tcp6()1076     public void testAesGcm64Tcp6() throws Exception {
1077         IpSecAlgorithm authCrypt =
1078                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
1079         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
1080         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
1081     }
1082 
1083     @Test
testAesGcm64Udp4()1084     public void testAesGcm64Udp4() throws Exception {
1085         IpSecAlgorithm authCrypt =
1086                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
1087         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
1088         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
1089     }
1090 
1091     @Test
testAesGcm64Udp6()1092     public void testAesGcm64Udp6() throws Exception {
1093         IpSecAlgorithm authCrypt =
1094                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
1095         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
1096         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
1097     }
1098 
1099     @Test
testAesGcm96Tcp4()1100     public void testAesGcm96Tcp4() throws Exception {
1101         IpSecAlgorithm authCrypt =
1102                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
1103         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
1104         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
1105     }
1106 
1107     @Test
testAesGcm96Tcp6()1108     public void testAesGcm96Tcp6() throws Exception {
1109         IpSecAlgorithm authCrypt =
1110                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
1111         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
1112         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
1113     }
1114 
1115     @Test
testAesGcm96Udp4()1116     public void testAesGcm96Udp4() throws Exception {
1117         IpSecAlgorithm authCrypt =
1118                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
1119         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
1120         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
1121     }
1122 
1123     @Test
testAesGcm96Udp6()1124     public void testAesGcm96Udp6() throws Exception {
1125         IpSecAlgorithm authCrypt =
1126                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
1127         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
1128         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
1129     }
1130 
1131     @Test
testAesGcm128Tcp4()1132     public void testAesGcm128Tcp4() throws Exception {
1133         IpSecAlgorithm authCrypt =
1134                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
1135         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
1136         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
1137     }
1138 
1139     @Test
testAesGcm128Tcp6()1140     public void testAesGcm128Tcp6() throws Exception {
1141         IpSecAlgorithm authCrypt =
1142                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
1143         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
1144         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
1145     }
1146 
1147     @Test
testAesGcm128Udp4()1148     public void testAesGcm128Udp4() throws Exception {
1149         IpSecAlgorithm authCrypt =
1150                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
1151         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
1152         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
1153     }
1154 
1155     @Test
testAesGcm128Udp6()1156     public void testAesGcm128Udp6() throws Exception {
1157         IpSecAlgorithm authCrypt =
1158                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
1159         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
1160         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
1161     }
1162 
buildAuthCryptChaCha20Poly1305()1163     private static IpSecAlgorithm buildAuthCryptChaCha20Poly1305() throws Exception {
1164         return new IpSecAlgorithm(
1165                 AUTH_CRYPT_CHACHA20_POLY1305, AEAD_KEY, CHACHA20_POLY1305_ICV_LEN * 8);
1166     }
1167 
1168     @Test
testChaCha20Poly1305Tcp4()1169     public void testChaCha20Poly1305Tcp4() throws Exception {
1170         assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
1171 
1172         final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
1173         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
1174         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
1175     }
1176 
1177     @Test
testChaCha20Poly1305Tcp6()1178     public void testChaCha20Poly1305Tcp6() throws Exception {
1179         assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
1180 
1181         final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
1182         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
1183         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
1184     }
1185 
1186     @Test
testChaCha20Poly1305Udp4()1187     public void testChaCha20Poly1305Udp4() throws Exception {
1188         assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
1189 
1190         final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
1191         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false);
1192         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true);
1193     }
1194 
1195     @Test
testChaCha20Poly1305Udp6()1196     public void testChaCha20Poly1305Udp6() throws Exception {
1197         assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
1198 
1199         final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
1200         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false);
1201         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true);
1202     }
1203 
1204     @Test
testAesCbcHmacMd5Tcp4UdpEncap()1205     public void testAesCbcHmacMd5Tcp4UdpEncap() throws Exception {
1206         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1207         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
1208         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1209         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1210     }
1211 
1212     @Test
testAesCbcHmacMd5Udp4UdpEncap()1213     public void testAesCbcHmacMd5Udp4UdpEncap() throws Exception {
1214         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1215         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
1216         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1217         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1218     }
1219 
1220     @Test
testAesCbcHmacSha1Tcp4UdpEncap()1221     public void testAesCbcHmacSha1Tcp4UdpEncap() throws Exception {
1222         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1223         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
1224         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1225         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1226     }
1227 
1228     @Test
testAesCbcHmacSha1Udp4UdpEncap()1229     public void testAesCbcHmacSha1Udp4UdpEncap() throws Exception {
1230         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1231         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96);
1232         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1233         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1234     }
1235 
1236     @Test
testAesCbcHmacSha256Tcp4UdpEncap()1237     public void testAesCbcHmacSha256Tcp4UdpEncap() throws Exception {
1238         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1239         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
1240         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1241         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1242     }
1243 
1244     @Test
testAesCbcHmacSha256Udp4UdpEncap()1245     public void testAesCbcHmacSha256Udp4UdpEncap() throws Exception {
1246         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1247         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
1248         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1249         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1250     }
1251 
1252     @Test
testAesCbcHmacSha384Tcp4UdpEncap()1253     public void testAesCbcHmacSha384Tcp4UdpEncap() throws Exception {
1254         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1255         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
1256         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1257         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1258     }
1259 
1260     @Test
testAesCbcHmacSha384Udp4UdpEncap()1261     public void testAesCbcHmacSha384Udp4UdpEncap() throws Exception {
1262         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1263         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192);
1264         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1265         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1266     }
1267 
1268     @Test
testAesCbcHmacSha512Tcp4UdpEncap()1269     public void testAesCbcHmacSha512Tcp4UdpEncap() throws Exception {
1270         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1271         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
1272         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1273         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1274     }
1275 
1276     @Test
testAesCbcHmacSha512Udp4UdpEncap()1277     public void testAesCbcHmacSha512Udp4UdpEncap() throws Exception {
1278         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1279         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256);
1280         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1281         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1282     }
1283 
1284     @Test
testAesCtrHmacSha512Tcp4UdpEncap()1285     public void testAesCtrHmacSha512Tcp4UdpEncap() throws Exception {
1286         assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
1287 
1288         final IpSecAlgorithm crypt = buildCryptAesCtr();
1289         final IpSecAlgorithm auth = buildAuthHmacSha512();
1290         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1291         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1292     }
1293 
1294     @Test
testAesCtrHmacSha512Udp4UdpEncap()1295     public void testAesCtrHmacSha512Udp4UdpEncap() throws Exception {
1296         assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR));
1297 
1298         final IpSecAlgorithm crypt = buildCryptAesCtr();
1299         final IpSecAlgorithm auth = buildAuthHmacSha512();
1300         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1301         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1302     }
1303 
1304     @Test
testAesCbcAesXCbcTcp4UdpEncap()1305     public void testAesCbcAesXCbcTcp4UdpEncap() throws Exception {
1306         assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
1307 
1308         final IpSecAlgorithm crypt = new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY);
1309         final IpSecAlgorithm auth = new IpSecAlgorithm(AUTH_AES_XCBC, getKey(128), 96);
1310         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1311         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1312     }
1313 
1314     @Test
testAesCbcAesXCbcUdp4UdpEncap()1315     public void testAesCbcAesXCbcUdp4UdpEncap() throws Exception {
1316         assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC));
1317 
1318         final IpSecAlgorithm crypt = new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY);
1319         final IpSecAlgorithm auth = new IpSecAlgorithm(AUTH_AES_XCBC, getKey(128), 96);
1320         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1321         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1322     }
1323 
1324     @Test
testAesCbcAesCmacTcp4UdpEncap()1325     public void testAesCbcAesCmacTcp4UdpEncap() throws Exception {
1326         assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
1327 
1328         final IpSecAlgorithm crypt = new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY);
1329         final IpSecAlgorithm auth = new IpSecAlgorithm(AUTH_AES_CMAC, getKey(128), 96);
1330         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1331         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1332     }
1333 
1334     @Test
testAesCbcAesCmacUdp4UdpEncap()1335     public void testAesCbcAesCmacUdp4UdpEncap() throws Exception {
1336         assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC));
1337 
1338         final IpSecAlgorithm crypt = new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY);
1339         final IpSecAlgorithm auth = new IpSecAlgorithm(AUTH_AES_CMAC, getKey(128), 96);
1340         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false);
1341         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true);
1342     }
1343 
1344     @Test
testAesGcm64Tcp4UdpEncap()1345     public void testAesGcm64Tcp4UdpEncap() throws Exception {
1346         IpSecAlgorithm authCrypt =
1347                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
1348         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
1349         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
1350     }
1351 
1352     @Test
testAesGcm64Udp4UdpEncap()1353     public void testAesGcm64Udp4UdpEncap() throws Exception {
1354         IpSecAlgorithm authCrypt =
1355                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64);
1356         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
1357         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
1358     }
1359 
1360     @Test
testAesGcm96Tcp4UdpEncap()1361     public void testAesGcm96Tcp4UdpEncap() throws Exception {
1362         IpSecAlgorithm authCrypt =
1363                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
1364         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
1365         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
1366     }
1367 
1368     @Test
testAesGcm96Udp4UdpEncap()1369     public void testAesGcm96Udp4UdpEncap() throws Exception {
1370         IpSecAlgorithm authCrypt =
1371                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96);
1372         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
1373         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
1374     }
1375 
1376     @Test
testAesGcm128Tcp4UdpEncap()1377     public void testAesGcm128Tcp4UdpEncap() throws Exception {
1378         IpSecAlgorithm authCrypt =
1379                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
1380         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
1381         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
1382     }
1383 
1384     @Test
testAesGcm128Udp4UdpEncap()1385     public void testAesGcm128Udp4UdpEncap() throws Exception {
1386         IpSecAlgorithm authCrypt =
1387                 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
1388         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
1389         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
1390     }
1391 
1392     @Test
testChaCha20Poly1305Tcp4UdpEncap()1393     public void testChaCha20Poly1305Tcp4UdpEncap() throws Exception {
1394         assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
1395 
1396         final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
1397         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
1398         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
1399     }
1400 
1401     @Test
testChaCha20Poly1305Udp4UdpEncap()1402     public void testChaCha20Poly1305Udp4UdpEncap() throws Exception {
1403         assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305));
1404 
1405         final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305();
1406         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false);
1407         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true);
1408     }
1409 
1410     @Test
testCryptUdp4()1411     public void testCryptUdp4() throws Exception {
1412         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1413         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, false, 1, false);
1414         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, false, 1, true);
1415     }
1416 
1417     @Test
testAuthUdp4()1418     public void testAuthUdp4() throws Exception {
1419         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
1420         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, false, 1, false);
1421         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, false, 1, true);
1422     }
1423 
1424     @Test
testCryptUdp6()1425     public void testCryptUdp6() throws Exception {
1426         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1427         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, null, null, false, 1, false);
1428         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, null, null, false, 1, true);
1429     }
1430 
1431     @Test
testAuthUdp6()1432     public void testAuthUdp6() throws Exception {
1433         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
1434         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, auth, null, false, 1, false);
1435         checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, auth, null, false, 1, true);
1436     }
1437 
1438     @Test
testCryptTcp4()1439     public void testCryptTcp4() throws Exception {
1440         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1441         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, false, 1, false);
1442         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, false, 1, true);
1443     }
1444 
1445     @Test
testAuthTcp4()1446     public void testAuthTcp4() throws Exception {
1447         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
1448         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, false, 1, false);
1449         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, false, 1, true);
1450     }
1451 
1452     @Test
testCryptTcp6()1453     public void testCryptTcp6() throws Exception {
1454         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1455         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, null, null, false, 1, false);
1456         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, null, null, false, 1, true);
1457     }
1458 
1459     @Test
testAuthTcp6()1460     public void testAuthTcp6() throws Exception {
1461         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
1462         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, auth, null, false, 1, false);
1463         checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, auth, null, false, 1, true);
1464     }
1465 
1466     @Test
testCryptUdp4UdpEncap()1467     public void testCryptUdp4UdpEncap() throws Exception {
1468         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1469         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, true, 1, false);
1470         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, true, 1, true);
1471     }
1472 
1473     @Test
testAuthUdp4UdpEncap()1474     public void testAuthUdp4UdpEncap() throws Exception {
1475         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
1476         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, true, 1, false);
1477         checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, true, 1, true);
1478     }
1479 
1480     @Test
testCryptTcp4UdpEncap()1481     public void testCryptTcp4UdpEncap() throws Exception {
1482         IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
1483         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, true, 1, false);
1484         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, true, 1, true);
1485     }
1486 
1487     @Test
testAuthTcp4UdpEncap()1488     public void testAuthTcp4UdpEncap() throws Exception {
1489         IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128);
1490         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, true, 1, false);
1491         checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, true, 1, true);
1492     }
1493 
1494     @Test
testOpenUdpEncapSocketSpecificPort()1495     public void testOpenUdpEncapSocketSpecificPort() throws Exception {
1496         IpSecManager.UdpEncapsulationSocket encapSocket = null;
1497         int port = -1;
1498         for (int i = 0; i < MAX_PORT_BIND_ATTEMPTS; i++) {
1499             try {
1500                 port = findUnusedPort();
1501                 encapSocket = mISM.openUdpEncapsulationSocket(port);
1502                 break;
1503             } catch (ErrnoException e) {
1504                 if (e.errno == OsConstants.EADDRINUSE) {
1505                     // Someone claimed the port since we called findUnusedPort.
1506                     continue;
1507                 }
1508                 throw e;
1509             } finally {
1510                 if (encapSocket != null) {
1511                     encapSocket.close();
1512                 }
1513             }
1514         }
1515 
1516         if (encapSocket == null) {
1517             fail("Failed " + MAX_PORT_BIND_ATTEMPTS + " attempts to bind to a port");
1518         }
1519 
1520         assertTrue("Returned invalid port", encapSocket.getPort() == port);
1521     }
1522 
1523     @Test
testOpenUdpEncapSocketRandomPort()1524     public void testOpenUdpEncapSocketRandomPort() throws Exception {
1525         try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
1526             assertTrue("Returned invalid port", encapSocket.getPort() != 0);
1527         }
1528     }
1529 }
1530