aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/java/com/android/ike/ikev2/message/IkePayload.java11
-rw-r--r--src/java/com/android/ike/ikev2/message/IkePayloadFactory.java82
-rw-r--r--src/java/com/android/ike/ikev2/message/IkeTsPayload.java95
-rw-r--r--tests/iketests/src/java/com/android/ike/ikev2/message/IkeMessageTest.java8
-rw-r--r--tests/iketests/src/java/com/android/ike/ikev2/message/IkeTsPayloadTest.java45
5 files changed, 207 insertions, 34 deletions
diff --git a/src/java/com/android/ike/ikev2/message/IkePayload.java b/src/java/com/android/ike/ikev2/message/IkePayload.java
index 332450f7..11ec94a9 100644
--- a/src/java/com/android/ike/ikev2/message/IkePayload.java
+++ b/src/java/com/android/ike/ikev2/message/IkePayload.java
@@ -37,6 +37,11 @@ public abstract class IkePayload {
/** Length of a generic IKE payload header */
public static final int GENERIC_HEADER_LENGTH = 4;
+ /**
+ * Payload types as defined by IANA:
+ *
+ * @see <a href="https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml">
+ */
@Retention(RetentionPolicy.SOURCE)
@IntDef({
PAYLOAD_TYPE_NO_NEXT,
@@ -49,6 +54,8 @@ public abstract class IkePayload {
PAYLOAD_TYPE_NONCE,
PAYLOAD_TYPE_NOTIFY,
PAYLOAD_TYPE_VENDOR,
+ PAYLOAD_TYPE_TS_INITIATOR,
+ PAYLOAD_TYPE_TS_RESPONDER,
PAYLOAD_TYPE_SK
})
public @interface PayloadType {}
@@ -73,6 +80,10 @@ public abstract class IkePayload {
public static final int PAYLOAD_TYPE_NOTIFY = 41;
/** Vendor Payload */
public static final int PAYLOAD_TYPE_VENDOR = 43;
+ /** Traffic Selector Payload of Child SA Initiator */
+ public static final int PAYLOAD_TYPE_TS_INITIATOR = 44;
+ /** Traffic Selector Payload of Child SA Responder */
+ public static final int PAYLOAD_TYPE_TS_RESPONDER = 45;
/** Encrypted and Authenticated Payload */
public static final int PAYLOAD_TYPE_SK = 46;
diff --git a/src/java/com/android/ike/ikev2/message/IkePayloadFactory.java b/src/java/com/android/ike/ikev2/message/IkePayloadFactory.java
index a091618d..ef47b0ca 100644
--- a/src/java/com/android/ike/ikev2/message/IkePayloadFactory.java
+++ b/src/java/com/android/ike/ikev2/message/IkePayloadFactory.java
@@ -45,39 +45,49 @@ final class IkePayloadFactory {
return (flagByte & PAYLOAD_HEADER_CRITICAL_BIT_SET) == PAYLOAD_HEADER_CRITICAL_BIT_SET;
}
- /** Default instance used for constructing IkePayload */
+ /** Default IIkePayloadDecoder instance used for constructing IkePayload */
+ static IIkePayloadDecoder sDecoderInstance = new IkePayloadDecoder();
+
+ /**
+ * IkePayloadDecoder implements IIkePayloadDecoder for constructing IkePayload from decoding
+ * received message.
+ *
+ * <p>Package private
+ */
@VisibleForTesting
- static IkePayloadDecoder sDecoderInstance =
- new IkePayloadDecoder() {
- @Override
- public IkePayload decodeIkePayload(
- int payloadType, boolean isCritical, byte[] payloadBody)
- throws IkeException {
- switch (payloadType) {
- // TODO: Add cases for creating supported payloads.
- case IkePayload.PAYLOAD_TYPE_SA:
- return new IkeSaPayload(isCritical, payloadBody);
- case IkePayload.PAYLOAD_TYPE_KE:
- return new IkeKePayload(isCritical, payloadBody);
- case IkePayload.PAYLOAD_TYPE_ID_INITIATOR:
- return new IkeIdPayload(isCritical, payloadBody, true);
- case IkePayload.PAYLOAD_TYPE_ID_RESPONDER:
- return new IkeIdPayload(isCritical, payloadBody, false);
- case IkePayload.PAYLOAD_TYPE_CERT:
- return IkeCertPayload.getIkeCertPayload(isCritical, payloadBody);
- case IkePayload.PAYLOAD_TYPE_AUTH:
- return IkeAuthPayload.getIkeAuthPayload(isCritical, payloadBody);
- case IkePayload.PAYLOAD_TYPE_NONCE:
- return new IkeNoncePayload(isCritical, payloadBody);
- case IkePayload.PAYLOAD_TYPE_NOTIFY:
- return new IkeNotifyPayload(isCritical, payloadBody);
- case IkePayload.PAYLOAD_TYPE_VENDOR:
- return new IkeVendorPayload(isCritical, payloadBody);
- default:
- return new IkeUnsupportedPayload(payloadType, isCritical);
- }
- }
- };
+ static class IkePayloadDecoder implements IIkePayloadDecoder {
+ @Override
+ public IkePayload decodeIkePayload(int payloadType, boolean isCritical, byte[] payloadBody)
+ throws IkeException {
+ switch (payloadType) {
+ // TODO: Add cases for creating supported payloads.
+ case IkePayload.PAYLOAD_TYPE_SA:
+ return new IkeSaPayload(isCritical, payloadBody);
+ case IkePayload.PAYLOAD_TYPE_KE:
+ return new IkeKePayload(isCritical, payloadBody);
+ case IkePayload.PAYLOAD_TYPE_ID_INITIATOR:
+ return new IkeIdPayload(isCritical, payloadBody, true);
+ case IkePayload.PAYLOAD_TYPE_ID_RESPONDER:
+ return new IkeIdPayload(isCritical, payloadBody, false);
+ case IkePayload.PAYLOAD_TYPE_CERT:
+ return IkeCertPayload.getIkeCertPayload(isCritical, payloadBody);
+ case IkePayload.PAYLOAD_TYPE_AUTH:
+ return IkeAuthPayload.getIkeAuthPayload(isCritical, payloadBody);
+ case IkePayload.PAYLOAD_TYPE_NONCE:
+ return new IkeNoncePayload(isCritical, payloadBody);
+ case IkePayload.PAYLOAD_TYPE_NOTIFY:
+ return new IkeNotifyPayload(isCritical, payloadBody);
+ case IkePayload.PAYLOAD_TYPE_VENDOR:
+ return new IkeVendorPayload(isCritical, payloadBody);
+ case IkePayload.PAYLOAD_TYPE_TS_INITIATOR:
+ return new IkeTsPayload(isCritical, payloadBody, true);
+ case IkePayload.PAYLOAD_TYPE_TS_RESPONDER:
+ return new IkeTsPayload(isCritical, payloadBody, false);
+ default:
+ return new IkeUnsupportedPayload(payloadType, isCritical);
+ }
+ }
+ }
/**
* Construct an instance of IkePayload according to its payload type.
@@ -170,8 +180,14 @@ final class IkePayloadFactory {
return new Pair(payload, nextPayloadType);
}
+ /**
+ * IIkePayloadDecoder provides a package private interface for constructing IkePayload from
+ * decoding received message.
+ *
+ * <p>IIkePayloadDecoder exists so that the interface is injectable for testing.
+ */
@VisibleForTesting
- interface IkePayloadDecoder {
+ interface IIkePayloadDecoder {
IkePayload decodeIkePayload(int payloadType, boolean isCritical, byte[] payloadBody)
throws IkeException;
}
diff --git a/src/java/com/android/ike/ikev2/message/IkeTsPayload.java b/src/java/com/android/ike/ikev2/message/IkeTsPayload.java
new file mode 100644
index 00000000..339e92e6
--- /dev/null
+++ b/src/java/com/android/ike/ikev2/message/IkeTsPayload.java
@@ -0,0 +1,95 @@
+/*
+ * 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.message;
+
+import com.android.ike.ikev2.exceptions.IkeException;
+
+import java.nio.ByteBuffer;
+
+/**
+ * IkeTsPayload represents an Traffic Selector Initiator Payload or an Traffic Selector Responder
+ * Payload.
+ *
+ * <p>Traffic Selector Initiator Payload and Traffic Selector Responder Payload have same format but
+ * different payload types. They describe the address ranges and port ranges of Child SA initiator
+ * and Child SA responder.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.13">RFC 7296, Internet Key Exchange
+ * Protocol Version 2 (IKEv2).
+ */
+public final class IkeTsPayload extends IkePayload {
+ // Length of reserved field in octets.
+ private static final int TS_HEADER_RESERVED_LEN = 3;
+
+ /** Number of Traffic Selectors */
+ public final int numTs;
+
+ IkeTsPayload(boolean critical, byte[] payloadBody, boolean isInitiator) throws IkeException {
+ super((isInitiator ? PAYLOAD_TYPE_TS_INITIATOR : PAYLOAD_TYPE_TS_RESPONDER), critical);
+
+ ByteBuffer inputBuffer = ByteBuffer.wrap(payloadBody);
+ numTs = Byte.toUnsignedInt(inputBuffer.get());
+ // Skip RESERVED byte
+ inputBuffer.get(new byte[TS_HEADER_RESERVED_LEN]);
+
+ // TODO: Decode Traffic Selectors.
+ }
+
+ /**
+ * Encode Traffic Selector Payload to ByteBuffer.
+ *
+ * @param nextPayload type of payload that follows this payload.
+ * @param byteBuffer destination ByteBuffer that stores encoded payload.
+ */
+ @Override
+ protected void encodeToByteBuffer(@PayloadType int nextPayload, ByteBuffer byteBuffer) {
+ throw new UnsupportedOperationException(
+ "It is not supported to encode a " + getTypeString());
+ //TODO: Implement it.
+ }
+
+ /**
+ * Get entire payload length.
+ *
+ * @return entire payload length.
+ */
+ @Override
+ protected int getPayloadLength() {
+ throw new UnsupportedOperationException(
+ "It is not supported to get payload length of " + getTypeString());
+ //TODO: Implement it.
+ }
+
+ /**
+ * Return the payload type as a String.
+ *
+ * @return the payload type as a String.
+ */
+ @Override
+ public String getTypeString() {
+ switch (payloadType) {
+ case PAYLOAD_TYPE_ID_INITIATOR:
+ return "Traffic Selector Initiator Payload";
+ case PAYLOAD_TYPE_ID_RESPONDER:
+ return "Traffic Selector Responder Payload";
+ default:
+ // Won't reach here.
+ throw new IllegalArgumentException(
+ "Invalid Payload Type for Traffic Selector Payload.");
+ }
+ }
+}
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 75f2ca20..8584f78a 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
@@ -24,6 +24,7 @@ import com.android.ike.ikev2.exceptions.IkeException;
import com.android.ike.ikev2.exceptions.InvalidSyntaxException;
import com.android.ike.ikev2.exceptions.UnsupportedCriticalPayloadException;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -93,7 +94,7 @@ public final class IkeMessageTest {
@Before
public void setUp() {
IkePayloadFactory.sDecoderInstance =
- new IkePayloadFactory.IkePayloadDecoder() {
+ new IkePayloadFactory.IIkePayloadDecoder() {
@Override
public IkePayload decodeIkePayload(
@@ -108,6 +109,11 @@ public final class IkeMessageTest {
};
}
+ @After
+ public void tearDown() {
+ IkePayloadFactory.sDecoderInstance = new IkePayloadFactory.IkePayloadDecoder();
+ }
+
@Test
public void testDecodeIkeMessage() throws Exception {
byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET);
diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeTsPayloadTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeTsPayloadTest.java
new file mode 100644
index 00000000..f1c8b6e6
--- /dev/null
+++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeTsPayloadTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.message;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import java.nio.ByteBuffer;
+
+public final class IkeTsPayloadTest {
+ private static final String TS_INITIATOR_PAYLOAD_HEX_STRING =
+ "2d00001801000000070000100000ffff00000000ffffffff";
+ private static final int NUMBER_OF_TS = 1;
+
+ @Test
+ public void testDecodeTsInitiatorPayload() throws Exception {
+ ByteBuffer inputBuffer =
+ ByteBuffer.wrap(TestUtils.hexStringToByteArray(TS_INITIATOR_PAYLOAD_HEX_STRING));
+
+ IkePayload payload =
+ IkePayloadFactory.getIkePayload(IkePayload.PAYLOAD_TYPE_TS_INITIATOR, inputBuffer)
+ .first;
+ assertTrue(payload instanceof IkeTsPayload);
+
+ IkeTsPayload tsPayload = (IkeTsPayload) payload;
+ assertEquals(IkePayload.PAYLOAD_TYPE_TS_INITIATOR, tsPayload.payloadType);
+ assertEquals(NUMBER_OF_TS, tsPayload.numTs);
+ }
+}