diff options
Diffstat (limited to 'tests/iketests/src/java/com/android/ike/ikev2/message/IkeKePayloadTest.java')
-rw-r--r-- | tests/iketests/src/java/com/android/ike/ikev2/message/IkeKePayloadTest.java | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeKePayloadTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeKePayloadTest.java new file mode 100644 index 00000000..1bb0b709 --- /dev/null +++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeKePayloadTest.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2018 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.message; + +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 com.android.ike.ikev2.IkeDhParams; +import com.android.ike.ikev2.SaProposal; +import com.android.ike.ikev2.exceptions.InvalidSyntaxException; +import com.android.ike.ikev2.utils.BigIntegerUtils; + +import org.junit.Test; + +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.Arrays; + +import javax.crypto.spec.DHPrivateKeySpec; + +public final class IkeKePayloadTest { + private static final String KE_PAYLOAD_GENERIC_HEADER = "28000088"; + private static final String KE_PAYLOAD_RAW_PACKET = + "00020000b4a2faf4bb54878ae21d638512ece55d9236fc50" + + "46ab6cef82220f421f3ce6361faf36564ecb6d28798a94aa" + + "d7b2b4b603ddeaaa5630adb9ece8ac37534036040610ebdd" + + "92f46bef84f0be7db860351843858f8acf87056e272377f7" + + "0c9f2d81e29c7b0ce4f291a3a72476bb0b278fd4b7b0a4c2" + + "6bbeb08214c7071376079587"; + + private static final boolean CRITICAL_BIT = false; + + @IkePayload.PayloadType + private static final int NEXT_PAYLOAD_TYPE = IkePayload.PAYLOAD_TYPE_NONCE; + + private static final int EXPECTED_DH_GROUP = SaProposal.DH_GROUP_1024_BIT_MODP; + + private static final int EXPECTED_KE_DATA_LEN = 128; + + private static final String KEY_EXCHANGE_DATA_RAW_PACKET = + "b4a2faf4bb54878ae21d638512ece55d9236fc5046ab6cef" + + "82220f421f3ce6361faf36564ecb6d28798a94aad7b2b4b6" + + "03ddeaaa5630adb9ece8ac37534036040610ebdd92f46bef" + + "84f0be7db860351843858f8acf87056e272377f70c9f2d81" + + "e29c7b0ce4f291a3a72476bb0b278fd4b7b0a4c26bbeb082" + + "14c7071376079587"; + + private static final String PRIME_1024_BIT_MODP_160_SUBGROUP = + "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6" + + "9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0" + + "13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70" + + "98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0" + + "A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708" + + "DF1FB2BC2E4A4371"; + private static final String GENERATOR_1024_BIT_MODP_160_SUBGROUP = + "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507F" + + "D6406CFF14266D31266FEA1E5C41564B777E690F5504F213" + + "160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1" + + "909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A" + + "D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24" + + "855E6EEB22B3B2E5"; + private static final String PRIVATE_KEY_LOCAL = "B9A3B3AE8FEFC1A2930496507086F8455D48943E"; + private static final String PUBLIC_KEY_REMOTE = + "717A6CB053371FF4A3B932941C1E5663F861A1D6AD34AE66" + + "576DFB98F6C6CBF9DDD5A56C7833F6BCFDFF095582AD868E" + + "440E8D09FD769E3CECCDC3D3B1E4CFA057776CAAF9739B6A" + + "9FEE8E7411F8D6DAC09D6A4EDB46CC2B5D5203090EAE6126" + + "311E53FD2C14B574E6A3109A3DA1BE41BDCEAA186F5CE067" + + "16A2B6A07B3C33FE"; + private static final String EXPECTED_SHARED_KEY = + "5C804F454D30D9C4DF85271F93528C91DF6B48AB5F80B3B5" + + "9CAAC1B28F8ACBA9CD3E39F3CB614525D9521D2E644C53B8" + + "07B810F340062F257D7D6FBFE8D5E8F072E9B6E9AFDA9413" + + "EAFB2E8B0699B1FB5A0CACEDDEAEAD7E9CFBB36AE2B42083" + + "5BD83A19FB0B5E96BF8FA4D09E345525167ECD9155416F46" + + "F408ED31B63C6E6D"; + private static final String KEY_EXCHANGE_ALGORITHM = "DH"; + + @Test + public void testDecodeIkeKePayload() throws Exception { + byte[] inputPacket = TestUtils.hexStringToByteArray(KE_PAYLOAD_RAW_PACKET); + + IkeKePayload payload = new IkeKePayload(CRITICAL_BIT, inputPacket); + + assertFalse(payload.isOutbound); + assertEquals(EXPECTED_DH_GROUP, payload.dhGroup); + + byte[] keyExchangeData = TestUtils.hexStringToByteArray(KEY_EXCHANGE_DATA_RAW_PACKET); + assertEquals(keyExchangeData.length, payload.keyExchangeData.length); + for (int i = 0; i < keyExchangeData.length; i++) { + assertEquals(keyExchangeData[i], payload.keyExchangeData[i]); + } + } + + @Test + public void testDecodeIkeKePayloadWithInvalidKeData() throws Exception { + // Cut bytes of KE data from original KE payload + String badKeyPayloadPacket = + KE_PAYLOAD_RAW_PACKET.substring(0, KE_PAYLOAD_RAW_PACKET.length() - 2); + byte[] inputPacket = TestUtils.hexStringToByteArray(badKeyPayloadPacket); + + try { + IkeKePayload payload = new IkeKePayload(CRITICAL_BIT, inputPacket); + fail("Expected InvalidSyntaxException: KE data length doesn't match its DH group type"); + } catch (InvalidSyntaxException expected) { + } + } + + @Test + public void testEncodeIkeKePayload() throws Exception { + byte[] inputPacket = TestUtils.hexStringToByteArray(KE_PAYLOAD_RAW_PACKET); + IkeKePayload payload = new IkeKePayload(CRITICAL_BIT, inputPacket); + + ByteBuffer byteBuffer = ByteBuffer.allocate(payload.getPayloadLength()); + payload.encodeToByteBuffer(NEXT_PAYLOAD_TYPE, byteBuffer); + + byte[] expectedKePayload = + TestUtils.hexStringToByteArray(KE_PAYLOAD_GENERIC_HEADER + KE_PAYLOAD_RAW_PACKET); + assertArrayEquals(expectedKePayload, byteBuffer.array()); + } + + @Test + public void testGetIkeKePayload() throws Exception { + IkeKePayload payload = new IkeKePayload(SaProposal.DH_GROUP_1024_BIT_MODP); + + // Test DHPrivateKeySpec + assertTrue(payload.isOutbound); + DHPrivateKeySpec privateKeySpec = payload.localPrivateKey; + + BigInteger primeValue = privateKeySpec.getP(); + BigInteger expectedPrimeValue = new BigInteger(IkeDhParams.PRIME_1024_BIT_MODP, 16); + assertEquals(0, expectedPrimeValue.compareTo(primeValue)); + + BigInteger genValue = privateKeySpec.getG(); + BigInteger expectedGenValue = BigInteger.valueOf(IkeDhParams.BASE_GENERATOR_MODP); + assertEquals(0, expectedGenValue.compareTo(genValue)); + + // Test IkeKePayload + assertEquals(EXPECTED_DH_GROUP, payload.dhGroup); + assertEquals(EXPECTED_KE_DATA_LEN, payload.keyExchangeData.length); + } + + // Since we didn't find test data for DH group types supported in current IKE library, we use + // test data for "1024-bit MODP Group with 160-bit Prime Order Subgroup" from RFC 5114. The main + // difference is that it uses weaker Prime and Generator values and requires more complicated + // recipient test in real Key Exchange process. But it is suitable for testing. + @Test + public void testGetSharedkey() throws Exception { + BigInteger primeValue = + BigIntegerUtils.unsignedHexStringToBigInteger(PRIME_1024_BIT_MODP_160_SUBGROUP); + BigInteger baseGenValue = + BigIntegerUtils.unsignedHexStringToBigInteger(GENERATOR_1024_BIT_MODP_160_SUBGROUP); + BigInteger privateKeyValue = + BigIntegerUtils.unsignedHexStringToBigInteger(PRIVATE_KEY_LOCAL); + byte[] remotePublicKey = TestUtils.hexStringToByteArray(PUBLIC_KEY_REMOTE); + + DHPrivateKeySpec privateKeySpec = + new DHPrivateKeySpec(privateKeyValue, primeValue, baseGenValue); + byte[] sharedKeyBytes = IkeKePayload.getSharedKey(privateKeySpec, remotePublicKey); + + byte[] expectedSharedKeyBytes = TestUtils.hexStringToByteArray(EXPECTED_SHARED_KEY); + assertTrue(Arrays.equals(expectedSharedKeyBytes, sharedKeyBytes)); + } +} |