From 0c6027964803f0528ddd4bf9bddf5d2abcfa8941 Mon Sep 17 00:00:00 2001 From: Yan Yan Date: Tue, 11 Aug 2020 17:34:46 -0700 Subject: [PATCH] Verify kernel implementation of AES-CTR This CL adds a test to verify kernel implementation of AES-CTR Since there is no hardware that first launched with SDK beyond R at the time of writing this CL, new tests for AES-CTR were manually enabled and verified on coral (coral-kernel already supports AES-CTR) Bug: 171083832 Test: atest IpSecAlgorithmImplTest Change-Id: Ib626a6c3999b7d682d0858e92d0dbb5138fdc45d --- .../net/cts/IpSecAlgorithmImplTest.java | 44 +++++++++++++++++++ .../src/android/net/cts/IpSecManagerTest.java | 4 +- .../net/src/android/net/cts/PacketUtils.java | 39 ++++++++++++++-- 3 files changed, 81 insertions(+), 6 deletions(-) diff --git a/tests/cts/net/src/android/net/cts/IpSecAlgorithmImplTest.java b/tests/cts/net/src/android/net/cts/IpSecAlgorithmImplTest.java index 3b110a4f4c..73dc80c62d 100644 --- a/tests/cts/net/src/android/net/cts/IpSecAlgorithmImplTest.java +++ b/tests/cts/net/src/android/net/cts/IpSecAlgorithmImplTest.java @@ -17,6 +17,14 @@ package android.net.cts; import static android.net.IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305; +import static android.net.IpSecAlgorithm.CRYPT_AES_CTR; +import static android.net.cts.PacketUtils.AES_CTR; +import static android.net.cts.PacketUtils.AES_CTR_BLK_SIZE; +import static android.net.cts.PacketUtils.AES_CTR_IV_LEN; +import static android.net.cts.PacketUtils.AES_CTR_KEY_LEN_20; +import static android.net.cts.PacketUtils.AES_CTR_KEY_LEN_28; +import static android.net.cts.PacketUtils.AES_CTR_KEY_LEN_36; +import static android.net.cts.PacketUtils.AES_CTR_SALT_LEN; import static android.net.cts.PacketUtils.CHACHA20_POLY1305; import static android.net.cts.PacketUtils.CHACHA20_POLY1305_BLK_SIZE; import static android.net.cts.PacketUtils.CHACHA20_POLY1305_ICV_LEN; @@ -43,6 +51,7 @@ import android.net.cts.PacketUtils.EspAeadCipher; import android.net.cts.PacketUtils.EspAuth; import android.net.cts.PacketUtils.EspAuthNull; import android.net.cts.PacketUtils.EspCipher; +import android.net.cts.PacketUtils.EspCryptCipher; import android.net.cts.PacketUtils.EspHeader; import android.net.cts.PacketUtils.IpHeader; import android.net.cts.PacketUtils.UdpHeader; @@ -194,6 +203,41 @@ public class IpSecAlgorithmImplTest extends IpSecBaseTest { } } + private void checkAesCtr(int keyLen) throws Exception { + final byte[] cryptKey = getKeyBytes(keyLen); + + final IpSecAlgorithm ipsecEncryptAlgo = + new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CTR, cryptKey); + final EspCipher espCipher = + new EspCryptCipher( + AES_CTR, AES_CTR_BLK_SIZE, cryptKey, AES_CTR_IV_LEN, AES_CTR_SALT_LEN); + + runWithShellPermissionIdentity(new TestNetworkRunnable(new CheckCryptoImplTest( + ipsecEncryptAlgo, null /* ipsecAuthAlgo */, null /* ipsecAeadAlgo */, + espCipher, EspAuthNull.getInstance()))); + } + + @Test + public void testAesCtr160() throws Exception { + assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR)); + + checkAesCtr(AES_CTR_KEY_LEN_20); + } + + @Test + public void testAesCtr224() throws Exception { + assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR)); + + checkAesCtr(AES_CTR_KEY_LEN_28); + } + + @Test + public void testAesCtr288() throws Exception { + assumeTrue(hasIpSecAlgorithm(CRYPT_AES_CTR)); + + checkAesCtr(AES_CTR_KEY_LEN_36); + } + @Test public void testChaCha20Poly1305() throws Exception { assumeTrue(hasIpSecAlgorithm(AUTH_CRYPT_CHACHA20_POLY1305)); diff --git a/tests/cts/net/src/android/net/cts/IpSecManagerTest.java b/tests/cts/net/src/android/net/cts/IpSecManagerTest.java index e7e1d67dbc..5f79a3e22c 100644 --- a/tests/cts/net/src/android/net/cts/IpSecManagerTest.java +++ b/tests/cts/net/src/android/net/cts/IpSecManagerTest.java @@ -33,7 +33,7 @@ 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; +import static android.net.cts.PacketUtils.AES_CTR_KEY_LEN_20; import static android.net.cts.PacketUtils.AES_GCM_BLK_SIZE; import static android.net.cts.PacketUtils.AES_GCM_IV_LEN; import static android.net.cts.PacketUtils.AES_XCBC_ICV_LEN; @@ -928,7 +928,7 @@ public class IpSecManagerTest extends IpSecBaseTest { } private static IpSecAlgorithm buildCryptAesCtr() throws Exception { - return new IpSecAlgorithm(CRYPT_AES_CTR, getKeyBytes(AES_CTR_KEY_LEN)); + return new IpSecAlgorithm(CRYPT_AES_CTR, getKeyBytes(AES_CTR_KEY_LEN_20)); } private static IpSecAlgorithm buildAuthHmacSha512() throws Exception { diff --git a/tests/cts/net/src/android/net/cts/PacketUtils.java b/tests/cts/net/src/android/net/cts/PacketUtils.java index 27c9f3b00c..6b409f2b92 100644 --- a/tests/cts/net/src/android/net/cts/PacketUtils.java +++ b/tests/cts/net/src/android/net/cts/PacketUtils.java @@ -54,8 +54,11 @@ public class PacketUtils { // Encryption parameters static final int AES_CBC_IV_LEN = 16; static final int AES_CBC_BLK_SIZE = 16; + static final int AES_CTR_SALT_LEN = 4; - static final int AES_CTR_KEY_LEN = 20; + static final int AES_CTR_KEY_LEN_20 = 20; + static final int AES_CTR_KEY_LEN_28 = 28; + static final int AES_CTR_KEY_LEN_36 = 36; static final int AES_CTR_BLK_SIZE = ESP_BLK_SIZE; static final int AES_CTR_IV_LEN = 8; @@ -77,9 +80,13 @@ public class PacketUtils { static final int AES_CMAC_KEY_LEN = 16; static final int AES_CMAC_ICV_LEN = 12; + // Block counter field should be 32 bits and starts from value one as per RFC 3686 + static final byte[] AES_CTR_INITIAL_COUNTER = new byte[] {0x00, 0x00, 0x00, 0x01}; + // Encryption algorithms static final String AES = "AES"; static final String AES_CBC = "AES/CBC/NoPadding"; + static final String AES_CTR = "AES/CTR/NoPadding"; // AEAD algorithms static final String CHACHA20_POLY1305 = "ChaCha20/Poly1305/NoPadding"; @@ -552,14 +559,38 @@ public class PacketUtils { public static class EspCryptCipher extends EspCipher { public EspCryptCipher(String algoName, int blockSize, byte[] key, int ivLen) { - super(algoName, blockSize, key, ivLen, SALT_LEN_UNUSED); + this(algoName, blockSize, key, ivLen, SALT_LEN_UNUSED); + } + + public EspCryptCipher(String algoName, int blockSize, byte[] key, int ivLen, int saltLen) { + super(algoName, blockSize, key, ivLen, saltLen); } @Override public byte[] getCipherText(int nextHeader, byte[] payload, int spi, int seqNum) throws GeneralSecurityException { - final IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); - final SecretKeySpec secretKeySpec = new SecretKeySpec(key, algoName); + final IvParameterSpec ivParameterSpec; + final SecretKeySpec secretKeySpec; + + if (AES_CBC.equals(algoName)) { + ivParameterSpec = new IvParameterSpec(iv); + secretKeySpec = new SecretKeySpec(key, algoName); + } else if (AES_CTR.equals(algoName)) { + // Provided key consists of encryption/decryption key plus 4-byte salt. Salt is used + // with ESP payload IV and initial block counter value to build IvParameterSpec. + final byte[] secretKey = Arrays.copyOfRange(key, 0, key.length - saltLen); + final byte[] salt = Arrays.copyOfRange(key, secretKey.length, key.length); + secretKeySpec = new SecretKeySpec(secretKey, algoName); + + final ByteBuffer ivParameterBuffer = + ByteBuffer.allocate(iv.length + saltLen + AES_CTR_INITIAL_COUNTER.length); + ivParameterBuffer.put(salt); + ivParameterBuffer.put(iv); + ivParameterBuffer.put(AES_CTR_INITIAL_COUNTER); + ivParameterSpec = new IvParameterSpec(ivParameterBuffer.array()); + } else { + throw new IllegalArgumentException("Invalid algorithm " + algoName); + } // Encrypt payload final Cipher cipher = Cipher.getInstance(algoName);