From 5e692b6ca7e6454ecf99321a1bfb9acd5152f7f9 Mon Sep 17 00:00:00 2001 From: Yan Yan Date: Tue, 11 Aug 2020 14:46:52 -0700 Subject: [PATCH 1/2] Add tests for new IPsec algorithms in IpSecManagerTest This CL adds CTS tests that: - Verify IpSecAlgorithm#getSupportedAlgorithms - Verify new algorithms are supported in device that first launched with SDK beyond R - Verify IpSecTransforms can be built with new algortihms and traffic flows Since there is no hardware that first launched with SDK beyond R at the time of writing this CL, tests for new algorithms were manually enabled and verified on the pixel with an updated kernel. Bug: 171083832 Test: atest IpSecManagerTest Change-Id: Icffbe67fca29b051457dbf863ba3aaf653806a83 --- .../src/android/net/cts/IpSecBaseTest.java | 50 +++- .../src/android/net/cts/IpSecManagerTest.java | 276 +++++++++++++++++- .../net/src/android/net/cts/PacketUtils.java | 20 +- tests/cts/net/util/Android.bp | 1 + .../android/net/cts/util/CtsNetUtils.java | 5 +- 5 files changed, 341 insertions(+), 11 deletions(-) diff --git a/tests/cts/net/src/android/net/cts/IpSecBaseTest.java b/tests/cts/net/src/android/net/cts/IpSecBaseTest.java index 10e43e7b6a..c54ee91065 100644 --- a/tests/cts/net/src/android/net/cts/IpSecBaseTest.java +++ b/tests/cts/net/src/android/net/cts/IpSecBaseTest.java @@ -16,6 +16,14 @@ package android.net.cts; +import static android.net.IpSecAlgorithm.AUTH_CRYPT_AES_GCM; +import static android.net.IpSecAlgorithm.AUTH_HMAC_MD5; +import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA1; +import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA256; +import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA384; +import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512; +import static android.net.IpSecAlgorithm.CRYPT_AES_CBC; + import static org.junit.Assert.assertArrayEquals; import android.content.Context; @@ -31,6 +39,12 @@ import android.util.Log; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; +import com.android.modules.utils.build.SdkLevel; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + import java.io.FileDescriptor; import java.io.IOException; import java.net.DatagramPacket; @@ -42,12 +56,10 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - @RunWith(AndroidJUnit4.class) public class IpSecBaseTest { @@ -71,6 +83,18 @@ public class IpSecBaseTest { 0x20, 0x21, 0x22, 0x23 }; + private static final Set MANDATORY_IPSEC_ALGOS_SINCE_P = new HashSet<>(); + + static { + MANDATORY_IPSEC_ALGOS_SINCE_P.add(CRYPT_AES_CBC); + MANDATORY_IPSEC_ALGOS_SINCE_P.add(AUTH_HMAC_MD5); + MANDATORY_IPSEC_ALGOS_SINCE_P.add(AUTH_HMAC_SHA1); + MANDATORY_IPSEC_ALGOS_SINCE_P.add(AUTH_HMAC_SHA256); + MANDATORY_IPSEC_ALGOS_SINCE_P.add(AUTH_HMAC_SHA384); + MANDATORY_IPSEC_ALGOS_SINCE_P.add(AUTH_HMAC_SHA512); + MANDATORY_IPSEC_ALGOS_SINCE_P.add(AUTH_CRYPT_AES_GCM); + } + protected static final byte[] AUTH_KEY = getKey(256); protected static final byte[] CRYPT_KEY = getKey(256); @@ -89,8 +113,24 @@ public class IpSecBaseTest { .getSystemService(Context.CONNECTIVITY_SERVICE); } + /** Checks if an IPsec algorithm is enabled on the device */ + protected static boolean hasIpSecAlgorithm(String algorithm) { + if (SdkLevel.isAtLeastS()) { + return IpSecAlgorithm.getSupportedAlgorithms().contains(algorithm); + } else { + return MANDATORY_IPSEC_ALGOS_SINCE_P.contains(algorithm); + } + } + + protected static byte[] getKeyBytes(int byteLength) { + return Arrays.copyOf(KEY_DATA, byteLength); + } + protected static byte[] getKey(int bitLength) { - return Arrays.copyOf(KEY_DATA, bitLength / 8); + if (bitLength % 8 != 0) { + throw new IllegalArgumentException("Invalid key length in bits" + bitLength); + } + return getKeyBytes(bitLength / 8); } protected static int getDomain(InetAddress address) { diff --git a/tests/cts/net/src/android/net/cts/IpSecManagerTest.java b/tests/cts/net/src/android/net/cts/IpSecManagerTest.java index d08f6e99c4..0fba0037aa 100644 --- a/tests/cts/net/src/android/net/cts/IpSecManagerTest.java +++ b/tests/cts/net/src/android/net/cts/IpSecManagerTest.java @@ -16,10 +16,30 @@ package android.net.cts; +import static android.net.IpSecAlgorithm.AUTH_AES_XCBC; +import static android.net.IpSecAlgorithm.AUTH_CRYPT_AES_GCM; +import static android.net.IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305; +import static android.net.IpSecAlgorithm.AUTH_HMAC_MD5; +import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA1; +import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA256; +import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA384; +import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512; +import static android.net.IpSecAlgorithm.CRYPT_AES_CBC; +import static android.net.IpSecAlgorithm.CRYPT_AES_CTR; import static android.net.cts.PacketUtils.AES_CBC_BLK_SIZE; import static android.net.cts.PacketUtils.AES_CBC_IV_LEN; +import static android.net.cts.PacketUtils.AES_CTR_BLK_SIZE; +import static android.net.cts.PacketUtils.AES_CTR_IV_LEN; +import static android.net.cts.PacketUtils.AES_CTR_KEY_LEN; import static android.net.cts.PacketUtils.AES_GCM_BLK_SIZE; import static android.net.cts.PacketUtils.AES_GCM_IV_LEN; +import static android.net.cts.PacketUtils.AES_XCBC_ICV_LEN; +import static android.net.cts.PacketUtils.AES_XCBC_KEY_LEN; +import static android.net.cts.PacketUtils.CHACHA20_POLY1305_BLK_SIZE; +import static android.net.cts.PacketUtils.CHACHA20_POLY1305_ICV_LEN; +import static android.net.cts.PacketUtils.CHACHA20_POLY1305_IV_LEN; +import static android.net.cts.PacketUtils.HMAC_SHA512_ICV_LEN; +import static android.net.cts.PacketUtils.HMAC_SHA512_KEY_LEN; import static android.net.cts.PacketUtils.IP4_HDRLEN; import static android.net.cts.PacketUtils.IP6_HDRLEN; import static android.net.cts.PacketUtils.TCP_HDRLEN_WITH_TIMESTAMP_OPT; @@ -27,15 +47,20 @@ import static android.net.cts.PacketUtils.UDP_HDRLEN; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; +import static com.android.compatibility.common.util.PropertyUtil.getFirstApiLevel; +import static com.android.compatibility.common.util.PropertyUtil.getVendorApiLevel; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; import android.net.IpSecAlgorithm; import android.net.IpSecManager; import android.net.IpSecTransform; import android.net.TrafficStats; +import android.os.Build; import android.platform.test.annotations.AppModeFull; import android.system.ErrnoException; import android.system.Os; @@ -44,8 +69,11 @@ import android.system.OsConstants; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; +import com.android.testutils.DevSdkIgnoreRule; +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; import com.android.testutils.SkipPresubmit; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -56,10 +84,15 @@ import java.net.DatagramSocket; import java.net.Inet6Address; import java.net.InetAddress; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; @RunWith(AndroidJUnit4.class) @AppModeFull(reason = "Socket cannot bind in instant app mode") public class IpSecManagerTest extends IpSecBaseTest { + @Rule public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(); private static final String TAG = IpSecManagerTest.class.getSimpleName(); @@ -417,8 +450,12 @@ public class IpSecManagerTest extends IpSecBaseTest { switch (cryptOrAead.getName()) { case IpSecAlgorithm.CRYPT_AES_CBC: return AES_CBC_IV_LEN; + case IpSecAlgorithm.CRYPT_AES_CTR: + return AES_CTR_IV_LEN; case IpSecAlgorithm.AUTH_CRYPT_AES_GCM: return AES_GCM_IV_LEN; + case IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305: + return CHACHA20_POLY1305_IV_LEN; default: throw new IllegalArgumentException( "IV length unknown for algorithm" + cryptOrAead.getName()); @@ -433,8 +470,12 @@ public class IpSecManagerTest extends IpSecBaseTest { switch (cryptOrAead.getName()) { case IpSecAlgorithm.CRYPT_AES_CBC: return AES_CBC_BLK_SIZE; + case IpSecAlgorithm.CRYPT_AES_CTR: + return AES_CTR_BLK_SIZE; case IpSecAlgorithm.AUTH_CRYPT_AES_GCM: return AES_GCM_BLK_SIZE; + case IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305: + return CHACHA20_POLY1305_BLK_SIZE; default: throw new IllegalArgumentException( "Blk size unknown for algorithm" + cryptOrAead.getName()); @@ -516,7 +557,6 @@ public class IpSecManagerTest extends IpSecBaseTest { int blkSize, int truncLenBits) throws Exception { - int innerPacketSize = TEST_DATA.length + transportHdrLen + ipHdrLen; int outerPacketSize = PacketUtils.calculateEspPacketSize( @@ -663,6 +703,40 @@ public class IpSecManagerTest extends IpSecBaseTest { // checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, true, 1000); // } + @IgnoreUpTo(Build.VERSION_CODES.R) + @Test + public void testGetSupportedAlgorithms() throws Exception { + final Map algoToRequiredMinSdk = new HashMap<>(); + algoToRequiredMinSdk.put(CRYPT_AES_CBC, Build.VERSION_CODES.P); + algoToRequiredMinSdk.put(AUTH_HMAC_MD5, Build.VERSION_CODES.P); + algoToRequiredMinSdk.put(AUTH_HMAC_SHA1, Build.VERSION_CODES.P); + algoToRequiredMinSdk.put(AUTH_HMAC_SHA256, Build.VERSION_CODES.P); + algoToRequiredMinSdk.put(AUTH_HMAC_SHA384, Build.VERSION_CODES.P); + algoToRequiredMinSdk.put(AUTH_HMAC_SHA512, Build.VERSION_CODES.P); + algoToRequiredMinSdk.put(AUTH_CRYPT_AES_GCM, Build.VERSION_CODES.P); + + // TODO: b/170424293 Use Build.VERSION_CODES.S when is finalized + algoToRequiredMinSdk.put(CRYPT_AES_CTR, Build.VERSION_CODES.R + 1); + algoToRequiredMinSdk.put(AUTH_AES_XCBC, Build.VERSION_CODES.R + 1); + algoToRequiredMinSdk.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.R + 1); + + final Set supportedAlgos = IpSecAlgorithm.getSupportedAlgorithms(); + + // Verify all supported algorithms are valid + for (String algo : supportedAlgos) { + assertTrue("Found invalid algo " + algo, algoToRequiredMinSdk.keySet().contains(algo)); + } + + // Verify all mandatory algorithms are supported + for (Entry entry : algoToRequiredMinSdk.entrySet()) { + if (Math.min(getFirstApiLevel(), getVendorApiLevel()) >= entry.getValue()) { + assertTrue( + "Fail to support " + entry.getKey(), + supportedAlgos.contains(entry.getKey())); + } + } + } + @Test public void testInterfaceCountersUdp4() throws Exception { IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); @@ -849,6 +923,106 @@ public class IpSecManagerTest extends IpSecBaseTest { checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); } + private static IpSecAlgorithm buildCryptAesCtr() throws Exception { + return new IpSecAlgorithm(CRYPT_AES_CTR, getKeyBytes(AES_CTR_KEY_LEN)); + } + + private static IpSecAlgorithm buildAuthHmacSha512() throws Exception { + return new IpSecAlgorithm( + AUTH_HMAC_SHA512, getKeyBytes(HMAC_SHA512_KEY_LEN), HMAC_SHA512_ICV_LEN * 8); + } + + @Test + public void testAesCtrHmacSha512Tcp4() throws Exception { + assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR)); + + final IpSecAlgorithm crypt = buildCryptAesCtr(); + final IpSecAlgorithm auth = buildAuthHmacSha512(); + checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false); + checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true); + } + + @Test + @SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec") + public void testAesCtrHmacSha512Tcp6() throws Exception { + assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR)); + + final IpSecAlgorithm crypt = buildCryptAesCtr(); + final IpSecAlgorithm auth = buildAuthHmacSha512(); + checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false); + checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); + } + + @Test + public void testAesCtrHmacSha512Udp4() throws Exception { + assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR)); + + final IpSecAlgorithm crypt = buildCryptAesCtr(); + final IpSecAlgorithm auth = buildAuthHmacSha512(); + checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false); + checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true); + } + + @Test + public void testAesCtrHmacSha512Udp6() throws Exception { + assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR)); + + final IpSecAlgorithm crypt = buildCryptAesCtr(); + final IpSecAlgorithm auth = buildAuthHmacSha512(); + checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false); + checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); + } + + private static IpSecAlgorithm buildCryptAesCbc() throws Exception { + return new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY); + } + + private static IpSecAlgorithm buildAuthAesXcbc() throws Exception { + return new IpSecAlgorithm( + AUTH_AES_XCBC, getKeyBytes(AES_XCBC_KEY_LEN), AES_XCBC_ICV_LEN * 8); + } + + @Test + public void testAesCbcAesXCbcTcp4() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC)); + + final IpSecAlgorithm crypt = buildCryptAesCbc(); + final IpSecAlgorithm auth = buildAuthAesXcbc(); + checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false); + checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true); + } + + @Test + @SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec") + public void testAesCbcAesXCbcTcp6() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC)); + + final IpSecAlgorithm crypt = buildCryptAesCbc(); + final IpSecAlgorithm auth = buildAuthAesXcbc(); + checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false); + checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); + } + + @Test + public void testAesCbcAesXCbcUdp4() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC)); + + final IpSecAlgorithm crypt = buildCryptAesCbc(); + final IpSecAlgorithm auth = buildAuthAesXcbc(); + checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false); + checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true); + } + + @Test + public void testAesCbcAesXCbcUdp6() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC)); + + final IpSecAlgorithm crypt = buildCryptAesCbc(); + final IpSecAlgorithm auth = buildAuthAesXcbc(); + checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false); + checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); + } + @Test public void testAesGcm64Tcp4() throws Exception { IpSecAlgorithm authCrypt = @@ -948,6 +1122,48 @@ public class IpSecManagerTest extends IpSecBaseTest { checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true); } + private static IpSecAlgorithm buildAuthCryptChaCha20Poly1305() throws Exception { + return new IpSecAlgorithm( + AUTH_CRYPT_CHACHA20_POLY1305, AEAD_KEY, CHACHA20_POLY1305_ICV_LEN * 8); + } + + @Test + public void testChaCha20Poly1305Tcp4() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305)); + + final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305(); + checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false); + checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true); + } + + @Test + @SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec") + public void testChaCha20Poly1305Tcp6() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305)); + + final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305(); + checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false); + checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true); + } + + @Test + public void testChaCha20Poly1305Udp4() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305)); + + final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305(); + checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false); + checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true); + } + + @Test + public void testChaCha20Poly1305Udp6() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305)); + + final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305(); + checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false); + checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true); + } + @Test public void testAesCbcHmacMd5Tcp4UdpEncap() throws Exception { IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); @@ -1028,6 +1244,46 @@ public class IpSecManagerTest extends IpSecBaseTest { checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); } + @Test + public void testAesCtrHmacSha512Tcp4UdpEncap() throws Exception { + assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR)); + + final IpSecAlgorithm crypt = buildCryptAesCtr(); + final IpSecAlgorithm auth = buildAuthHmacSha512(); + checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false); + checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); + } + + @Test + public void testAesCtrHmacSha512Udp4UdpEncap() throws Exception { + assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR)); + + final IpSecAlgorithm crypt = buildCryptAesCtr(); + final IpSecAlgorithm auth = buildAuthHmacSha512(); + checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false); + checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); + } + + @Test + public void testAesCbcAesXCbcTcp4UdpEncap() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC)); + + final IpSecAlgorithm crypt = new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY); + final IpSecAlgorithm auth = new IpSecAlgorithm(AUTH_AES_XCBC, getKey(128), 96); + checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false); + checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); + } + + @Test + public void testAesCbcAesXCbcUdp4UdpEncap() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC)); + + final IpSecAlgorithm crypt = new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY); + final IpSecAlgorithm auth = new IpSecAlgorithm(AUTH_AES_XCBC, getKey(128), 96); + checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false); + checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); + } + @Test public void testAesGcm64Tcp4UdpEncap() throws Exception { IpSecAlgorithm authCrypt = @@ -1076,6 +1332,24 @@ public class IpSecManagerTest extends IpSecBaseTest { checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true); } + @Test + public void testChaCha20Poly1305Tcp4UdpEncap() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305)); + + final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305(); + checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false); + checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true); + } + + @Test + public void testChaCha20Poly1305Udp4UdpEncap() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305)); + + final IpSecAlgorithm authCrypt = buildAuthCryptChaCha20Poly1305(); + checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false); + checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true); + } + @Test public void testCryptUdp4() throws Exception { IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); diff --git a/tests/cts/net/src/android/net/cts/PacketUtils.java b/tests/cts/net/src/android/net/cts/PacketUtils.java index 0aedecb5ad..54a70d0c34 100644 --- a/tests/cts/net/src/android/net/cts/PacketUtils.java +++ b/tests/cts/net/src/android/net/cts/PacketUtils.java @@ -43,17 +43,33 @@ public class PacketUtils { static final int UDP_HDRLEN = 8; static final int TCP_HDRLEN = 20; static final int TCP_HDRLEN_WITH_TIMESTAMP_OPT = TCP_HDRLEN + 12; + static final int ESP_BLK_SIZE = 4; // ESP has to be 4-byte aligned // Not defined in OsConstants static final int IPPROTO_IPV4 = 4; static final int IPPROTO_ESP = 50; // Encryption parameters - static final int AES_GCM_IV_LEN = 8; static final int AES_CBC_IV_LEN = 16; - static final int AES_GCM_BLK_SIZE = 4; static final int AES_CBC_BLK_SIZE = 16; + static final int AES_CTR_KEY_LEN = 20; + static final int AES_CTR_BLK_SIZE = ESP_BLK_SIZE; + static final int AES_CTR_IV_LEN = 8; + + // AEAD parameters + static final int AES_GCM_IV_LEN = 8; + static final int AES_GCM_BLK_SIZE = 4; + static final int CHACHA20_POLY1305_BLK_SIZE = ESP_BLK_SIZE; + static final int CHACHA20_POLY1305_IV_LEN = 8; + static final int CHACHA20_POLY1305_ICV_LEN = 16; + + // Authentication parameters + static final int HMAC_SHA512_KEY_LEN = 64; + static final int HMAC_SHA512_ICV_LEN = 32; + static final int AES_XCBC_KEY_LEN = 16; + static final int AES_XCBC_ICV_LEN = 12; + // Encryption algorithms static final String AES = "AES"; static final String AES_CBC = "AES/CBC/NoPadding"; diff --git a/tests/cts/net/util/Android.bp b/tests/cts/net/util/Android.bp index 88a206858d..b5f1208a4d 100644 --- a/tests/cts/net/util/Android.bp +++ b/tests/cts/net/util/Android.bp @@ -26,5 +26,6 @@ java_library { "compatibility-device-util-axt", "junit", "net-tests-utils", + "modules-utils-build", ], } diff --git a/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java b/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java index d5a26c4f62..1fbe3b894d 100644 --- a/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java +++ b/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java @@ -23,6 +23,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_TEST; import static android.net.wifi.WifiManager.SCAN_RESULTS_AVAILABLE_ACTION; +import static com.android.compatibility.common.util.PropertyUtil.getFirstApiLevel; import static com.android.testutils.TestPermissionUtil.runAsShell; import static org.junit.Assert.assertEquals; @@ -55,7 +56,6 @@ import android.net.wifi.WifiManager; import android.os.Binder; import android.os.Build; import android.os.IBinder; -import android.os.SystemProperties; import android.provider.Settings; import android.system.Os; import android.system.OsConstants; @@ -116,8 +116,7 @@ public final class CtsNetUtils { /** Checks if FEATURE_IPSEC_TUNNELS is enabled on the device */ public boolean hasIpsecTunnelsFeature() { return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS) - || SystemProperties.getInt("ro.product.first_api_level", 0) - >= Build.VERSION_CODES.Q; + || getFirstApiLevel() >= Build.VERSION_CODES.Q; } /** From 0891de63113ef91c2520ab103ae0690564a438a9 Mon Sep 17 00:00:00 2001 From: Yan Yan Date: Mon, 8 Feb 2021 20:55:41 -0800 Subject: [PATCH 2/2] Add CTS for AES-CMAC This commit: - Verify AES-CMAC is supported in device that first launched with SDK beyond R - Verify IpSecTransforms can be built with AES-CMAC and traffic flows Bug: 171083832 Test: atest IpSecManagerTest Test: AES-CMAC tests are manually enabled and verified Change-Id: I00d1aa475033810a5f60f0e3fc692be87ff62e13 --- .../src/android/net/cts/IpSecManagerTest.java | 70 +++++++++++++++++++ .../net/src/android/net/cts/PacketUtils.java | 2 + 2 files changed, 72 insertions(+) diff --git a/tests/cts/net/src/android/net/cts/IpSecManagerTest.java b/tests/cts/net/src/android/net/cts/IpSecManagerTest.java index 0fba0037aa..e7e1d67dbc 100644 --- a/tests/cts/net/src/android/net/cts/IpSecManagerTest.java +++ b/tests/cts/net/src/android/net/cts/IpSecManagerTest.java @@ -16,6 +16,7 @@ package android.net.cts; +import static android.net.IpSecAlgorithm.AUTH_AES_CMAC; import static android.net.IpSecAlgorithm.AUTH_AES_XCBC; import static android.net.IpSecAlgorithm.AUTH_CRYPT_AES_GCM; import static android.net.IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305; @@ -28,6 +29,8 @@ import static android.net.IpSecAlgorithm.CRYPT_AES_CBC; import static android.net.IpSecAlgorithm.CRYPT_AES_CTR; import static android.net.cts.PacketUtils.AES_CBC_BLK_SIZE; import static android.net.cts.PacketUtils.AES_CBC_IV_LEN; +import static android.net.cts.PacketUtils.AES_CMAC_ICV_LEN; +import static android.net.cts.PacketUtils.AES_CMAC_KEY_LEN; import static android.net.cts.PacketUtils.AES_CTR_BLK_SIZE; import static android.net.cts.PacketUtils.AES_CTR_IV_LEN; import static android.net.cts.PacketUtils.AES_CTR_KEY_LEN; @@ -717,6 +720,7 @@ public class IpSecManagerTest extends IpSecBaseTest { // TODO: b/170424293 Use Build.VERSION_CODES.S when is finalized algoToRequiredMinSdk.put(CRYPT_AES_CTR, Build.VERSION_CODES.R + 1); + algoToRequiredMinSdk.put(AUTH_AES_CMAC, Build.VERSION_CODES.R + 1); algoToRequiredMinSdk.put(AUTH_AES_XCBC, Build.VERSION_CODES.R + 1); algoToRequiredMinSdk.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.R + 1); @@ -982,6 +986,11 @@ public class IpSecManagerTest extends IpSecBaseTest { AUTH_AES_XCBC, getKeyBytes(AES_XCBC_KEY_LEN), AES_XCBC_ICV_LEN * 8); } + private static IpSecAlgorithm buildAuthAesCmac() throws Exception { + return new IpSecAlgorithm( + AUTH_AES_CMAC, getKeyBytes(AES_CMAC_KEY_LEN), AES_CMAC_ICV_LEN * 8); + } + @Test public void testAesCbcAesXCbcTcp4() throws Exception { assumeTrue(hasIpSecAlgorithm(AUTH_AES_XCBC)); @@ -1023,6 +1032,47 @@ public class IpSecManagerTest extends IpSecBaseTest { checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); } + @Test + public void testAesCbcAesCmacTcp4() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC)); + + final IpSecAlgorithm crypt = buildCryptAesCbc(); + final IpSecAlgorithm auth = buildAuthAesCmac(); + checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false); + checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true); + } + + @Test + @SkipPresubmit(reason = "b/186608065 - kernel 5.10 regression in TrafficStats with ipsec") + public void testAesCbcAesCmacTcp6() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC)); + + final IpSecAlgorithm crypt = buildCryptAesCbc(); + final IpSecAlgorithm auth = buildAuthAesCmac(); + checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false); + checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); + } + + @Test + public void testAesCbcAesCmacUdp4() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC)); + + final IpSecAlgorithm crypt = buildCryptAesCbc(); + final IpSecAlgorithm auth = buildAuthAesCmac(); + checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false); + checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true); + } + + @Test + public void testAesCbcAesCmacUdp6() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC)); + + final IpSecAlgorithm crypt = buildCryptAesCbc(); + final IpSecAlgorithm auth = buildAuthAesCmac(); + checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false); + checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); + } + @Test public void testAesGcm64Tcp4() throws Exception { IpSecAlgorithm authCrypt = @@ -1284,6 +1334,26 @@ public class IpSecManagerTest extends IpSecBaseTest { checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); } + @Test + public void testAesCbcAesCmacTcp4UdpEncap() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC)); + + final IpSecAlgorithm crypt = new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY); + final IpSecAlgorithm auth = new IpSecAlgorithm(AUTH_AES_CMAC, getKey(128), 96); + checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false); + checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); + } + + @Test + public void testAesCbcAesCmacUdp4UdpEncap() throws Exception { + assumeTrue(hasIpSecAlgorithm(AUTH_AES_CMAC)); + + final IpSecAlgorithm crypt = new IpSecAlgorithm(CRYPT_AES_CBC, CRYPT_KEY); + final IpSecAlgorithm auth = new IpSecAlgorithm(AUTH_AES_CMAC, getKey(128), 96); + checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false); + checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); + } + @Test public void testAesGcm64Tcp4UdpEncap() throws Exception { IpSecAlgorithm authCrypt = diff --git a/tests/cts/net/src/android/net/cts/PacketUtils.java b/tests/cts/net/src/android/net/cts/PacketUtils.java index 54a70d0c34..7e622f658a 100644 --- a/tests/cts/net/src/android/net/cts/PacketUtils.java +++ b/tests/cts/net/src/android/net/cts/PacketUtils.java @@ -69,6 +69,8 @@ public class PacketUtils { static final int HMAC_SHA512_ICV_LEN = 32; static final int AES_XCBC_KEY_LEN = 16; static final int AES_XCBC_ICV_LEN = 12; + static final int AES_CMAC_KEY_LEN = 16; + static final int AES_CMAC_ICV_LEN = 12; // Encryption algorithms static final String AES = "AES";