diff options
Diffstat (limited to 'tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeMessageTest.java')
-rw-r--r-- | tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeMessageTest.java | 935 |
1 files changed, 0 insertions, 935 deletions
diff --git a/tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeMessageTest.java b/tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeMessageTest.java deleted file mode 100644 index 38b41527..00000000 --- a/tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeMessageTest.java +++ /dev/null @@ -1,935 +0,0 @@ -/* - * 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.internal.net.ipsec.ike.message; - -import static com.android.internal.net.ipsec.ike.message.IkeMessage.DECODE_STATUS_OK; -import static com.android.internal.net.ipsec.ike.message.IkeMessage.DECODE_STATUS_PROTECTED_ERROR; -import static com.android.internal.net.ipsec.ike.message.IkeMessage.DECODE_STATUS_UNPROTECTED_ERROR; -import static com.android.internal.net.ipsec.ike.message.IkePayload.PAYLOAD_TYPE_AUTH; -import static com.android.internal.net.ipsec.ike.message.IkePayload.PAYLOAD_TYPE_ID_INITIATOR; -import static com.android.internal.net.ipsec.ike.message.IkePayload.PAYLOAD_TYPE_NO_NEXT; -import static com.android.internal.net.ipsec.ike.message.IkeTestUtils.makeDummySkfPayload; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.net.ipsec.ike.exceptions.IkeException; -import android.net.ipsec.ike.exceptions.IkeInternalException; - -import com.android.internal.net.TestUtils; -import com.android.internal.net.ipsec.ike.SaRecord.IkeSaRecord; -import com.android.internal.net.ipsec.ike.crypto.IkeMacIntegrity; -import com.android.internal.net.ipsec.ike.crypto.IkeNormalModeCipher; -import com.android.internal.net.ipsec.ike.exceptions.InvalidMessageIdException; -import com.android.internal.net.ipsec.ike.exceptions.InvalidSyntaxException; -import com.android.internal.net.ipsec.ike.exceptions.UnsupportedCriticalPayloadException; -import com.android.internal.net.ipsec.ike.message.IkeMessage.DecodeResult; -import com.android.internal.net.ipsec.ike.message.IkeMessage.DecodeResultError; -import com.android.internal.net.ipsec.ike.message.IkeMessage.DecodeResultOk; -import com.android.internal.net.ipsec.ike.message.IkeMessage.DecodeResultPartial; -import com.android.internal.net.ipsec.ike.message.IkePayloadFactory.IIkePayloadDecoder; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.nio.ByteBuffer; -import java.security.GeneralSecurityException; -import java.util.Arrays; -import java.util.LinkedList; - -import javax.crypto.IllegalBlockSizeException; - -public final class IkeMessageTest { - private static final String IKE_SA_INIT_HEADER_RAW_PACKET = - "8f54bf6d8b48e6e10000000000000000212022080000000000000150"; - private static final String IKE_SA_INIT_BODY_RAW_PACKET = - "220000300000002c010100040300000c0100000c" - + "800e00800300000803000002030000080400000200000008" - + "020000022800008800020000b4a2faf4bb54878ae21d6385" - + "12ece55d9236fc5046ab6cef82220f421f3ce6361faf3656" - + "4ecb6d28798a94aad7b2b4b603ddeaaa5630adb9ece8ac37" - + "534036040610ebdd92f46bef84f0be7db860351843858f8a" - + "cf87056e272377f70c9f2d81e29c7b0ce4f291a3a72476bb" - + "0b278fd4b7b0a4c26bbeb08214c707137607958729000024" - + "c39b7f368f4681b89fa9b7be6465abd7c5f68b6ed5d3b4c7" - + "2cb4240eb5c464122900001c00004004e54f73b7d83f6beb" - + "881eab2051d8663f421d10b02b00001c00004005d915368c" - + "a036004cb578ae3e3fb268509aeab1900000002069936922" - + "8741c6d4ca094c93e242c9de19e7b7c60000000500000500"; - private static final String IKE_SA_INIT_RAW_PACKET = - IKE_SA_INIT_HEADER_RAW_PACKET + IKE_SA_INIT_BODY_RAW_PACKET; - - // Byte offsets of first payload type in IKE message header. - private static final int FIRST_PAYLOAD_TYPE_OFFSET = 16; - // Byte offsets of first payload's critical bit in IKE message body. - private static final int PAYLOAD_CRITICAL_BIT_OFFSET = 1; - // Byte offsets of first payload length in IKE message body. - private static final int FIRST_PAYLOAD_LENGTH_OFFSET = 2; - // Byte offsets of last payload length in IKE message body. - private static final int LAST_PAYLOAD_LENGTH_OFFSET = 278; - - private static final String IKE_AUTH_HEADER_HEX_STRING = - "5f54bf6d8b48e6e1909232b3d1edcb5c2e20230800000001000000ec"; - private static final String IKE_AUTH_BODY_HEX_STRING = - "230000d0b9132b7bb9f658dfdc648e5017a6322a030c316c" - + "e55f365760d46426ce5cfc78bd1ed9abff63eb9594c1bd58" - + "46de333ecd3ea2b705d18293b130395300ba92a351041345" - + "0a10525cea51b2753b4e92b081fd78d995659a98f742278f" - + "f9b8fd3e21554865c15c79a5134d66b2744966089e416c60" - + "a274e44a9a3f084eb02f3bdce1e7de9de8d9a62773ab563b" - + "9a69ba1db03c752acb6136452b8a86c41addb4210d68c423" - + "efed80e26edca5fa3fe5d0a5ca9375ce332c474b93fb1fa3" - + "59eb4e81ae6e0f22abdad69ba8007d50"; - - private static final String IKE_AUTH_EXPECTED_CHECKSUM_HEX_STRING = "ae6e0f22abdad69ba8007d50"; - private static final String IKE_AUTH_HEX_STRING = - IKE_AUTH_HEADER_HEX_STRING + IKE_AUTH_BODY_HEX_STRING; - - private static final String IKE_AUTH_UNENCRYPTED_PADDED_DATA_HEX_STRING = - "2400000c010000000a50500d2700000c010000000a505050" - + "2100001c02000000df7c038aefaaa32d3f44b228b52a3327" - + "44dfb2c12c00002c00000028010304032ad4c0a20300000c" - + "0100000c800e008003000008030000020000000805000000" - + "2d00001801000000070000100000ffff00000000ffffffff" - + "2900001801000000070000100000ffff00000000ffffffff" - + "29000008000040000000000c000040010000000100000000" - + "000000000000000b"; - - private static final String IKE_FRAG_HEX_STRING = - "939ae1251d18eb9077a99551b15c6e9335202320000000010000" - + "00c0000000a400020002fd7c7931705af184b7be76bbd45a" - + "8ecbb3ffd58b9438b93f67e9fe86b06229f80e9b52d2ff6a" - + "fde3f2c13ae93ce55a801f62e1a818c9003880a36bbe986f" - + "e6979ba233b9f4f0ddc992d06dbad5a2b998be18fae947e5" - + "ccfb37775d069344e711fbf499bb289cf4cca245bd450ad8" - + "9d18689207759507ba18d47247e920b9e000a25a7596e413" - + "0929e5cdc37d5c1b0d90bbaae946c260f4d3cf815f6d"; - private static final String ID_INIT_PAYLOAD_HEX_STRING = "2400000c010000000a50500d"; - private static final String ID_RESP_PAYLOAD_HEX_STRING = "0000000c010000000a505050"; - - private static final long INIT_SPI = 0x5f54bf6d8b48e6e1L; - private static final long RESP_SPI = 0x909232b3d1edcb5cL; - private static final String IKE_EMPTY_INFO_MSG_HEX_STRING = - "5f54bf6d8b48e6e1909232b3d1edcb5c2e20252800000000" - + "0000004c00000030e376871750fdba9f7012446c5dc3f97a" - + "f83b48ba0dbc68bcc4a78136832100aa4192f251cd4d1b97" - + "d298e550"; - private static final String IKE_EMPTY_INFO_MSG_IV_HEX_STRING = - "e376871750fdba9f7012446c5dc3f97a"; - private static final String IKE_EMPTY_INFO_MSG_ENCRYPTED_DATA_HEX_STRING = - "f83b48ba0dbc68bcc4a78136832100aa"; - private static final String IKE_EMPTY_INFO_MSG_CHECKSUM_HEX_STRING = "4192f251cd4d1b97d298e550"; - - private static final byte[] FRAGMENT_ONE_UNENCRYPTED_DATA = "fragmentOne".getBytes(); - private static final byte[] FRAGMENT_TWO_UNENCRYPTED_DATA = "fragmentTwo".getBytes(); - - private static final int TOTAL_FRAGMENTS = 2; - private static final int FRAGMENT_NUM_ONE = 1; - private static final int FRAGMENT_NUM_TWO = 2; - - private static final int IKE_FRAG_EXPECTED_MESSAGE_ID = 1; - - private static final int IKE_AUTH_EXPECTED_MESSAGE_ID = 1; - private static final int IKE_AUTH_CIPHER_IV_SIZE = 16; - private static final int IKE_AUTH_CIPHER_BLOCK_SIZE = 16; - private static final int IKE_AUTH_PAYLOAD_SIZE = 8; - - private byte[] mIkeAuthPacket; - private byte[] mUnencryptedPaddedData; - private IkeHeader mIkeAuthHeader; - - private IIkePayloadDecoder mSpyIkePayloadDecoder; - - private IkeMacIntegrity mMockIntegrity; - private IkeNormalModeCipher mMockCipher; - private IkeSaRecord mMockIkeSaRecord; - - private byte[] mIkeFragPacketOne; - private byte[] mIkeFragPacketTwo; - private IkeHeader mFragOneHeader; - private IkeHeader mFragTwoHeader; - - private IkeSkfPayload mDummySkfPayloadOne; - private IkeSkfPayload mDummySkfPayloadTwo; - - private static final int[] EXPECTED_IKE_INIT_PAYLOAD_LIST = { - IkePayload.PAYLOAD_TYPE_SA, - IkePayload.PAYLOAD_TYPE_KE, - IkePayload.PAYLOAD_TYPE_NONCE, - IkePayload.PAYLOAD_TYPE_NOTIFY, - IkePayload.PAYLOAD_TYPE_NOTIFY, - IkePayload.PAYLOAD_TYPE_VENDOR - }; - - class TestIkeSupportedPayload extends IkePayload { - TestIkeSupportedPayload(int payload, boolean critical) { - super(payload, critical); - } - - @Override - protected void encodeToByteBuffer(@PayloadType int nextPayload, ByteBuffer byteBuffer) { - throw new UnsupportedOperationException( - "It is not supported to encode " + getTypeString()); - } - - @Override - protected int getPayloadLength() { - throw new UnsupportedOperationException( - "It is not supported to get payload length of " + getTypeString()); - } - - @Override - public String getTypeString() { - return "Test(" + payloadType + ")"; - } - } - - @Before - public void setUp() throws Exception { - mSpyIkePayloadDecoder = spy(new IkePayloadFactory.IkePayloadDecoder()); - doAnswer( - (invocation) -> { - int payloadType = (int) invocation.getArguments()[0]; - boolean isCritical = (boolean) invocation.getArguments()[1]; - if (support(payloadType)) { - return new TestIkeSupportedPayload(payloadType, isCritical); - } - return new IkeUnsupportedPayload(payloadType, isCritical); - }) - .when(mSpyIkePayloadDecoder) - .decodeIkePayload(anyInt(), anyBoolean(), anyBoolean(), any()); - - IkePayloadFactory.sDecoderInstance = mSpyIkePayloadDecoder; - - mIkeAuthPacket = TestUtils.hexStringToByteArray(IKE_AUTH_HEX_STRING); - mUnencryptedPaddedData = - TestUtils.hexStringToByteArray(IKE_AUTH_UNENCRYPTED_PADDED_DATA_HEX_STRING); - mIkeAuthHeader = new IkeHeader(mIkeAuthPacket); - - mMockIntegrity = mock(IkeMacIntegrity.class); - byte[] expectedChecksum = - TestUtils.hexStringToByteArray(IKE_AUTH_EXPECTED_CHECKSUM_HEX_STRING); - when(mMockIntegrity.generateChecksum(any(), any())).thenReturn(expectedChecksum); - when(mMockIntegrity.getChecksumLen()).thenReturn(expectedChecksum.length); - - mMockCipher = mock(IkeNormalModeCipher.class); - when(mMockCipher.getIvLen()).thenReturn(IKE_AUTH_CIPHER_IV_SIZE); - when(mMockCipher.getBlockSize()).thenReturn(IKE_AUTH_CIPHER_BLOCK_SIZE); - when(mMockCipher.decrypt(any(), any(), any())).thenReturn(mUnencryptedPaddedData); - - mMockIkeSaRecord = mock(IkeSaRecord.class); - when(mMockIkeSaRecord.getInboundDecryptionKey()).thenReturn(new byte[0]); - when(mMockIkeSaRecord.getInboundIntegrityKey()).thenReturn(new byte[0]); - - mIkeFragPacketOne = makeFragmentBytes(1 /*fragNum*/, 2 /*totalFragments*/); - mIkeFragPacketTwo = makeFragmentBytes(2 /*fragNum*/, 2 /*totalFragments*/); - - mFragOneHeader = new IkeHeader(mIkeFragPacketOne); - mFragTwoHeader = new IkeHeader(mIkeFragPacketTwo); - - mDummySkfPayloadOne = - makeDummySkfPayload( - FRAGMENT_ONE_UNENCRYPTED_DATA, FRAGMENT_NUM_ONE, TOTAL_FRAGMENTS); - mDummySkfPayloadTwo = - makeDummySkfPayload( - FRAGMENT_TWO_UNENCRYPTED_DATA, FRAGMENT_NUM_TWO, TOTAL_FRAGMENTS); - } - - private byte[] makeFragmentBytes(int fragNum, int totalFragments) { - byte[] packet = TestUtils.hexStringToByteArray(IKE_FRAG_HEX_STRING); - ByteBuffer byteBuffer = ByteBuffer.wrap(packet); - byteBuffer.get(new byte[IkeHeader.IKE_HEADER_LENGTH + IkePayload.GENERIC_HEADER_LENGTH]); - - byteBuffer.putShort((short) fragNum).putShort((short) totalFragments); - return byteBuffer.array(); - } - - @After - public void tearDown() { - IkePayloadFactory.sDecoderInstance = new IkePayloadFactory.IkePayloadDecoder(); - } - - private IkeMessage verifyDecodeResultOkAndGetMessage( - DecodeResult decodeResult, byte[] firstPacket) throws Exception { - assertEquals(DECODE_STATUS_OK, decodeResult.status); - - DecodeResultOk resultOk = (DecodeResultOk) decodeResult; - assertNotNull(resultOk.ikeMessage); - assertArrayEquals(firstPacket, resultOk.firstPacket); - - return resultOk.ikeMessage; - } - - private IkeException verifyDecodeResultErrorAndGetIkeException( - DecodeResult decodeResult, int decodeStatus, byte[] firstPacket) throws Exception { - assertEquals(decodeStatus, decodeResult.status); - - DecodeResultError resultError = (DecodeResultError) decodeResult; - assertNotNull(resultError.ikeException); - - return resultError.ikeException; - } - - @Test - public void testDecodeIkeMessage() throws Exception { - byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET); - IkeHeader header = new IkeHeader(inputPacket); - - DecodeResult decodeResult = IkeMessage.decode(0, header, inputPacket); - - IkeMessage message = verifyDecodeResultOkAndGetMessage(decodeResult, inputPacket); - - assertEquals(EXPECTED_IKE_INIT_PAYLOAD_LIST.length, message.ikePayloadList.size()); - for (int i = 0; i < EXPECTED_IKE_INIT_PAYLOAD_LIST.length; i++) { - assertEquals( - EXPECTED_IKE_INIT_PAYLOAD_LIST[i], message.ikePayloadList.get(i).payloadType); - } - } - - @Test - public void testDecodeMessageWithUnsupportedUncriticalPayload() throws Exception { - byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET); - // Set first payload unsupported uncritical - inputPacket[FIRST_PAYLOAD_TYPE_OFFSET] = (byte) 0xff; - IkeHeader header = new IkeHeader(inputPacket); - - DecodeResult decodeResult = IkeMessage.decode(0, header, inputPacket); - - IkeMessage message = verifyDecodeResultOkAndGetMessage(decodeResult, inputPacket); - - assertEquals(EXPECTED_IKE_INIT_PAYLOAD_LIST.length - 1, message.ikePayloadList.size()); - for (int i = 0; i < EXPECTED_IKE_INIT_PAYLOAD_LIST.length - 1; i++) { - assertEquals( - EXPECTED_IKE_INIT_PAYLOAD_LIST[i + 1], - message.ikePayloadList.get(i).payloadType); - } - } - - @Test - public void testThrowUnsupportedCriticalPayloadException() throws Exception { - byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET); - // Set first payload unsupported critical - inputPacket[FIRST_PAYLOAD_TYPE_OFFSET] = (byte) 0xff; - inputPacket[IkeHeader.IKE_HEADER_LENGTH + PAYLOAD_CRITICAL_BIT_OFFSET] = (byte) 0x80; - - UnsupportedCriticalPayloadException exception = - IkeTestUtils.decodeAndVerifyUnprotectedErrorMsg( - inputPacket, UnsupportedCriticalPayloadException.class); - - assertEquals(1, exception.payloadTypeList.size()); - } - - @Test - public void testDecodeMessageWithTooShortPayloadLength() throws Exception { - byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET); - // Set first payload length to 0 - inputPacket[IkeHeader.IKE_HEADER_LENGTH + FIRST_PAYLOAD_LENGTH_OFFSET] = (byte) 0; - inputPacket[IkeHeader.IKE_HEADER_LENGTH + FIRST_PAYLOAD_LENGTH_OFFSET + 1] = (byte) 0; - - IkeTestUtils.decodeAndVerifyUnprotectedErrorMsg(inputPacket, InvalidSyntaxException.class); - } - - @Test - public void testDecodeMessageWithTooLongPayloadLength() throws Exception { - byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET); - // Increase last payload length by one byte - inputPacket[IkeHeader.IKE_HEADER_LENGTH + LAST_PAYLOAD_LENGTH_OFFSET]++; - - IkeTestUtils.decodeAndVerifyUnprotectedErrorMsg(inputPacket, InvalidSyntaxException.class); - } - - @Test - public void testDecodeMessageWithUnexpectedBytesInTheEnd() throws Exception { - byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET + "0000"); - - IkeTestUtils.decodeAndVerifyUnprotectedErrorMsg(inputPacket, InvalidSyntaxException.class); - } - - @Test - public void testDecodeEncryptedMessage() throws Exception { - DecodeResult decodeResult = - IkeMessage.decode( - IKE_AUTH_EXPECTED_MESSAGE_ID, - mMockIntegrity, - mMockCipher, - mMockIkeSaRecord, - mIkeAuthHeader, - mIkeAuthPacket, - null /*collectedFragments*/); - IkeMessage ikeMessage = verifyDecodeResultOkAndGetMessage(decodeResult, mIkeAuthPacket); - - assertEquals(IKE_AUTH_PAYLOAD_SIZE, ikeMessage.ikePayloadList.size()); - } - - @Test - public void testDecodeEncryptedMessageWithWrongId() throws Exception { - DecodeResult decodeResult = - IkeMessage.decode( - 2, - mMockIntegrity, - mMockCipher, - mMockIkeSaRecord, - mIkeAuthHeader, - mIkeAuthPacket, - null /*collectedFragments*/); - IkeException ikeException = - verifyDecodeResultErrorAndGetIkeException( - decodeResult, DECODE_STATUS_UNPROTECTED_ERROR, mIkeAuthPacket); - - assertTrue(ikeException instanceof InvalidMessageIdException); - } - - @Test - public void testDecodeEncryptedMessageWithWrongChecksum() throws Exception { - when(mMockIntegrity.generateChecksum(any(), any())).thenReturn(new byte[0]); - - DecodeResult decodeResult = - IkeMessage.decode( - IKE_AUTH_EXPECTED_MESSAGE_ID, - mMockIntegrity, - mMockCipher, - mMockIkeSaRecord, - mIkeAuthHeader, - mIkeAuthPacket, - null /*collectedFragments*/); - IkeException ikeException = - verifyDecodeResultErrorAndGetIkeException( - decodeResult, DECODE_STATUS_UNPROTECTED_ERROR, mIkeAuthPacket); - - assertTrue( - ((IkeInternalException) ikeException).getCause() - instanceof GeneralSecurityException); - } - - @Test - public void testDecryptFail() throws Exception { - when(mMockCipher.decrypt(any(), any(), any())).thenThrow(IllegalBlockSizeException.class); - - DecodeResult decodeResult = - IkeMessage.decode( - IKE_AUTH_EXPECTED_MESSAGE_ID, - mMockIntegrity, - mMockCipher, - mMockIkeSaRecord, - mIkeAuthHeader, - mIkeAuthPacket, - null /*collectedFragments*/); - - IkeException ikeException = - verifyDecodeResultErrorAndGetIkeException( - decodeResult, DECODE_STATUS_UNPROTECTED_ERROR, mIkeAuthPacket); - assertTrue( - ((IkeInternalException) ikeException).getCause() - instanceof IllegalBlockSizeException); - } - - @Test - public void testParsingErrorInEncryptedMessage() throws Exception { - // Set first payload length to 0 - byte[] decryptedData = - Arrays.copyOfRange(mUnencryptedPaddedData, 0, mUnencryptedPaddedData.length); - decryptedData[FIRST_PAYLOAD_LENGTH_OFFSET] = (byte) 0; - decryptedData[FIRST_PAYLOAD_LENGTH_OFFSET + 1] = (byte) 0; - when(mMockCipher.decrypt(any(), any(), any())).thenReturn(decryptedData); - - DecodeResult decodeResult = - IkeMessage.decode( - IKE_AUTH_EXPECTED_MESSAGE_ID, - mMockIntegrity, - mMockCipher, - mMockIkeSaRecord, - mIkeAuthHeader, - mIkeAuthPacket, - null /*collectedFragments*/); - IkeException ikeException = - verifyDecodeResultErrorAndGetIkeException( - decodeResult, DECODE_STATUS_PROTECTED_ERROR, mIkeAuthPacket); - - assertTrue(ikeException instanceof InvalidSyntaxException); - } - - private boolean support(int payloadType) { - // Supports all payload typs from 33 to 46 - return (payloadType >= 33 && payloadType <= 46); - } - - @Test - public void testAttachEncodedHeader() throws Exception { - byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET); - byte[] ikeBodyBytes = TestUtils.hexStringToByteArray(IKE_SA_INIT_BODY_RAW_PACKET); - IkeHeader header = new IkeHeader(inputPacket); - IkeMessage message = - ((DecodeResultOk) IkeMessage.decode(0, header, inputPacket)).ikeMessage; - - byte[] encodedIkeMessage = message.attachEncodedHeader(ikeBodyBytes); - assertArrayEquals(inputPacket, encodedIkeMessage); - } - - @Test - public void testEncodeAndEncryptEmptyMsg() throws Exception { - when(mMockCipher.generateIv()) - .thenReturn(TestUtils.hexStringToByteArray(IKE_EMPTY_INFO_MSG_IV_HEX_STRING)); - when(mMockCipher.encrypt(any(), any(), any())) - .thenReturn( - TestUtils.hexStringToByteArray( - IKE_EMPTY_INFO_MSG_ENCRYPTED_DATA_HEX_STRING)); - - byte[] checkSum = TestUtils.hexStringToByteArray(IKE_EMPTY_INFO_MSG_CHECKSUM_HEX_STRING); - when(mMockIntegrity.getChecksumLen()).thenReturn(checkSum.length); - when(mMockIntegrity.generateChecksum(any(), any())).thenReturn(checkSum); - - IkeHeader ikeHeader = - new IkeHeader( - INIT_SPI, - RESP_SPI, - IkePayload.PAYLOAD_TYPE_SK, - IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, - true /*isResp*/, - true /*fromInit*/, - 0); - IkeMessage ikeMessage = new IkeMessage(ikeHeader, new LinkedList<>()); - - byte[][] ikeMessageBytes = - ikeMessage.encryptAndEncode( - mMockIntegrity, - mMockCipher, - mMockIkeSaRecord, - true /*supportFragment*/, - 1280 /*fragSize*/); - byte[][] expectedBytes = - new byte[][] {TestUtils.hexStringToByteArray(IKE_EMPTY_INFO_MSG_HEX_STRING)}; - - assertArrayEquals(expectedBytes, ikeMessageBytes); - } - - private DecodeResultPartial makeDecodeResultForFragOne(DecodeResultPartial collectedFrags) { - return new DecodeResultPartial( - mFragOneHeader, - mIkeFragPacketOne, - mDummySkfPayloadOne, - PAYLOAD_TYPE_AUTH, - collectedFrags); - } - - private DecodeResultPartial makeDecodeResultForFragTwo(DecodeResultPartial collectedFrags) { - return new DecodeResultPartial( - mFragTwoHeader, - mIkeFragPacketTwo, - mDummySkfPayloadTwo, - PAYLOAD_TYPE_NO_NEXT, - collectedFrags); - } - - @Test - public void testConstructDecodePartialFirstFragArriveFirst() throws Exception { - DecodeResultPartial resultPartial = makeDecodeResultForFragOne(null /*collectedFragments*/); - - assertEquals(PAYLOAD_TYPE_AUTH, resultPartial.firstPayloadType); - assertArrayEquals(mIkeFragPacketOne, resultPartial.firstFragBytes); - assertEquals(mFragOneHeader, resultPartial.ikeHeader); - - assertEquals(TOTAL_FRAGMENTS, resultPartial.collectedFragsList.length); - assertArrayEquals( - FRAGMENT_ONE_UNENCRYPTED_DATA, - resultPartial.collectedFragsList[FRAGMENT_NUM_ONE - 1]); - assertFalse(resultPartial.isAllFragmentsReceived()); - } - - @Test - public void testConstructDecodePartialSecondFragArriveFirst() throws Exception { - DecodeResultPartial resultPartial = makeDecodeResultForFragTwo(null /*collectedFragments*/); - - assertEquals(PAYLOAD_TYPE_NO_NEXT, resultPartial.firstPayloadType); - assertNull(resultPartial.firstFragBytes); - assertEquals(mFragTwoHeader, resultPartial.ikeHeader); - - assertEquals(TOTAL_FRAGMENTS, resultPartial.collectedFragsList.length); - assertArrayEquals( - FRAGMENT_TWO_UNENCRYPTED_DATA, - resultPartial.collectedFragsList[FRAGMENT_NUM_TWO - 1]); - assertFalse(resultPartial.isAllFragmentsReceived()); - } - - @Test - public void testConstructDecodeResultPartialWithCollectedFrags() throws Exception { - DecodeResultPartial resultPartialIncomplete = - makeDecodeResultForFragTwo(null /*collectedFragments*/); - DecodeResultPartial resultPartialComplete = - makeDecodeResultForFragOne(resultPartialIncomplete); - - assertEquals(PAYLOAD_TYPE_AUTH, resultPartialComplete.firstPayloadType); - assertArrayEquals(mIkeFragPacketOne, resultPartialComplete.firstFragBytes); - assertEquals(mFragTwoHeader, resultPartialComplete.ikeHeader); - - assertEquals(TOTAL_FRAGMENTS, resultPartialComplete.collectedFragsList.length); - assertTrue(resultPartialComplete.isAllFragmentsReceived()); - } - - @Test - public void testReassembleAllFrags() throws Exception { - DecodeResultPartial resultPartialIncomplete = - makeDecodeResultForFragOne(null /*collectedFragments*/); - DecodeResultPartial resultPartialComplete = - makeDecodeResultForFragTwo(resultPartialIncomplete); - - assertEquals(PAYLOAD_TYPE_AUTH, resultPartialIncomplete.firstPayloadType); - assertArrayEquals(mIkeFragPacketOne, resultPartialIncomplete.firstFragBytes); - assertEquals(mFragOneHeader, resultPartialIncomplete.ikeHeader); - - assertEquals(TOTAL_FRAGMENTS, resultPartialIncomplete.collectedFragsList.length); - assertTrue(resultPartialIncomplete.isAllFragmentsReceived()); - - // Verify reassembly result - ByteBuffer expectedBuffer = - ByteBuffer.allocate( - FRAGMENT_ONE_UNENCRYPTED_DATA.length - + FRAGMENT_TWO_UNENCRYPTED_DATA.length); - expectedBuffer.put(FRAGMENT_ONE_UNENCRYPTED_DATA).put(FRAGMENT_TWO_UNENCRYPTED_DATA); - - byte[] reassembledBytes = resultPartialComplete.reassembleAllFrags(); - assertArrayEquals(expectedBuffer.array(), reassembledBytes); - } - - @Test - public void testReassembleIncompleteFragmentsThrows() throws Exception { - DecodeResultPartial resultPartial = makeDecodeResultForFragTwo(null /*collectedFragments*/); - - assertFalse(resultPartial.isAllFragmentsReceived()); - - try { - resultPartial.reassembleAllFrags(); - fail("Expected to fail because reassembly is not done"); - } catch (IllegalStateException expected) { - - } - } - - private void setDecryptSkfPayload(IkeSkfPayload skf) throws Exception { - doReturn(skf) - .when(mSpyIkePayloadDecoder) - .decodeIkeSkPayload( - eq(true), - anyBoolean(), - any(), - eq(mMockIntegrity), - eq(mMockCipher), - any(), - any()); - } - - private DecodeResult decodeSkf( - int expectedMsgId, - IkeHeader header, - byte[] packet, - DecodeResultPartial collectFragments) - throws Exception { - return IkeMessage.decode( - expectedMsgId, - mMockIntegrity, - mMockCipher, - mMockIkeSaRecord, - header, - packet, - collectFragments); - } - - @Test - public void testRcvFirstArrivedFrag() throws Exception { - setDecryptSkfPayload(mDummySkfPayloadTwo); - DecodeResult decodeResult = - decodeSkf( - IKE_FRAG_EXPECTED_MESSAGE_ID, - mFragTwoHeader, - mIkeFragPacketTwo, - null /* collectedFragments*/); - - // Verify decoding result - assertTrue(decodeResult instanceof DecodeResultPartial); - DecodeResultPartial resultPartial = (DecodeResultPartial) decodeResult; - - assertEquals(PAYLOAD_TYPE_NO_NEXT, resultPartial.firstPayloadType); - assertNull(resultPartial.firstFragBytes); - assertEquals(mFragTwoHeader, resultPartial.ikeHeader); - - assertEquals(TOTAL_FRAGMENTS, resultPartial.collectedFragsList.length); - assertArrayEquals( - FRAGMENT_TWO_UNENCRYPTED_DATA, - resultPartial.collectedFragsList[FRAGMENT_NUM_TWO - 1]); - assertFalse(resultPartial.isAllFragmentsReceived()); - } - - @Test - public void testRcvLastArrivedFrag() throws Exception { - // Create two dummy SKF Payloads so that the complete unencrypted data is two ID payloads - byte[] idInitPayloadBytes = TestUtils.hexStringToByteArray(ID_INIT_PAYLOAD_HEX_STRING); - byte[] idRespPayloadBytes = TestUtils.hexStringToByteArray(ID_RESP_PAYLOAD_HEX_STRING); - IkeSkfPayload skfOne = - makeDummySkfPayload(idInitPayloadBytes, FRAGMENT_NUM_ONE, TOTAL_FRAGMENTS); - IkeSkfPayload skfTwo = - makeDummySkfPayload(idRespPayloadBytes, FRAGMENT_NUM_TWO, TOTAL_FRAGMENTS); - - DecodeResultPartial resultPartialIncomplete = - new DecodeResultPartial( - mFragOneHeader, - mIkeFragPacketOne, - skfOne, - PAYLOAD_TYPE_ID_INITIATOR, - null /* collectedFragments*/); - - setDecryptSkfPayload(skfTwo); - DecodeResult decodeResult = - decodeSkf( - IKE_FRAG_EXPECTED_MESSAGE_ID, - mFragTwoHeader, - mIkeFragPacketTwo, - resultPartialIncomplete); - - // Verify fragments reassembly has been finished and complete message has been decoded. - assertTrue(decodeResult instanceof DecodeResultOk); - DecodeResultOk resultOk = (DecodeResultOk) decodeResult; - assertArrayEquals(mIkeFragPacketOne, resultOk.firstPacket); - assertEquals(2, resultOk.ikeMessage.ikePayloadList.size()); - } - - @Test - public void testRcvFirstArrivedFragWithUnprotectedError() throws Exception { - DecodeResult decodeResult = - decodeSkf( - IKE_FRAG_EXPECTED_MESSAGE_ID + 1, - mFragTwoHeader, - mIkeFragPacketTwo, - null /* collectedFragments*/); - - // Verify that unprotected error was returned - IkeException ikeException = - verifyDecodeResultErrorAndGetIkeException( - decodeResult, DECODE_STATUS_UNPROTECTED_ERROR, mIkeAuthPacket); - assertTrue(ikeException instanceof InvalidMessageIdException); - } - - @Test - public void testRcvLastArrivedFragWithUnprotectedError() throws Exception { - DecodeResultPartial resultPartialIncomplete = - makeDecodeResultForFragOne(null /* collectedFragments*/); - - DecodeResult decodeResult = - decodeSkf( - IKE_FRAG_EXPECTED_MESSAGE_ID + 1, - mFragTwoHeader, - mIkeFragPacketTwo, - resultPartialIncomplete); - - // Verify that newly received fragment was discarded - assertEquals(resultPartialIncomplete, decodeResult); - } - - @Test - public void testRcvFragWithLargerTotalFragments() throws Exception { - DecodeResultPartial resultPartialIncomplete = - new DecodeResultPartial( - mFragOneHeader, - mIkeFragPacketOne, - mDummySkfPayloadOne, - PAYLOAD_TYPE_NO_NEXT, - null /* collectedFragments*/); - - // Set total fragments of inbound fragment to 5 - int totalFragments = 5; - byte[] fragPacket = makeFragmentBytes(2 /*fragNum*/, totalFragments); - - byte[] unencryptedData = "testRcvFragWithLargerTotalFragments".getBytes(); - IkeSkfPayload skfPayload = - makeDummySkfPayload(unencryptedData, FRAGMENT_NUM_TWO, totalFragments); - setDecryptSkfPayload(skfPayload); - DecodeResult decodeResult = - decodeSkf( - IKE_FRAG_EXPECTED_MESSAGE_ID, - mFragTwoHeader, - fragPacket, - resultPartialIncomplete); - - // Verify that previously collected fragments were all discarded - assertTrue(decodeResult instanceof DecodeResultPartial); - DecodeResultPartial resultPartial = (DecodeResultPartial) decodeResult; - - assertEquals(PAYLOAD_TYPE_NO_NEXT, resultPartial.firstPayloadType); - assertNull(resultPartial.firstFragBytes); - assertEquals(mFragTwoHeader, resultPartial.ikeHeader); - - assertEquals(totalFragments, resultPartial.collectedFragsList.length); - assertArrayEquals(unencryptedData, resultPartial.collectedFragsList[FRAGMENT_NUM_TWO - 1]); - assertFalse(resultPartial.isAllFragmentsReceived()); - } - - @Test - public void testRcvFragWithSmallerTotalFragments() throws Exception { - int totalFragments = 5; - byte[] unencryptedData = "testRcvFragWithSmallerTotalFragments".getBytes(); - IkeSkfPayload skfPayload = - makeDummySkfPayload(unencryptedData, FRAGMENT_NUM_ONE, totalFragments); - - DecodeResultPartial resultPartialIncomplete = - new DecodeResultPartial( - mFragOneHeader, - mIkeFragPacketOne, - skfPayload, - PAYLOAD_TYPE_AUTH, - null /* collectedFragments*/); - - setDecryptSkfPayload(mDummySkfPayloadTwo); - DecodeResult decodeResult = - decodeSkf( - IKE_FRAG_EXPECTED_MESSAGE_ID, - mFragTwoHeader, - mIkeFragPacketTwo, - resultPartialIncomplete); - - // Verify that newly received fragment was discarded - assertEquals(resultPartialIncomplete, decodeResult); - } - - @Test - public void testRcvReplayFrag() throws Exception { - DecodeResultPartial resultPartialIncomplete = - makeDecodeResultForFragTwo(null /* collectedFragments*/); - - setDecryptSkfPayload(mDummySkfPayloadTwo); - DecodeResult decodeResult = - decodeSkf( - IKE_FRAG_EXPECTED_MESSAGE_ID, - mFragTwoHeader, - mIkeFragPacketTwo, - resultPartialIncomplete); - - // Verify that newly received fragment was discarded - assertEquals(resultPartialIncomplete, decodeResult); - } - - @Test - public void testRcvCompleteMessageDuringReassembly() throws Exception { - DecodeResultPartial resultPartialIncomplete = - makeDecodeResultForFragTwo(null /* collectedFragments*/); - - DecodeResult decodeResult = - decodeSkf( - IKE_AUTH_EXPECTED_MESSAGE_ID, - mIkeAuthHeader, - mIkeAuthPacket, - resultPartialIncomplete); - - // Verify that newly received IKE message was discarded - assertEquals(resultPartialIncomplete, decodeResult); - } - - @Test - public void testEncodeAndEncryptFragments() throws Exception { - int messageId = 1; - int fragSize = 140; - int expectedTotalFragments = 3; - - byte[] integrityKey = new byte[0]; - byte[] encryptionKey = new byte[0]; - byte[] iv = new byte[IKE_AUTH_CIPHER_IV_SIZE]; - - when(mMockCipher.generateIv()).thenReturn(iv); - when(mMockCipher.encrypt(any(), any(), any())) - .thenAnswer( - (invocation) -> { - return (byte[]) invocation.getArguments()[0]; - }); - - IkeHeader ikeHeader = - new IkeHeader( - INIT_SPI, - RESP_SPI, - IkePayload.PAYLOAD_TYPE_SK, - IkeHeader.EXCHANGE_TYPE_IKE_AUTH, - true /*isResp*/, - false /*fromInit*/, - messageId); - - byte[][] packetList = - new IkeMessage.IkeMessageHelper() - .encryptAndEncode( - ikeHeader, - IkePayload.PAYLOAD_TYPE_AUTH, - mUnencryptedPaddedData, - mMockIntegrity, - mMockCipher, - integrityKey, - encryptionKey, - true /*supportFragment*/, - fragSize); - - assertEquals(expectedTotalFragments, packetList.length); - - IkeHeader expectedIkeHeader = - new IkeHeader( - INIT_SPI, - RESP_SPI, - IkePayload.PAYLOAD_TYPE_SKF, - IkeHeader.EXCHANGE_TYPE_IKE_AUTH, - true /*isResp*/, - false /*fromInit*/, - messageId); - for (int i = 0; i < packetList.length; i++) { - byte[] p = packetList[i]; - - // Verify fragment length - assertNotNull(p); - assertTrue(p.length <= fragSize); - - ByteBuffer packetBuffer = ByteBuffer.wrap(p); - - // Verify IKE header - byte[] headerBytes = new byte[IkeHeader.IKE_HEADER_LENGTH]; - packetBuffer.get(headerBytes); - - ByteBuffer expectedHeadBuffer = ByteBuffer.allocate(IkeHeader.IKE_HEADER_LENGTH); - expectedIkeHeader.encodeToByteBuffer( - expectedHeadBuffer, p.length - IkeHeader.IKE_HEADER_LENGTH); - - assertArrayEquals(expectedHeadBuffer.array(), headerBytes); - - // Verify fragment payload header - packetBuffer.get(new byte[IkePayload.GENERIC_HEADER_LENGTH]); - assertEquals(i + 1 /*expetced fragNum*/, Short.toUnsignedInt(packetBuffer.getShort())); - assertEquals(expectedTotalFragments, Short.toUnsignedInt(packetBuffer.getShort())); - } - - verify(mMockCipher, times(expectedTotalFragments + 1)) - .encrypt(any(), eq(encryptionKey), eq(iv)); - } -} |