diff options
Diffstat (limited to 'tests/iketests/src/java/com/android')
6 files changed, 524 insertions, 38 deletions
diff --git a/tests/iketests/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptionsTest.java b/tests/iketests/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptionsTest.java index a67d44f9..5ed6480c 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptionsTest.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptionsTest.java @@ -20,8 +20,12 @@ import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.AF_INET6; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_ADDRESS; +import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_DNS; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_NETMASK; +import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_SUBNET; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP6_ADDRESS; +import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP6_DNS; +import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP6_SUBNET; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -52,6 +56,11 @@ public final class TunnelModeChildSessionOptionsTest { private static final Inet6Address IPV6_ADDRESS = (Inet6Address) (InetAddressUtils.parseNumericAddress("2001:db8::1")); + private static final Inet4Address IPV4_DNS_SERVER = + (Inet4Address) (InetAddressUtils.parseNumericAddress("8.8.8.8")); + private static final Inet6Address IPV6_DNS_SERVER = + (Inet6Address) (InetAddressUtils.parseNumericAddress("2001:4860:4860::8888")); + private ChildSaProposal mSaProposal; @Before @@ -130,4 +139,43 @@ public final class TunnelModeChildSessionOptionsTest { } } + + @Test + public void testBuildChildSessionOptionsWithDnsServerReq() { + TunnelModeChildSessionOptions childOptions = + new TunnelModeChildSessionOptions.Builder() + .addSaProposal(mSaProposal) + .addInternalDnsServerRequest(AF_INET, 1) + .addInternalDnsServerRequest(AF_INET6, 1) + .addInternalDnsServerRequest(IPV4_DNS_SERVER) + .addInternalDnsServerRequest(IPV6_DNS_SERVER) + .build(); + + verifyCommon(childOptions); + + SparseArray<Integer> exptectedAttrCntMap = new SparseArray<>(); + exptectedAttrCntMap.put(CONFIG_ATTR_INTERNAL_IP4_DNS, 2); + exptectedAttrCntMap.put(CONFIG_ATTR_INTERNAL_IP6_DNS, 2); + + verifyAttrTypes(exptectedAttrCntMap, childOptions); + } + + @Test + public void testBuildChildSessionOptionsWithSubnetReq() { + TunnelModeChildSessionOptions childOptions = + new TunnelModeChildSessionOptions.Builder() + .addSaProposal(mSaProposal) + .addInternalSubnetRequest(AF_INET, 1) + .addInternalSubnetRequest(AF_INET6, 1) + .build(); + + verifyCommon(childOptions); + + SparseArray<Integer> exptectedAttrCntMap = new SparseArray<>(); + exptectedAttrCntMap.put(CONFIG_ATTR_INTERNAL_IP4_SUBNET, 1); + exptectedAttrCntMap.put(CONFIG_ATTR_INTERNAL_IP6_SUBNET, 1); + + verifyAttrTypes(exptectedAttrCntMap, childOptions); + } } + diff --git a/tests/iketests/src/java/com/android/ike/ikev2/crypto/IkeCombinedModeCipherTest.java b/tests/iketests/src/java/com/android/ike/ikev2/crypto/IkeCombinedModeCipherTest.java new file mode 100644 index 00000000..a7ff2990 --- /dev/null +++ b/tests/iketests/src/java/com/android/ike/ikev2/crypto/IkeCombinedModeCipherTest.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.ike.ikev2.crypto; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import android.net.IpSecAlgorithm; + +import com.android.ike.TestUtils; +import com.android.ike.ikev2.SaProposal; +import com.android.ike.ikev2.message.IkeMessage; +import com.android.ike.ikev2.message.IkeSaPayload.EncryptionTransform; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.util.Arrays; +import java.util.Random; + +import javax.crypto.AEADBadTagException; + +@RunWith(JUnit4.class) +public final class IkeCombinedModeCipherTest { + private static final String IV = "fbd69d9de2dafc5e"; + private static final String ENCRYPTED_PADDED_DATA_WITH_CHECKSUM = + "f4109834e9f3559758c05edf119917521b885f67f0d14ced43"; + private static final String UNENCRYPTED_PADDED_DATA = "000000080000400f00"; + private static final String ADDITIONAL_AUTH_DATA = + "77c708b4523e39a471dc683c1d4f21362e202508000000060000004129000025"; + private static final String KEY = + "7C04513660DEC572D896105254EF92608054F8E6EE19E79CE52AB8697B2B5F2C2AA90C29"; + + private static final int AES_GCM_IV_LEN = 8; + private static final int AES_GCM_16_CHECKSUM_LEN = 128; + + private IkeCombinedModeCipher mAesGcm16Cipher; + + private byte[] mAesGcmKey; + private byte[] mIv; + private byte[] mEncryptedPaddedDataWithChecksum; + private byte[] mUnencryptedPaddedData; + private byte[] mAdditionalAuthData; + + @Before + public void setUp() { + mAesGcm16Cipher = + (IkeCombinedModeCipher) + IkeCipher.create( + new EncryptionTransform( + SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16, + SaProposal.KEY_LEN_AES_256), + IkeMessage.getSecurityProvider()); + + mAesGcmKey = TestUtils.hexStringToByteArray(KEY); + mIv = TestUtils.hexStringToByteArray(IV); + mEncryptedPaddedDataWithChecksum = + TestUtils.hexStringToByteArray(ENCRYPTED_PADDED_DATA_WITH_CHECKSUM); + mUnencryptedPaddedData = TestUtils.hexStringToByteArray(UNENCRYPTED_PADDED_DATA); + mAdditionalAuthData = TestUtils.hexStringToByteArray(ADDITIONAL_AUTH_DATA); + } + + @Test + public void testBuild() throws Exception { + assertTrue(mAesGcm16Cipher.isAead()); + assertEquals(AES_GCM_IV_LEN, mAesGcm16Cipher.generateIv().length); + } + + @Test + public void testGenerateRandomIv() throws Exception { + assertFalse(Arrays.equals(mAesGcm16Cipher.generateIv(), mAesGcm16Cipher.generateIv())); + } + + @Test + public void testEncrypt() throws Exception { + byte[] calculatedData = + mAesGcm16Cipher.encrypt( + mUnencryptedPaddedData, mAdditionalAuthData, mAesGcmKey, mIv); + + assertArrayEquals(mEncryptedPaddedDataWithChecksum, calculatedData); + } + + @Test + public void testDecrypt() throws Exception { + byte[] calculatedData = + mAesGcm16Cipher.decrypt( + mEncryptedPaddedDataWithChecksum, mAdditionalAuthData, mAesGcmKey, mIv); + + assertArrayEquals(mUnencryptedPaddedData, calculatedData); + } + + @Test + public void testEncryptWithWrongKeyLen() throws Exception { + byte[] encryptionKey = TestUtils.hexStringToByteArray(KEY + "00"); + + try { + mAesGcm16Cipher.encrypt( + mUnencryptedPaddedData, mAdditionalAuthData, encryptionKey, mIv); + fail("Expected to fail because encryption key has wrong length."); + } catch (IllegalArgumentException expected) { + + } + } + + @Test + public void testDecrypWithWrongKey() throws Exception { + byte[] encryptionKey = new byte[mAesGcmKey.length]; + new Random().nextBytes(encryptionKey); + + try { + mAesGcm16Cipher.decrypt( + mEncryptedPaddedDataWithChecksum, mAdditionalAuthData, encryptionKey, mIv); + fail("Expected to fail because decryption key is wrong"); + } catch (AEADBadTagException expected) { + + } + } + + @Test + public void testBuildIpSecAlgorithm() throws Exception { + IpSecAlgorithm ipsecAlgorithm = mAesGcm16Cipher.buildIpSecAlgorithmWithKey(mAesGcmKey); + + IpSecAlgorithm expectedIpSecAlgorithm = + new IpSecAlgorithm( + IpSecAlgorithm.AUTH_CRYPT_AES_GCM, mAesGcmKey, AES_GCM_16_CHECKSUM_LEN); + + assertTrue(IpSecAlgorithm.equals(expectedIpSecAlgorithm, ipsecAlgorithm)); + } + + @Test + public void buildIpSecAlgorithmWithInvalidKey() throws Exception { + byte[] encryptionKey = TestUtils.hexStringToByteArray(KEY + "00"); + + try { + mAesGcm16Cipher.buildIpSecAlgorithmWithKey(encryptionKey); + fail("Expected to fail because encryption key has wrong length."); + } catch (IllegalArgumentException expected) { + + } + } +} diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthDigitalSignPayloadTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthDigitalSignPayloadTest.java index 52f9259a..239bd504 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthDigitalSignPayloadTest.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthDigitalSignPayloadTest.java @@ -16,6 +16,8 @@ package com.android.ike.ikev2.message; +import static com.android.ike.ikev2.message.IkeAuthDigitalSignPayload.SIGNATURE_ALGO_RSA_SHA2_256; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -31,6 +33,7 @@ import com.android.ike.ikev2.testutils.CertUtils; import org.junit.Before; import org.junit.Test; +import java.security.PrivateKey; import java.security.cert.X509Certificate; public final class IkeAuthDigitalSignPayloadTest { @@ -92,9 +95,7 @@ public final class IkeAuthDigitalSignPayloadTest { assertTrue(payload instanceof IkeAuthDigitalSignPayload); IkeAuthDigitalSignPayload dsPayload = (IkeAuthDigitalSignPayload) payload; - assertEquals( - IkeAuthDigitalSignPayload.SIGNATURE_ALGO_RSA_SHA2_256, - dsPayload.signatureAlgoAndHash); + assertEquals(SIGNATURE_ALGO_RSA_SHA2_256, dsPayload.signatureAlgoAndHash); assertArrayEquals(dsPayload.signature, TestUtils.hexStringToByteArray(SIGNATURE)); } @@ -136,7 +137,24 @@ public final class IkeAuthDigitalSignPayloadTest { PRF_RESP_KEY); fail("Expected to fail due to wrong certificate."); } catch (AuthenticationFailedException expected) { - } } + + @Test + public void testGenerateSignature() throws Exception { + PrivateKey key = CertUtils.createRsaPrivateKeyFromKeyFile("end-cert-key-a.key"); + + IkeAuthDigitalSignPayload authPayload = + new IkeAuthDigitalSignPayload( + SIGNATURE_ALGO_RSA_SHA2_256, + key, + IKE_INIT_RESP_REQUEST, + NONCE_INIT_RESP, + ID_RESP_PAYLOAD_BODY, + mIkeHmacSha1Prf, + PRF_RESP_KEY); + + assertEquals(SIGNATURE_ALGO_RSA_SHA2_256, authPayload.signatureAlgoAndHash); + assertArrayEquals(authPayload.signature, TestUtils.hexStringToByteArray(SIGNATURE)); + } } diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeConfigPayloadTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeConfigPayloadTest.java index 9ee6a620..e8a67d79 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeConfigPayloadTest.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeConfigPayloadTest.java @@ -17,6 +17,7 @@ package com.android.ike.ikev2.message; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_ADDRESS; +import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_DHCP; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_DNS; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_NETMASK; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_SUBNET; @@ -47,6 +48,7 @@ import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttrIpv4AddressBase; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttrIpv6AddrRangeBase; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttribute; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Address; +import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Dhcp; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Dns; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Netmask; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Subnet; @@ -104,6 +106,13 @@ public final class IkeConfigPayloadTest { private static final byte[] IPV4_DNS_ATTRIBUTE_WITHOUT_VALUE = TestUtils.hexStringToByteArray("00030000"); + private static final Inet4Address IPV4_DHCP = + (Inet4Address) (InetAddressUtils.parseNumericAddress("192.0.2.200")); + private static final byte[] IPV4_DHCP_ATTRIBUTE_WITH_VALUE = + TestUtils.hexStringToByteArray("00060004c00002c8"); + private static final byte[] IPV4_DHCP_ATTRIBUTE_WITHOUT_VALUE = + TestUtils.hexStringToByteArray("00060000"); + private static final byte[] IPV4_SUBNET_ATTRIBUTE_VALUE = TestUtils.hexStringToByteArray("c0000264fffffff0"); private static final byte[] IPV4_SUBNET_ATTRIBUTE_WITH_VALUE = @@ -420,6 +429,44 @@ public final class IkeConfigPayloadTest { } @Test + public void testDecodeIpv4DhcpWithValue() throws Exception { + ConfigAttributeIpv4Dhcp attribute = new ConfigAttributeIpv4Dhcp(IPV4_DHCP.getAddress()); + + assertEquals(CONFIG_ATTR_INTERNAL_IP4_DHCP, attribute.attributeType); + assertEquals(IPV4_DHCP, attribute.address); + } + + @Test + public void testDecodeIpv4DhcpWithoutValue() throws Exception { + ConfigAttributeIpv4Dhcp attribute = new ConfigAttributeIpv4Dhcp(new byte[0]); + + assertEquals(CONFIG_ATTR_INTERNAL_IP4_DHCP, attribute.attributeType); + assertNull(attribute.address); + } + + @Test + public void testEncodeIpv4DhcpWithValue() throws Exception { + ConfigAttributeIpv4Dhcp attributeIp4Dhcp = new ConfigAttributeIpv4Dhcp(IPV4_DHCP); + + verifyEncodeIpv4AddresBaseAttribute( + attributeIp4Dhcp, + CONFIG_ATTR_INTERNAL_IP4_DHCP, + IPV4_DHCP_ATTRIBUTE_WITH_VALUE, + IPV4_DHCP); + } + + @Test + public void testEncodeIpv4DhcpWithoutValue() throws Exception { + ConfigAttributeIpv4Dhcp attribute = new ConfigAttributeIpv4Dhcp(); + + verifyEncodeIpv4AddresBaseAttribute( + attribute, + CONFIG_ATTR_INTERNAL_IP4_DHCP, + IPV4_DHCP_ATTRIBUTE_WITHOUT_VALUE, + null /*expectedAddress*/); + } + + @Test public void testDecodeIpv4SubnetWithValue() throws Exception { ConfigAttributeIpv4Subnet attributeIp4Subnet = new ConfigAttributeIpv4Subnet(IPV4_SUBNET_ATTRIBUTE_VALUE); @@ -450,18 +497,6 @@ public final class IkeConfigPayloadTest { } @Test - public void testEncodeIpv4SubnetWithValue() throws Exception { - ConfigAttributeIpv4Subnet attributeIp4Subnet = - new ConfigAttributeIpv4Subnet(IPV4_LINK_ADDRESS); - - verifyBuildAndEncodeAttributeCommon( - attributeIp4Subnet, - CONFIG_ATTR_INTERNAL_IP4_SUBNET, - IPV4_SUBNET_ATTRIBUTE_WITH_VALUE); - assertEquals(IPV4_LINK_ADDRESS, attributeIp4Subnet.linkAddress); - } - - @Test public void testEncodeIpv4SubnetWithoutValue() throws Exception { ConfigAttributeIpv4Subnet attributeIp4Subnet = new ConfigAttributeIpv4Subnet(); @@ -559,18 +594,6 @@ public final class IkeConfigPayloadTest { } @Test - public void testEncodeIpv6SubnetWithValue() throws Exception { - ConfigAttributeIpv6Subnet attributeIp6Subnet = - new ConfigAttributeIpv6Subnet(IPV6_LINK_ADDRESS); - - verifyEncodeIpv6RangeBaseAttribute( - attributeIp6Subnet, - CONFIG_ATTR_INTERNAL_IP6_SUBNET, - IPV6_SUBNET_ATTRIBUTE_WITH_VALUE, - IPV6_LINK_ADDRESS); - } - - @Test public void testEncodeIpv6SubnetWithoutValue() throws Exception { ConfigAttributeIpv6Subnet attributeIp6Subnet = new ConfigAttributeIpv6Subnet(); diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeEncryptedPayloadBodyTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeEncryptedPayloadBodyTest.java index 24e9e986..c43a8594 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeEncryptedPayloadBodyTest.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeEncryptedPayloadBodyTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.fail; import com.android.ike.TestUtils; import com.android.ike.ikev2.SaProposal; import com.android.ike.ikev2.crypto.IkeCipher; +import com.android.ike.ikev2.crypto.IkeCombinedModeCipher; import com.android.ike.ikev2.crypto.IkeMacIntegrity; import com.android.ike.ikev2.crypto.IkeNormalModeCipher; import com.android.ike.ikev2.message.IkeSaPayload.EncryptionTransform; @@ -34,7 +35,6 @@ import java.security.GeneralSecurityException; import java.util.Arrays; public final class IkeEncryptedPayloadBodyTest { - private static final String IKE_AUTH_INIT_REQUEST_HEADER = "5f54bf6d8b48e6e1909232b3d1edcb5c2e20230800000001000000ec"; private static final String IKE_AUTH_INIT_REQUEST_SK_HEADER = "230000d0"; @@ -83,6 +83,85 @@ public final class IkeEncryptedPayloadBodyTest { private static final String HMAC_SHA1_3DES_MSG_INTE_KEY = "867a0bd019108db856cf6984fc9fb62d70c0de74"; + // TODO: b/142753861 Test IKE fragment protected by AES_CBC instead of 3DES + + // Test vectors for IKE fragment protected by HmacSha1 and 3DES + private static final String HMAC_SHA1_3DES_FRAG_HEX_STRING = + "939ae1251d18eb9077a99551b15c6e933520232000000001" + + "000000c0000000a400050005fd7c7931705af184b7be76bb" + + "d45a8ecbb3ffd58b9438b93f67e9fe86b06229f80e9b52d2" + + "ff6afde3f2c13ae93ce55a801f62e1a818c9003880a36bbe" + + "986fe6979ba233b9f4f0ddc992d06dbad5a2b998be18fae9" + + "47e5ccfb37775d069344e711fbf499bb289cf4cca245bd45" + + "0ad89d18689207759507ba18d47247e920b9e000a25a7596" + + "e4130929e5cdc37d5c1b0d90bbaae946c260f4d3cf815f6d"; + private static final String HMAC_SHA1_3DES_FRAG_DECRYPTED_BODY_HEX_STRING = + "54ebd95c572100002002000000000100040a0a0a01000300" + + "040808080800030004080804042c00002c00000028020304" + + "03cc86090a0300000c0100000c800e010003000008030000" + + "0200000008050000002d00001801000000070000100000ff" + + "ff0a0a0a010a0a0a010000001801000000070000100000ff" + + "ff00000000ffffffff"; + private static final String HMAC_SHA1_3DES_FRAG_IV = "fd7c7931705af184"; + private static final String HMAC_SHA1_3DES_FRAG_PADDING = "dcf0fa5e2b64"; + + private static final int HMAC_SHA1_3DES_FRAGMENT_NUM = 5; + private static final int HMAC_SHA1_3DES_TOTAL_FRAGMENTS = 5; + + private static final String HMAC_SHA1_3DES_FRAG_ENCR_KEY = + "6BBF6CB3526D6492F4DA0AF45E9B9FD3E1FF534280352073"; + private static final String HMAC_SHA1_3DES_FRAG_INTE_KEY = + "293449E8E518060780B9C06F15838A06EEF57814"; + + // Test vectors for IKE message protected by AES_GCM_16 + private static final String AES_GCM_MSG_HEX_STRING = + "77c708b4523e39a471dc683c1d4f21362e20230800000005" + + "0000006127000045fbd69d9ee2dafc5e7c03a0106761065b2" + + "8fa8d11aed6046f7f8af117e44da7635be6e0dfafcb0a387c" + + "53fb46ba5d6fa9509161915929de97b7fbe23dc65723b0fe"; + private static final String AES_GCM_MSG_DECRYPTED_BODY_HEX_STRING = + "000000280200000033233837e909ec805d56151bef5b1fa9b8e25b32419c9b3fc96ee699ec29d501"; + private static final String AES_GCM_MSG_IV = "fbd69d9ee2dafc5e"; + private static final String AES_GCM_MSG_ENCR_KEY = + "7C04513660DEC572D896105254EF92608054F8E6EE19E79CE52AB8697B2B5F2C2AA90C29"; + + // Test vectors for IKE fragment protected by AES_GCM_16 + private static final String AES_GCM_FRAG_HEX_STRING = + "77c708b4523e39a471dc683c1d4f213635202320000000010" + + "0000113000000f7000200026faf9e5c04c67571871681d443" + + "01489f99fd78d318b0517a5a99bf6a3e1770f43d7d997c9e0" + + "d186038d16df3fd525eda821f80b3a40fc6bce397ac67539e" + + "40042919a5e9af38c70881d092a8571f0e131f594c0e8d6b8" + + "4ea116f0c95619439b0a267b35bc47dac72bbfb3d3776feb3" + + "86d7d4f819b0248f52f60bf4371ab6384e37819a9685c27d8" + + "e41abe30cd6f60905dd5c05c351ec0a1fcf9b99360161d2f3" + + "4dcf6401829df9392121d88e2201d279200e25d750678af6a" + + "7f4892a5c8d4a7358ec50cdf12cfa7652488f756ba6d07441" + + "e9a27aad3976ac8a705ff796857cb2df9ce360c3992e0285b" + + "34834255b06"; + private static final String AES_GCM_FRAG_DECRYPTED_BODY_HEX_STRING = + "0fce6e996f4936ec8db8097339c371c686be75f4bed3f259c" + + "14d39c3ad90cb864085c6375f75b724d9f9daa8e7b22a106a" + + "488bc48c081997b7416fd33b146882e51ff6a640edf760212" + + "7f2454d502e92262ba3dd07cff52ee1bb1ea85f582db41a68" + + "aaf6dace362e5d8b10cfeb65eebc7572690e2c415a11cae57" + + "020810cf7aa56d9f2d5c2be3a633f8e4c6af5483a2b1f05bd" + + "4340ab551ddf7f51def57eaf5a37793ff6aa1e1ec288a2adf" + + "a647c369f15efa61a619966a320f24e1765c0e00c5ed394aa" + + "ef14512032b005827c000000090100000501"; + private static final String AES_GCM_FRAG_IV = "6faf9e5c04c67571"; + + private static final int AES_GCM_FRAGMENT_NUM = 2; + private static final int AES_GCM_TOTAL_FRAGMENTS = 2; + + private static final String AES_GCM_FRAG_ENCR_KEY = + "955ED949D6F18857220E97B17D9285C830A39F8D4DC46AB43943668093C62A3D66664F8C"; + + private static final int ENCRYPTED_BODY_SK_OFFSET = + IkeHeader.IKE_HEADER_LENGTH + IkePayload.GENERIC_HEADER_LENGTH; + private static final int ENCRYPTED_BODY_SKF_OFFSET = + ENCRYPTED_BODY_SK_OFFSET + IkeSkfPayload.SKF_HEADER_LEN; + private IkeNormalModeCipher mAesCbcCipher; private byte[] mAesCbcKey; @@ -98,7 +177,18 @@ public final class IkeEncryptedPayloadBodyTest { private byte[] mIv; private byte[] mPadding; - // TODO: Add tests for authenticating and decrypting received message. + private IkeNormalModeCipher m3DesCipher; + + private IkeCombinedModeCipher mAesGcm16Cipher; + + private byte[] mAesGcmMsgKey; + private byte[] mAesGcmMsg; + private byte[] mAesGcmUnencryptedData; + + private byte[] mAesGcmFragKey; + private byte[] mAesGcmFragMsg; + private byte[] mAesGcmFragUnencryptedData; + @Before public void setUp() throws Exception { mDataToPadAndEncrypt = @@ -123,6 +213,12 @@ public final class IkeEncryptedPayloadBodyTest { mIv = TestUtils.hexStringToByteArray(IKE_AUTH_INIT_REQUEST_IV); mPadding = TestUtils.hexStringToByteArray(IKE_AUTH_INIT_REQUEST_PADDING); + m3DesCipher = + (IkeNormalModeCipher) + IkeCipher.create( + new EncryptionTransform(SaProposal.ENCRYPTION_ALGORITHM_3DES), + IkeMessage.getSecurityProvider()); + mAesCbcCipher = (IkeNormalModeCipher) IkeCipher.create( @@ -137,6 +233,24 @@ public final class IkeEncryptedPayloadBodyTest { new IntegrityTransform(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96), IkeMessage.getSecurityProvider()); mHmacSha1IntegrityKey = TestUtils.hexStringToByteArray(INTE_KEY_FROM_INIT_TO_RESP); + + mAesGcm16Cipher = + (IkeCombinedModeCipher) + IkeCipher.create( + new EncryptionTransform( + SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16, + SaProposal.KEY_LEN_AES_256), + IkeMessage.getSecurityProvider()); + + mAesGcmMsgKey = TestUtils.hexStringToByteArray(AES_GCM_MSG_ENCR_KEY); + mAesGcmMsg = TestUtils.hexStringToByteArray(AES_GCM_MSG_HEX_STRING); + mAesGcmUnencryptedData = + TestUtils.hexStringToByteArray(AES_GCM_MSG_DECRYPTED_BODY_HEX_STRING); + + mAesGcmFragKey = TestUtils.hexStringToByteArray(AES_GCM_FRAG_ENCR_KEY); + mAesGcmFragMsg = TestUtils.hexStringToByteArray(AES_GCM_FRAG_HEX_STRING); + mAesGcmFragUnencryptedData = + TestUtils.hexStringToByteArray(AES_GCM_FRAG_DECRYPTED_BODY_HEX_STRING); } @Test @@ -217,6 +331,7 @@ public final class IkeEncryptedPayloadBodyTest { new IkeEncryptedPayloadBody( ikeHeader, IkePayload.PAYLOAD_TYPE_ID_INITIATOR, + new byte[0] /*skfHeader*/, mDataToPadAndEncrypt, mHmacSha1IntegrityMac, mAesCbcCipher, @@ -238,7 +353,7 @@ public final class IkeEncryptedPayloadBodyTest { IkeEncryptedPayloadBody payloadBody = new IkeEncryptedPayloadBody( mIkeMessage, - IkeHeader.IKE_HEADER_LENGTH + IkePayload.GENERIC_HEADER_LENGTH, + ENCRYPTED_BODY_SK_OFFSET, mHmacSha1IntegrityMac, mAesCbcCipher, mHmacSha1IntegrityKey, @@ -252,20 +367,122 @@ public final class IkeEncryptedPayloadBodyTest { byte[] message = TestUtils.hexStringToByteArray(HMAC_SHA1_3DES_MSG_HEX_STRING); byte[] expectedDecryptedData = TestUtils.hexStringToByteArray(HMAC_SHA1_3DES_DECRYPTED_BODY_HEX_STRING); - IkeCipher tripleDesCipher = - IkeCipher.create( - new EncryptionTransform(SaProposal.ENCRYPTION_ALGORITHM_3DES), - IkeMessage.getSecurityProvider()); IkeEncryptedPayloadBody payloadBody = new IkeEncryptedPayloadBody( message, - IkeHeader.IKE_HEADER_LENGTH + IkePayload.GENERIC_HEADER_LENGTH, + ENCRYPTED_BODY_SK_OFFSET, mHmacSha1IntegrityMac, - tripleDesCipher, + m3DesCipher, TestUtils.hexStringToByteArray(HMAC_SHA1_3DES_MSG_INTE_KEY), TestUtils.hexStringToByteArray(HMAC_SHA1_3DES_MSG_ENCR_KEY)); assertArrayEquals(expectedDecryptedData, payloadBody.getUnencryptedData()); } + + @Test + public void testBuildAndEncodeWithHmacSha13Des() throws Exception { + byte[] message = TestUtils.hexStringToByteArray(HMAC_SHA1_3DES_FRAG_HEX_STRING); + IkeHeader ikeHeader = new IkeHeader(message); + + byte[] skfHeaderBytes = + IkeSkfPayload.encodeSkfHeader( + HMAC_SHA1_3DES_FRAGMENT_NUM, HMAC_SHA1_3DES_TOTAL_FRAGMENTS); + + IkeEncryptedPayloadBody payloadBody = + new IkeEncryptedPayloadBody( + ikeHeader, + IkePayload.PAYLOAD_TYPE_NO_NEXT, + skfHeaderBytes, + TestUtils.hexStringToByteArray( + HMAC_SHA1_3DES_FRAG_DECRYPTED_BODY_HEX_STRING), + mHmacSha1IntegrityMac, + m3DesCipher, + TestUtils.hexStringToByteArray(HMAC_SHA1_3DES_FRAG_INTE_KEY), + TestUtils.hexStringToByteArray(HMAC_SHA1_3DES_FRAG_ENCR_KEY), + TestUtils.hexStringToByteArray(HMAC_SHA1_3DES_FRAG_IV), + TestUtils.hexStringToByteArray(HMAC_SHA1_3DES_FRAG_PADDING)); + + byte[] expectedEncodedData = + Arrays.copyOfRange(message, ENCRYPTED_BODY_SKF_OFFSET, message.length); + + assertArrayEquals(expectedEncodedData, payloadBody.encode()); + } + + @Test + public void testAuthAndDecodeFullMsgWithAesGcm() throws Exception { + IkeEncryptedPayloadBody encryptedBody = + new IkeEncryptedPayloadBody( + mAesGcmMsg, + ENCRYPTED_BODY_SK_OFFSET, + null /*integrityMac*/, + mAesGcm16Cipher, + null /*integrityKey*/, + mAesGcmMsgKey); + + assertArrayEquals(mAesGcmUnencryptedData, encryptedBody.getUnencryptedData()); + } + + @Test + public void testBuildAndEncodeMsgWithAesGcm() throws Exception { + IkeHeader ikeHeader = new IkeHeader(mAesGcmMsg); + + IkeEncryptedPayloadBody payloadBody = + new IkeEncryptedPayloadBody( + ikeHeader, + IkePayload.PAYLOAD_TYPE_AUTH, + new byte[0], + mAesGcmUnencryptedData, + null /*integrityMac*/, + mAesGcm16Cipher, + null /*integrityKey*/, + mAesGcmMsgKey, + TestUtils.hexStringToByteArray(AES_GCM_MSG_IV), + new byte[0] /*padding*/); + + byte[] expectedEncodedData = + Arrays.copyOfRange(mAesGcmMsg, ENCRYPTED_BODY_SK_OFFSET, mAesGcmMsg.length); + + assertArrayEquals(expectedEncodedData, payloadBody.encode()); + } + + @Test + public void testAuthAndDecodeFragMsgWithAesGcm() throws Exception { + IkeEncryptedPayloadBody encryptedBody = + new IkeEncryptedPayloadBody( + mAesGcmFragMsg, + ENCRYPTED_BODY_SKF_OFFSET, + null /*integrityMac*/, + mAesGcm16Cipher, + null /*integrityKey*/, + mAesGcmFragKey); + + assertArrayEquals(mAesGcmFragUnencryptedData, encryptedBody.getUnencryptedData()); + } + + @Test + public void testBuildAndEncodeFragMsgWithAesGcm() throws Exception { + IkeHeader ikeHeader = new IkeHeader(mAesGcmFragMsg); + byte[] skfHeaderBytes = + IkeSkfPayload.encodeSkfHeader(AES_GCM_FRAGMENT_NUM, AES_GCM_TOTAL_FRAGMENTS); + + IkeEncryptedPayloadBody payloadBody = + new IkeEncryptedPayloadBody( + ikeHeader, + IkePayload.PAYLOAD_TYPE_NO_NEXT, + skfHeaderBytes, + mAesGcmFragUnencryptedData, + null /*integrityMac*/, + mAesGcm16Cipher, + null /*integrityKey*/, + mAesGcmFragKey, + TestUtils.hexStringToByteArray(AES_GCM_FRAG_IV), + new byte[0] /*padding*/); + + byte[] expectedEncodedData = + Arrays.copyOfRange( + mAesGcmFragMsg, ENCRYPTED_BODY_SKF_OFFSET, mAesGcmFragMsg.length); + + assertArrayEquals(expectedEncodedData, payloadBody.encode()); + } } diff --git a/tests/iketests/src/java/com/android/ike/ikev2/testutils/CertUtils.java b/tests/iketests/src/java/com/android/ike/ikev2/testutils/CertUtils.java index e44551a0..e42e5647 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/testutils/CertUtils.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/testutils/CertUtils.java @@ -21,14 +21,21 @@ import android.content.Context; import androidx.test.InstrumentationRegistry; import com.android.ike.ikev2.message.IkeMessage; +import com.android.org.bouncycastle.util.io.pem.PemObject; +import com.android.org.bouncycastle.util.io.pem.PemReader; import java.io.InputStream; +import java.io.InputStreamReader; +import java.security.KeyFactory; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; +import java.security.spec.PKCS8EncodedKeySpec; -/** CertUtils provides utility methods for creating X509 certificate. */ +/** CertUtils provides utility methods for creating X509 certificate and private key. */ public final class CertUtils { private static final String PEM_FOLDER_NAME = "pem"; + private static final String KEY_FOLDER_NAME = "key"; /** Creates an X509Certificate with a pem file */ public static X509Certificate createCertFromPemFile(String fileName) throws Exception { @@ -40,4 +47,17 @@ public final class CertUtils { CertificateFactory.getInstance("X.509", IkeMessage.getSecurityProvider()); return (X509Certificate) factory.generateCertificate(inputStream); } + + /** Creates an private key from a PKCS8 format key file */ + public static RSAPrivateKey createRsaPrivateKeyFromKeyFile(String fileName) throws Exception { + Context context = InstrumentationRegistry.getContext(); + InputStream inputStream = + context.getResources().getAssets().open(KEY_FOLDER_NAME + "/" + fileName); + + PemObject pemObject = new PemReader(new InputStreamReader(inputStream)).readPemObject(); + + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + return (RSAPrivateKey) + keyFactory.generatePrivate(new PKCS8EncodedKeySpec(pemObject.getContent())); + } } |