aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/java/com/android/ike/ikev2/message/IkeHeader.java5
-rw-r--r--src/java/com/android/ike/ikev2/message/IkeMessage.java83
-rw-r--r--src/java/com/android/ike/ikev2/message/IkePayloadFactory.java81
-rw-r--r--src/java/com/android/ike/ikev2/message/IkeSkPayload.java101
-rw-r--r--tests/iketests/src/java/com/android/ike/ikev2/message/IkeHeaderTest.java55
-rw-r--r--tests/iketests/src/java/com/android/ike/ikev2/message/IkeMessageTest.java70
6 files changed, 350 insertions, 45 deletions
diff --git a/src/java/com/android/ike/ikev2/message/IkeHeader.java b/src/java/com/android/ike/ikev2/message/IkeHeader.java
index 851442b9..d2277cef 100644
--- a/src/java/com/android/ike/ikev2/message/IkeHeader.java
+++ b/src/java/com/android/ike/ikev2/message/IkeHeader.java
@@ -138,7 +138,7 @@ public final class IkeHeader {
}
/** Validate syntax and major version. */
- public void validate() throws IkeException {
+ public void checkValidOrThrow(int packetLength) throws IkeException {
if (majorVersion > 2) {
// Receive higher version of protocol. Stop parsing.
throw new InvalidMajorVersionException(majorVersion);
@@ -154,6 +154,9 @@ public final class IkeHeader {
|| exchangeType > EXCHANGE_TYPE_INFORMATIONAL) {
throw new InvalidSyntaxException("Invalid IKE Exchange Type.");
}
+ if (messageLength != packetLength) {
+ throw new InvalidSyntaxException("Invalid IKE Message Length.");
+ }
}
/** Encode IKE header to ByteBuffer */
diff --git a/src/java/com/android/ike/ikev2/message/IkeMessage.java b/src/java/com/android/ike/ikev2/message/IkeMessage.java
index 0261ec2b..17bd5c0b 100644
--- a/src/java/com/android/ike/ikev2/message/IkeMessage.java
+++ b/src/java/com/android/ike/ikev2/message/IkeMessage.java
@@ -25,12 +25,18 @@ import com.android.ike.ikev2.exceptions.InvalidSyntaxException;
import com.android.ike.ikev2.exceptions.UnsupportedCriticalPayloadException;
import com.android.org.bouncycastle.jce.provider.BouncyCastleProvider;
+import java.io.IOException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.security.Provider;
+import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+
/**
* IkeMessage represents an IKE message.
*
@@ -60,22 +66,66 @@ public final class IkeMessage {
}
/**
- * Decode unenrypted IKE message body and create an instance of IkeMessage.
+ * Decrypt and decode encrypted IKE message body and create an instance of IkeMessage.
+ *
+ * @param header the IKE header that is decoded but not validated.
+ * @param inputPacket the byte array containing the whole IKE message.
+ * @param integrityMac the initialized Message Authentication Code (MAC) for integrity check.
+ * @param checksumLen the length of integrity checksum.
+ * @param decryptCipher the uninitialized Cipher for doing decryption.
+ * @param dKey the decryption key.
+ * @param ivLen the length of Initialization Vector.
+ * @return the IkeMessage instance.
+ * @throws IkeException if there is any protocol error.
+ * @throws IOException if there is any error during integrity check or decryption.
+ */
+ public static IkeMessage decode(
+ IkeHeader header,
+ byte[] inputPacket,
+ Mac integrityMac,
+ int checksumLen,
+ Cipher decryptCipher,
+ SecretKey dKey,
+ int ivLen)
+ throws IkeException, IOException {
+
+ header.checkValidOrThrow(inputPacket.length);
+
+ Pair<IkeSkPayload, Integer> pair =
+ IkePayloadFactory.getIkeSkPayload(
+ inputPacket, integrityMac, checksumLen, decryptCipher, dKey, ivLen);
+ IkeSkPayload skPayload = pair.first;
+ int firstPayloadType = pair.second;
+
+ List<IkePayload> supportedPayloadList =
+ decodePayloadList(firstPayloadType, skPayload.unencryptedPayloads);
+ return new IkeMessage(header, supportedPayloadList);
+ }
+
+ /**
+ * Decode unencrypted IKE message body and create an instance of IkeMessage.
*
- * @param header the IKE header that is decoded but not validated
- * @param inputPacket the byte array contains the whole IKE message
- * @throws IkeException if there is any error
+ * @param header the IKE header that is decoded but not validated.
+ * @param inputPacket the byte array contains the whole IKE message.
+ * @return the IkeMessage instance.
+ * @throws IkeException if there is any protocol error.
*/
public static IkeMessage decode(IkeHeader header, byte[] inputPacket) throws IkeException {
- header.validate();
+ header.checkValidOrThrow(inputPacket.length);
+
+ byte[] unencryptedPayloads =
+ Arrays.copyOfRange(inputPacket, IkeHeader.IKE_HEADER_LENGTH, inputPacket.length);
- ByteBuffer inputBuffer =
- ByteBuffer.wrap(
- inputPacket,
- IkeHeader.IKE_HEADER_LENGTH,
- inputPacket.length - IkeHeader.IKE_HEADER_LENGTH);
- @PayloadType int currentPayloadType = header.nextPayloadType;
+ List<IkePayload> supportedPayloadList =
+ decodePayloadList(header.nextPayloadType, unencryptedPayloads);
+ return new IkeMessage(header, supportedPayloadList);
+ }
+
+ private static List<IkePayload> decodePayloadList(
+ @PayloadType int firstPayloadType, byte[] unencryptedPayloads) throws IkeException {
+ ByteBuffer inputBuffer = ByteBuffer.wrap(unencryptedPayloads);
+ int currentPayloadType = firstPayloadType;
// For supported payload
List<IkePayload> supportedPayloadList = new LinkedList<>();
// For unsupported critical payload
@@ -96,14 +146,23 @@ public final class IkeMessage {
currentPayloadType = pair.second;
} catch (NegativeArraySizeException | BufferUnderflowException e) {
+ // TODO: b/119791832. Add length check in each payload before getting data from
+ // ByteBuffer.
+
+ // Invalid length error when parsing payload bodies.
throw new InvalidSyntaxException("Malformed IKE Payload");
}
}
+ if (inputBuffer.remaining() > 0) {
+ throw new InvalidSyntaxException(
+ "Malformed IKE Payload: Unexpected bytes at the end of packet.");
+ }
+
if (unsupportedCriticalPayloadList.size() > 0) {
throw new UnsupportedCriticalPayloadException(unsupportedCriticalPayloadList);
}
- return new IkeMessage(header, supportedPayloadList);
+ return supportedPayloadList;
}
static Provider getSecurityProvider() {
diff --git a/src/java/com/android/ike/ikev2/message/IkePayloadFactory.java b/src/java/com/android/ike/ikev2/message/IkePayloadFactory.java
index 86edb585..ced76d1b 100644
--- a/src/java/com/android/ike/ikev2/message/IkePayloadFactory.java
+++ b/src/java/com/android/ike/ikev2/message/IkePayloadFactory.java
@@ -19,10 +19,16 @@ package com.android.ike.ikev2.message;
import android.util.Pair;
import com.android.ike.ikev2.exceptions.IkeException;
+import com.android.ike.ikev2.exceptions.InvalidSyntaxException;
import com.android.internal.annotations.VisibleForTesting;
+import java.io.IOException;
import java.nio.ByteBuffer;
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+
/**
* IkePayloadFactory is used for creating IkePayload according to is type.
*
@@ -31,6 +37,14 @@ import java.nio.ByteBuffer;
*/
final class IkePayloadFactory {
+ // Critical bit is set and following reserved 7 bits are unset.
+ private static final byte PAYLOAD_HEADER_CRITICAL_BIT_SET = (byte) 0x80;
+
+ private static boolean isCriticalPayload(byte flagByte) {
+ // Reserved 7 bits following critical bit must be ignore on receipt.
+ return (flagByte & PAYLOAD_HEADER_CRITICAL_BIT_SET) == PAYLOAD_HEADER_CRITICAL_BIT_SET;
+ }
+
/** Default instance used for constructing IkePayload */
@VisibleForTesting
static IkePayloadDecoder sDecoderInstance =
@@ -68,15 +82,25 @@ final class IkePayloadFactory {
* IkePayload.PayloadType}
* @param input the encoded IKE message body containing all payloads. Position of it will
* increment.
+ * @return a Pair including IkePayload and next payload type.
*/
- static Pair<IkePayload, Integer> getIkePayload(int payloadType, ByteBuffer input)
+ protected static Pair<IkePayload, Integer> getIkePayload(int payloadType, ByteBuffer input)
throws IkeException {
int nextPayloadType = (int) input.get();
// read critical bit
- boolean isCritical = ((input.get() & 0x80) == 0x80);
+ boolean isCritical = isCriticalPayload(input.get());
int payloadLength = Short.toUnsignedInt(input.getShort());
+ if (payloadLength <= IkePayload.GENERIC_HEADER_LENGTH) {
+ throw new InvalidSyntaxException(
+ "Invalid Payload Length: Payload length is too short.");
+ }
int bodyLength = payloadLength - IkePayload.GENERIC_HEADER_LENGTH;
+ if (bodyLength > input.remaining()) {
+ // It is not clear whether previous payloads or current payload has invalid payload
+ // length.
+ throw new InvalidSyntaxException("Invalid Payload Length: Payload length is too long.");
+ }
byte[] payloadBody = new byte[bodyLength];
input.get(payloadBody);
@@ -85,6 +109,59 @@ final class IkePayloadFactory {
return new Pair(payload, nextPayloadType);
}
+ /**
+ * Construct an instance of IkeSkPayload by decrypting the received message.
+ *
+ * @param message the byte array contains the whole IKE message.
+ * @param integrityMac the initialized Mac for integrity check.
+ * @param checksumLen the length of integrity checksum.
+ * @param decryptCipher the uninitialized Cipher for doing decryption.
+ * @param dKey the decryption key.
+ * @param ivLen the length of Initialization Vector.
+ * @return a pair including IkePayload and next payload type.
+ * @throws IOException
+ */
+ protected static Pair<IkeSkPayload, Integer> getIkeSkPayload(
+ byte[] message,
+ Mac integrityMac,
+ int checksumLen,
+ Cipher decryptCipher,
+ SecretKey dKey,
+ int ivLen)
+ throws IkeException {
+ ByteBuffer input =
+ ByteBuffer.wrap(
+ message,
+ IkeHeader.IKE_HEADER_LENGTH,
+ message.length - IkeHeader.IKE_HEADER_LENGTH);
+
+ int nextPayloadType = (int) input.get();
+ // read critical bit
+ boolean isCritical = isCriticalPayload(input.get());
+
+ int payloadLength = Short.toUnsignedInt(input.getShort());
+
+ int bodyLength = message.length - IkeHeader.IKE_HEADER_LENGTH;
+ if (bodyLength < payloadLength) {
+ throw new InvalidSyntaxException(
+ "Invalid length of SK Payload: Payload length is too long.");
+ } else if (bodyLength > payloadLength) {
+ // According to RFC 7296, SK Payload must be the last payload and for CREATE_CHILD_SA,
+ // IKE_AUTH and INFORMATIONAL exchanges, message following the header is encrypted. Thus
+ // this implementaion only accepts that SK Payload to be the only payload. Any IKE
+ // packet violating this format will be treated as invalid. A request violating this
+ // format will be rejected and replied with an error notification.
+ throw new InvalidSyntaxException(
+ "Invalid length of SK Payload: Payload length is too short"
+ + " or SK Payload is not the only payload.");
+ }
+
+ IkeSkPayload payload =
+ new IkeSkPayload(
+ isCritical, message, integrityMac, checksumLen, decryptCipher, dKey, ivLen);
+ return new Pair(payload, nextPayloadType);
+ }
+
@VisibleForTesting
interface IkePayloadDecoder {
IkePayload decodeIkePayload(int payloadType, boolean isCritical, byte[] payloadBody)
diff --git a/src/java/com/android/ike/ikev2/message/IkeSkPayload.java b/src/java/com/android/ike/ikev2/message/IkeSkPayload.java
new file mode 100644
index 00000000..65c021a7
--- /dev/null
+++ b/src/java/com/android/ike/ikev2/message/IkeSkPayload.java
@@ -0,0 +1,101 @@
+/*
+ * 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 com.android.ike.ikev2.message.IkePayload.PayloadType;
+
+import java.nio.ByteBuffer;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+
+/**
+ * IkeSkPayload represents a Encrypted Payload.
+ *
+ * <p>It contains other payloads in encrypted form. It is must be the last payload in the message.
+ * It should be the only payload in this implementation.
+ *
+ * <p>Critical bit must be ignored when doing decoding.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#page-105">RFC 7296, Internet Key Exchange
+ * Protocol Version 2 (IKEv2).
+ */
+public final class IkeSkPayload extends IkePayload {
+
+ public final byte[] unencryptedPayloads;
+
+ /**
+ * Construct an instance of IkeSkPayload in the context of {@link IkePayloadFactory}.
+ *
+ * @param critical indicates if it is a critical payload.
+ * @param message the byte array contains the whole IKE message.
+ * @param integrityMac the initialized Mac for integrity check.
+ * @param checksumLen the length of integrity checksum.
+ * @param decryptCipher the uninitialized Cipher for doing decryption.
+ * @param dKey the decryption key.
+ * @param ivLen the length of Initialization Vector.
+ */
+ IkeSkPayload(
+ boolean critical,
+ byte[] message,
+ Mac integrityMac,
+ int checksumLen,
+ Cipher decryptCipher,
+ SecretKey dKey,
+ int ivLen) {
+ super(PAYLOAD_TYPE_SK, critical);
+ // TODO:Check integrity and decrypt SkPayload body.
+ throw new UnsupportedOperationException("It is not supported to construct a SkPayload.");
+ }
+
+ //TODO: Add another constructor for AEAD protected payload.
+
+ /**
+ * Throw an Exception when trying to encode this payload.
+ *
+ * @throws UnsupportedOperationException for this payload.
+ */
+ @Override
+ protected void encodeToByteBuffer(@PayloadType int nextPayload, ByteBuffer byteBuffer) {
+ // TODO: Implement thie method
+ throw new UnsupportedOperationException(
+ "It is not supported to encode a " + getTypeString());
+ }
+
+ /**
+ * Get entire payload length.
+ *
+ * @return entire payload length.
+ */
+ @Override
+ protected int getPayloadLength() {
+ // TODO: Implement thie method
+ throw new UnsupportedOperationException(
+ "It is not supported to get length of a " + getTypeString());
+ }
+
+ /**
+ * Return the payload type as a String.
+ *
+ * @return the payload type as a String.
+ */
+ @Override
+ public String getTypeString() {
+ return "Encrypted and Authenticated Payload";
+ }
+}
diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeHeaderTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeHeaderTest.java
index 70b2d651..1bc52c3b 100644
--- a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeHeaderTest.java
+++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeHeaderTest.java
@@ -20,6 +20,10 @@ 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.exceptions.InvalidMajorVersionException;
+import com.android.ike.ikev2.exceptions.InvalidSyntaxException;
import org.junit.Test;
@@ -59,6 +63,13 @@ public final class IkeHeaderTest {
private static final int IKE_MSG_ID = 0;
private static final int IKE_MSG_LENGTH = 336;
+ // Byte offsets of version field in IKE message header.
+ private static final int VERSION_OFFSET = 17;
+ // Byte offsets of exchange type in IKE message header.
+ private static final int EXCHANGE_TYPE_OFFSET = 18;
+ // Byte offsets of message length in IKE message header.
+ private static final int MESSAGE_LENGTH_OFFSET = 24;
+
@Test
public void testDecodeIkeHeader() throws Exception {
byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET);
@@ -82,6 +93,50 @@ public final class IkeHeaderTest {
}
@Test
+ public void testDecodeIkeHeaderWithInvalidMajorVersion() throws Exception {
+ byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET);
+ // Set major version 3.
+ inputPacket[VERSION_OFFSET] = (byte) 0x30;
+ // Set Exchange type 0
+ inputPacket[EXCHANGE_TYPE_OFFSET] = (byte) 0x00;
+ IkeHeader header = new IkeHeader(inputPacket);
+ try {
+ IkeMessage.decode(header, inputPacket);
+ fail(
+ "Expected InvalidMajorVersionException: major version is 3"
+ + "and exchange type is 0");
+ } catch (InvalidMajorVersionException expected) {
+ assertEquals(3, expected.receivedMajorVersion);
+ }
+ }
+
+ @Test
+ public void testDecodeIkeHeaderWithInvalidExchangeType() throws Exception {
+ byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET);
+ // Set Exchange type 0
+ inputPacket[EXCHANGE_TYPE_OFFSET] = (byte) 0x00;
+ IkeHeader header = new IkeHeader(inputPacket);
+ try {
+ IkeMessage.decode(header, inputPacket);
+ fail("Expected InvalidSyntaxException: exchange type is 0");
+ } catch (InvalidSyntaxException expected) {
+ }
+ }
+
+ @Test
+ public void testDecodeIkeHeaderWithInvalidPacketLength() throws Exception {
+ byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET);
+ // Set Exchange type 0
+ inputPacket[MESSAGE_LENGTH_OFFSET] = (byte) 0x01;
+ IkeHeader header = new IkeHeader(inputPacket);
+ try {
+ IkeMessage.decode(header, inputPacket);
+ fail("Expected InvalidSyntaxException: IKE message length.");
+ } catch (InvalidSyntaxException expected) {
+ }
+ }
+
+ @Test
public void testEncodeIkeHeader() throws Exception {
byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET);
IkeHeader header = new IkeHeader(inputPacket);
diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeMessageTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeMessageTest.java
index e2a1c9e1..8ba35560 100644
--- a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeMessageTest.java
+++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeMessageTest.java
@@ -21,7 +21,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import com.android.ike.ikev2.exceptions.IkeException;
-import com.android.ike.ikev2.exceptions.InvalidMajorVersionException;
import com.android.ike.ikev2.exceptions.InvalidSyntaxException;
import com.android.ike.ikev2.exceptions.UnsupportedCriticalPayloadException;
@@ -50,10 +49,14 @@ public final class IkeMessageTest {
private static final String IKE_SA_INIT_RAW_PACKET =
IKE_SA_INIT_HEADER_RAW_PACKET + IKE_SA_INIT_BODY_RAW_PACKET;
- private static final int FIRST_PAYLOAD_TYPE_POSITION = 16;
- private static final int VERSION_POSITION = 17;
- private static final int EXCHANGE_TYPE_POSITION = 18;
- private static final int PAYLOAD_CRITICAL_BIT_POSITION = 1;
+ // 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 int[] SUPPORTED_PAYLOAD_LIST = {
IkePayload.PAYLOAD_TYPE_SA,
@@ -120,7 +123,7 @@ public final class IkeMessageTest {
public void testDecodeMessageWithUnsupportedUncriticalPayload() throws Exception {
byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET);
// Set first payload unsupported uncritical
- inputPacket[FIRST_PAYLOAD_TYPE_POSITION] = (byte) 0xff;
+ inputPacket[FIRST_PAYLOAD_TYPE_OFFSET] = (byte) 0xff;
IkeHeader header = new IkeHeader(inputPacket);
IkeMessage message = IkeMessage.decode(header, inputPacket);
assertEquals(SUPPORTED_PAYLOAD_LIST.length - 1, message.ikePayloadList.size());
@@ -130,51 +133,58 @@ public final class IkeMessageTest {
}
@Test
- public void testThrowInvalidMajorVersionException() throws Exception {
+ public void testThrowUnsupportedCriticalPayloadException() throws Exception {
byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET);
- // Set major version 3.
- inputPacket[VERSION_POSITION] = (byte) 0x30;
- // Set Exchange type 0
- inputPacket[EXCHANGE_TYPE_POSITION] = (byte) 0x00;
+ // Set first payload unsupported critical
+ inputPacket[FIRST_PAYLOAD_TYPE_OFFSET] = (byte) 0xff;
+ inputPacket[IkeHeader.IKE_HEADER_LENGTH + PAYLOAD_CRITICAL_BIT_OFFSET] = (byte) 0x80;
+
IkeHeader header = new IkeHeader(inputPacket);
try {
IkeMessage.decode(header, inputPacket);
fail(
- "Expected InvalidMajorVersionException: major version is 3"
- + "and packet length is 0");
- } catch (InvalidMajorVersionException expected) {
- assertEquals(3, expected.receivedMajorVersion);
+ "Expected UnsupportedCriticalPayloadException: first"
+ + "payload is unsupported critical.");
+ } catch (UnsupportedCriticalPayloadException expected) {
+ assertEquals(1, expected.payloadTypeList.size());
}
}
@Test
- public void testThrowInvalidSyntaxException() throws Exception {
+ public void testDecodeMessageWithTooShortPayloadLength() throws Exception {
byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET);
- // Set Exchange type 0
- inputPacket[EXCHANGE_TYPE_POSITION] = (byte) 0x00;
+ // 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;
IkeHeader header = new IkeHeader(inputPacket);
try {
- IkeMessage.decode(header, inputPacket);
- fail("Expected InvalidSyntaxException: packet length is 0");
+ IkeMessage message = IkeMessage.decode(header, inputPacket);
+ fail("Expected InvalidSyntaxException: Payload length is too short.");
} catch (InvalidSyntaxException expected) {
}
}
@Test
- public void testThrowUnsupportedCriticalPayloadException() throws Exception {
+ public void testDecodeMessageWithTooLongPayloadLength() throws Exception {
byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET);
- // Set first payload unsupported critical
- inputPacket[FIRST_PAYLOAD_TYPE_POSITION] = (byte) 0xff;
- inputPacket[IkeHeader.IKE_HEADER_LENGTH + PAYLOAD_CRITICAL_BIT_POSITION] = (byte) 0x80;
+ // Increase last payload length by one byte
+ inputPacket[IkeHeader.IKE_HEADER_LENGTH + LAST_PAYLOAD_LENGTH_OFFSET]++;
+ IkeHeader header = new IkeHeader(inputPacket);
+ try {
+ IkeMessage message = IkeMessage.decode(header, inputPacket);
+ fail("Expected InvalidSyntaxException: Payload length is too long.");
+ } catch (InvalidSyntaxException expected) {
+ }
+ }
+ @Test
+ public void testDecodeMessageWithExpectedBytesInTheEnd() throws Exception {
+ byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET + "0000");
IkeHeader header = new IkeHeader(inputPacket);
try {
- IkeMessage.decode(header, inputPacket);
- fail(
- "Expected UnsupportedCriticalPayloadException: first"
- + "payload is unsupported critical.");
- } catch (UnsupportedCriticalPayloadException expected) {
- assertEquals(1, expected.payloadTypeList.size());
+ IkeMessage message = IkeMessage.decode(header, inputPacket);
+ fail("Expected InvalidSyntaxException: Unexpected bytes in the end of packet.");
+ } catch (InvalidSyntaxException expected) {
}
}