aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/java/com/android/ike/ikev2/message/IkeKePayload.java25
-rw-r--r--src/java/com/android/ike/ikev2/message/IkeMessage.java31
-rw-r--r--src/java/com/android/ike/ikev2/message/IkeNoncePayload.java24
-rw-r--r--src/java/com/android/ike/ikev2/message/IkeNotifyPayload.java19
-rw-r--r--src/java/com/android/ike/ikev2/message/IkePayload.java31
-rw-r--r--src/java/com/android/ike/ikev2/message/IkeSaPayload.java18
-rw-r--r--src/java/com/android/ike/ikev2/message/IkeUnsupportedPayload.java14
-rw-r--r--src/java/com/android/ike/ikev2/message/IkeVendorPayload.java14
-rw-r--r--tests/iketests/src/java/com/android/ike/ikev2/message/IkeMessageTest.java10
-rw-r--r--tests/iketests/src/java/com/android/ike/ikev2/message/IkeNoncePayloadTest.java47
-rw-r--r--tests/iketests/src/java/com/android/ike/ikev2/message/IkeNotifyPayloadTest.java1
11 files changed, 208 insertions, 26 deletions
diff --git a/src/java/com/android/ike/ikev2/message/IkeKePayload.java b/src/java/com/android/ike/ikev2/message/IkeKePayload.java
index 106bd234..5516ac52 100644
--- a/src/java/com/android/ike/ikev2/message/IkeKePayload.java
+++ b/src/java/com/android/ike/ikev2/message/IkeKePayload.java
@@ -120,19 +120,31 @@ public final class IkeKePayload extends IkePayload {
}
/**
- * Encode KE payload to byte array.
+ * Encode KE payload to ByteBuffer.
*
* @param nextPayload type of payload that follows this payload.
- * @return encoded KE payload
+ * @param byteBuffer destination ByteBuffer that stores encoded payload.
*/
@Override
- byte[] encode(@PayloadType int nextPayload) {
+ protected void encodeToByteBuffer(@PayloadType int nextPayload, ByteBuffer byteBuffer) {
throw new UnsupportedOperationException(
"It is not supported to encode a " + getTypeString());
// TODO: Implement encoding KE payload.
}
/**
+ * 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 this method for KE payload.
+ }
+
+ /**
* Construct an instance of IkeKePayload according to its {@link DhGroup}.
*
* @param dh the Dh-Group. It should be in {@link DhGroup}
@@ -164,7 +176,8 @@ public final class IkeKePayload extends IkePayload {
DHParameterSpec dhParams = new DHParameterSpec(prime, baseGen);
KeyPairGenerator dhKeyPairGen =
- KeyPairGenerator.getInstance(KEY_EXCHANGE_ALGORITHM, IkeMessage.getProvider());
+ KeyPairGenerator.getInstance(
+ KEY_EXCHANGE_ALGORITHM, IkeMessage.getSecurityProvider());
// By default SecureRandom uses AndroidOpenSSL provided SHA1PRNG Algorithm, which takes
// /dev/urandom as seed source.
dhKeyPairGen.initialize(dhParams, new SecureRandom());
@@ -199,13 +212,13 @@ public final class IkeKePayload extends IkePayload {
DHPublicKeySpec publicKeySpec =
new DHPublicKeySpec(publicKeyValue, primeValue, baseGenValue);
KeyFactory dhKeyFactory =
- KeyFactory.getInstance(KEY_EXCHANGE_ALGORITHM, IkeMessage.getProvider());
+ KeyFactory.getInstance(KEY_EXCHANGE_ALGORITHM, IkeMessage.getSecurityProvider());
DHPublicKey publicKey = (DHPublicKey) dhKeyFactory.generatePublic(publicKeySpec);
DHPrivateKey privateKey = (DHPrivateKey) dhKeyFactory.generatePrivate(privateKeySpec);
// Calculate shared secret
KeyAgreement dhKeyAgreement =
- KeyAgreement.getInstance(KEY_EXCHANGE_ALGORITHM, IkeMessage.getProvider());
+ KeyAgreement.getInstance(KEY_EXCHANGE_ALGORITHM, IkeMessage.getSecurityProvider());
dhKeyAgreement.init(privateKey);
dhKeyAgreement.doPhase(publicKey, true/** Last phase */);
diff --git a/src/java/com/android/ike/ikev2/message/IkeMessage.java b/src/java/com/android/ike/ikev2/message/IkeMessage.java
index 69c1bbdb..118e2f0f 100644
--- a/src/java/com/android/ike/ikev2/message/IkeMessage.java
+++ b/src/java/com/android/ike/ikev2/message/IkeMessage.java
@@ -106,7 +106,36 @@ public final class IkeMessage {
return new IkeMessage(header, supportedPayloadList);
}
- static Provider getProvider() {
+ static Provider getSecurityProvider() {
return SECURITY_PROVIDER;
}
+
+ /**
+ * Encode all payloads to a byte array.
+ *
+ * @return byte array contains all encoded payloads
+ */
+ public byte[] encodePayloads() {
+ if (ikePayloadList.isEmpty()) {
+ return new byte[0];
+ }
+
+ int payloadLengthSum = 0;
+ for (IkePayload payload : ikePayloadList) {
+ payloadLengthSum += payload.getPayloadLength();
+ }
+
+ ByteBuffer byteBuffer = ByteBuffer.allocate(payloadLengthSum);
+
+ for (int i = 0; i < ikePayloadList.size() - 1; i++) {
+ ikePayloadList
+ .get(i)
+ .encodeToByteBuffer(ikePayloadList.get(i + 1).payloadType, byteBuffer);
+ }
+ ikePayloadList
+ .get(ikePayloadList.size() - 1)
+ .encodeToByteBuffer(IkePayload.PAYLOAD_TYPE_NO_NEXT, byteBuffer);
+
+ return byteBuffer.array();
+ }
}
diff --git a/src/java/com/android/ike/ikev2/message/IkeNoncePayload.java b/src/java/com/android/ike/ikev2/message/IkeNoncePayload.java
index 156935cb..3792e938 100644
--- a/src/java/com/android/ike/ikev2/message/IkeNoncePayload.java
+++ b/src/java/com/android/ike/ikev2/message/IkeNoncePayload.java
@@ -19,6 +19,7 @@ package com.android.ike.ikev2.message;
import com.android.ike.ikev2.exceptions.IkeException;
import com.android.ike.ikev2.exceptions.InvalidSyntaxException;
+import java.nio.ByteBuffer;
import java.security.SecureRandom;
/**
@@ -71,16 +72,27 @@ public final class IkeNoncePayload extends IkePayload {
}
/**
- * Encode Nonce payload to byte array.
+ * Encode Nonce payload to ByteBuffer.
*
* @param nextPayload type of payload that follows this payload.
- * @return encoded Nonce payload
+ * @param byteBuffer destination ByteBuffer that stores encoded payload.
*/
@Override
- byte[] encode(@PayloadType int nextPayload) {
- throw new UnsupportedOperationException(
- "It is not supported to encode a " + getTypeString());
- // TODO: Implement encoding Nonce payload.
+ protected void encodeToByteBuffer(@PayloadType int nextPayload, ByteBuffer byteBuffer) {
+ int payloadLength = GENERIC_HEADER_LENGTH + nonceData.length;
+
+ encodePayloadHeaderToByteBuffer(nextPayload, payloadLength, byteBuffer);
+ byteBuffer.put(nonceData);
+ }
+
+ /**
+ * Get entire payload length.
+ *
+ * @return entire payload length.
+ */
+ @Override
+ protected int getPayloadLength() {
+ return GENERIC_HEADER_LENGTH + nonceData.length;
}
/**
diff --git a/src/java/com/android/ike/ikev2/message/IkeNotifyPayload.java b/src/java/com/android/ike/ikev2/message/IkeNotifyPayload.java
index 9476b69b..369a034d 100644
--- a/src/java/com/android/ike/ikev2/message/IkeNotifyPayload.java
+++ b/src/java/com/android/ike/ikev2/message/IkeNotifyPayload.java
@@ -125,20 +125,33 @@ public final class IkeNotifyPayload extends IkePayload {
notifyData = new byte[payloadBody.length - NOTIFY_HEADER_LEN];
inputBuffer.get(notifyData);
}
+
/**
- * Encode Notify payload to byte array.
+ * Encode Notify payload to ByteBuffer.
*
* @param nextPayload type of payload that follows this payload.
- * @return encoded Notify payload
+ * @param byteBuffer destination ByteBuffer that stores encoded payload.
*/
@Override
- byte[] encode(@PayloadType int nextPayload) {
+ protected void encodeToByteBuffer(@PayloadType int nextPayload, ByteBuffer byteBuffer) {
throw new UnsupportedOperationException(
"It is not supported to encode a " + getTypeString());
// TODO: Implement encoding Notify payload.
}
/**
+ * 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 this method for Notify payload.
+ }
+
+ /**
* Return the payload type as a String.
*
* @return the payload type as a String.
diff --git a/src/java/com/android/ike/ikev2/message/IkePayload.java b/src/java/com/android/ike/ikev2/message/IkePayload.java
index 5333ed6f..2a591063 100644
--- a/src/java/com/android/ike/ikev2/message/IkePayload.java
+++ b/src/java/com/android/ike/ikev2/message/IkePayload.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.nio.ByteBuffer;
/**
* IkePayload is an abstract class that represents the common information for all IKE payload types.
@@ -31,6 +32,8 @@ import java.lang.annotation.RetentionPolicy;
* Protocol Version 2 (IKEv2).
*/
public abstract class IkePayload {
+ // Critical bit and following reserved 7 bits in payload generic header must all be zero
+ private static final byte PAYLOAD_HEADER_CRITICAL_BIT_UNSET = 0;
/** Length of a generic IKE payload header */
public static final int GENERIC_HEADER_LENGTH = 4;
@@ -108,12 +111,34 @@ public abstract class IkePayload {
}
/**
- * Encode payload to byte array.
+ * Encode generic payload header to ByteBuffer.
*
* @param nextPayload type of payload that follows this payload.
- * @return encoded payload
+ * @param payloadLength length of the entire payload
+ * @param byteBuffer destination ByteBuffer that stores encoded payload header
*/
- abstract byte[] encode(@PayloadType int nextPayload);
+ protected void encodePayloadHeaderToByteBuffer(
+ @PayloadType int nextPayload, int payloadLength, ByteBuffer byteBuffer) {
+ byteBuffer
+ .put((byte) nextPayload)
+ .put(PAYLOAD_HEADER_CRITICAL_BIT_UNSET)
+ .putShort((short) payloadLength);
+ }
+
+ /**
+ * Encode payload to ByteBuffer.
+ *
+ * @param nextPayload type of payload that follows this payload.
+ * @param byteBuffer destination ByteBuffer that stores encoded payload.
+ */
+ protected abstract void encodeToByteBuffer(@PayloadType int nextPayload, ByteBuffer byteBuffer);
+
+ /**
+ * Get entire payload length.
+ *
+ * @return entire payload length.
+ */
+ protected abstract int getPayloadLength();
/**
* Return the payload type as a String.
diff --git a/src/java/com/android/ike/ikev2/message/IkeSaPayload.java b/src/java/com/android/ike/ikev2/message/IkeSaPayload.java
index 8734797f..e3ded360 100644
--- a/src/java/com/android/ike/ikev2/message/IkeSaPayload.java
+++ b/src/java/com/android/ike/ikev2/message/IkeSaPayload.java
@@ -299,19 +299,31 @@ public final class IkeSaPayload extends IkePayload {
}
/**
- * Encode SA payload to byte array.
+ * Encode SA payload to ByteBUffer.
*
* @param nextPayload type of payload that follows this payload.
- * @return encoded SA payload
+ * @param byteBuffer destination ByteBuffer that stores encoded payload.
*/
@Override
- byte[] encode(@PayloadType int nextPayload) {
+ protected void encodeToByteBuffer(@PayloadType int nextPayload, ByteBuffer byteBuffer) {
throw new UnsupportedOperationException(
"It is not supported to encode a " + getTypeString());
// TODO: Implement encoding SA payload.
}
/**
+ * 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 this method for SA payload.
+ }
+
+ /**
* Return the payload type as a String.
*
* @return the payload type as a String.
diff --git a/src/java/com/android/ike/ikev2/message/IkeUnsupportedPayload.java b/src/java/com/android/ike/ikev2/message/IkeUnsupportedPayload.java
index 17c07702..4b581cc8 100644
--- a/src/java/com/android/ike/ikev2/message/IkeUnsupportedPayload.java
+++ b/src/java/com/android/ike/ikev2/message/IkeUnsupportedPayload.java
@@ -16,6 +16,7 @@
package com.android.ike.ikev2.message;
+import java.nio.ByteBuffer;
/**
* IkeUnsupportedPayload represents anunsupported payload.
*
@@ -41,12 +42,23 @@ final class IkeUnsupportedPayload extends IkePayload {
* @throws UnsupportedOperationException for this payload.
*/
@Override
- byte[] encode(@PayloadType int nextPayload) {
+ protected void encodeToByteBuffer(@PayloadType int nextPayload, ByteBuffer byteBuffer) {
throw new UnsupportedOperationException(
"It is not supported to encode a " + getTypeString());
}
/**
+ * Throw an Exception when trying to get payload length
+ *
+ * @throws UnsupportedOperationException for this payload.
+ */
+ @Override
+ protected int getPayloadLength() {
+ throw new UnsupportedOperationException(
+ "It is not supported to get payload length of " + getTypeString());
+ }
+
+ /**
* Return the payload type as a String.
*
* @return the payload type as a String.
diff --git a/src/java/com/android/ike/ikev2/message/IkeVendorPayload.java b/src/java/com/android/ike/ikev2/message/IkeVendorPayload.java
index 5fabfc1a..ee224e9a 100644
--- a/src/java/com/android/ike/ikev2/message/IkeVendorPayload.java
+++ b/src/java/com/android/ike/ikev2/message/IkeVendorPayload.java
@@ -16,6 +16,8 @@
package com.android.ike.ikev2.message;
+import java.nio.ByteBuffer;
+
/**
* IkeVendorPayload represents a Vendor ID payload
*
@@ -47,12 +49,22 @@ public final class IkeVendorPayload extends IkePayload {
* @throws UnsupportedOperationException for this payload.
*/
@Override
- byte[] encode(@PayloadType int nextPayload) {
+ protected void encodeToByteBuffer(@PayloadType int nextPayload, ByteBuffer byteBuffer) {
throw new UnsupportedOperationException(
"It is not supported to encode a " + getTypeString());
}
/**
+ * Get entire payload length.
+ *
+ * @return entire payload length.
+ */
+ @Override
+ protected int getPayloadLength() {
+ return GENERIC_HEADER_LENGTH + vendorId.length;
+ }
+
+ /**
* Return the payload type as a String.
*
* @return the payload type as a String.
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 b7ecc3d6..05c59607 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
@@ -29,6 +29,8 @@ import com.android.ike.ikev2.exceptions.UnsupportedCriticalPayloadException;
import org.junit.Before;
import org.junit.Test;
+import java.nio.ByteBuffer;
+
public final class IkeMessageTest {
private static final String IKE_SA_INIT_RAW_PACKET =
"8f54bf6d8b48e6e100000000000000002120220800000000"
@@ -80,12 +82,18 @@ public final class IkeMessageTest {
}
@Override
- byte[] encode(@PayloadType int nextPayload) {
+ 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 Payload";
}
diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeNoncePayloadTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeNoncePayloadTest.java
new file mode 100644
index 00000000..a15507c5
--- /dev/null
+++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeNoncePayloadTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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 org.junit.Test;
+
+import java.nio.ByteBuffer;
+
+public final class IkeNoncePayloadTest {
+
+ private static final String NONCE_PAYLOAD_RAW_HEX_STRING =
+ "29000024c39b7f368f4681b89fa9b7be6465abd7c5f68b6ed5d3b4c72cb4240eb5c46412";
+ private static final String NONCE_DATA_RAW_HEX_STRING =
+ "c39b7f368f4681b89fa9b7be6465abd7c5f68b6ed5d3b4c72cb4240eb5c46412";
+
+ @IkePayload.PayloadType
+ private static final int NEXT_PAYLOAD_TYPE = IkePayload.PAYLOAD_TYPE_NOTIFY;
+
+ @Test
+ public void testEncode() throws Exception {
+ byte[] inputPacket = TestUtils.hexStringToByteArray(NONCE_DATA_RAW_HEX_STRING);
+ IkeNoncePayload payload = new IkeNoncePayload(false, inputPacket);
+
+ ByteBuffer byteBuffer = ByteBuffer.allocate(payload.getPayloadLength());
+ payload.encodeToByteBuffer(NEXT_PAYLOAD_TYPE, byteBuffer);
+
+ byte[] expectedNoncePayload =
+ TestUtils.hexStringToByteArray(NONCE_PAYLOAD_RAW_HEX_STRING);
+ assertArrayEquals(expectedNoncePayload, byteBuffer.array());
+ }
+}
diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeNotifyPayloadTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeNotifyPayloadTest.java
index 4968826c..382f04b1 100644
--- a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeNotifyPayloadTest.java
+++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeNotifyPayloadTest.java
@@ -33,7 +33,6 @@ public final class IkeNotifyPayloadTest {
private static final int EXPECTED_NOTIFY_TYPE =
IkeNotifyPayload.NOTIFY_TYPE_NAT_DETECTION_SOURCE_IP;
- private static final int EXPECTED_SPI = 0;
private static final int EXPECTED_NOTIFY_DATA_LEN = 20;
private static final int POS_PROTOCOL_ID = 0;