aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorevitayan <evitayan@google.com>2019-02-08 16:14:19 -0800
committerevitayan <evitayan@google.com>2019-02-14 13:05:34 -0800
commit4b255a59d01857ebc4a508106a8917e6b3710745 (patch)
tree82da3634a468ff04144727caafc3611229800bbf
parenta82e2910b79091e539328ccb7f296e0b9981aaf1 (diff)
downloadike-4b255a59d01857ebc4a508106a8917e6b3710745.tar.gz
Build outbound IkeAuthPskPayload
This commit: - Create constructor for building outbound IkeAuthPskPayload - Support calculating PSK signature - Support encoding IkeAuthPskPayload Bug: 122686851 Test: FrameworksIkeTests IkeAuthPskPayload Change-Id: I28c8c6c3c03a339761547303d4caacfd2db31729
-rw-r--r--src/java/com/android/ike/ikev2/message/IkeAuthDigitalSignPayload.java4
-rw-r--r--src/java/com/android/ike/ikev2/message/IkeAuthPayload.java18
-rw-r--r--src/java/com/android/ike/ikev2/message/IkeAuthPskPayload.java77
-rw-r--r--tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthPayloadTest.java4
-rw-r--r--tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthPskPayloadTest.java91
5 files changed, 178 insertions, 16 deletions
diff --git a/src/java/com/android/ike/ikev2/message/IkeAuthDigitalSignPayload.java b/src/java/com/android/ike/ikev2/message/IkeAuthDigitalSignPayload.java
index 12fb5f66..5b5a3f0b 100644
--- a/src/java/com/android/ike/ikev2/message/IkeAuthDigitalSignPayload.java
+++ b/src/java/com/android/ike/ikev2/message/IkeAuthDigitalSignPayload.java
@@ -138,14 +138,14 @@ public class IkeAuthDigitalSignPayload extends IkeAuthPayload {
// TODO: Add methods for generating and validating signature.
@Override
- protected void encodeToByteBuffer(@PayloadType int nextPayload, ByteBuffer byteBuffer) {
+ protected void encodeAuthDataToByteBuffer(ByteBuffer byteBuffer) {
// TODO: Implement it.
throw new UnsupportedOperationException(
"It is not supported to encode a " + getTypeString());
}
@Override
- protected int getPayloadLength() {
+ protected int getAuthDataLength() {
// TODO: Implement it.
throw new UnsupportedOperationException(
"It is not supported to get payload length of " + getTypeString());
diff --git a/src/java/com/android/ike/ikev2/message/IkeAuthPayload.java b/src/java/com/android/ike/ikev2/message/IkeAuthPayload.java
index beb2bdc6..502af36a 100644
--- a/src/java/com/android/ike/ikev2/message/IkeAuthPayload.java
+++ b/src/java/com/android/ike/ikev2/message/IkeAuthPayload.java
@@ -61,7 +61,7 @@ public abstract class IkeAuthPayload extends IkePayload {
@AuthMethod public final int authMethod;
- protected IkeAuthPayload(boolean critical, int authMethod) throws IkeException {
+ protected IkeAuthPayload(boolean critical, int authMethod) {
super(PAYLOAD_TYPE_AUTH, critical);
this.authMethod = authMethod;
}
@@ -131,7 +131,23 @@ public abstract class IkeAuthPayload extends IkePayload {
}
@Override
+ protected void encodeToByteBuffer(@PayloadType int nextPayload, ByteBuffer byteBuffer) {
+ encodePayloadHeaderToByteBuffer(nextPayload, getPayloadLength(), byteBuffer);
+ byteBuffer.put((byte) authMethod).put(new byte[AUTH_RESERVED_FIELD_LEN]);
+ encodeAuthDataToByteBuffer(byteBuffer);
+ }
+
+ @Override
+ protected int getPayloadLength() {
+ return GENERIC_HEADER_LENGTH + AUTH_HEADER_LEN + getAuthDataLength();
+ }
+
+ @Override
public String getTypeString() {
return "Authentication Payload";
}
+
+ protected abstract void encodeAuthDataToByteBuffer(ByteBuffer byteBuffer);
+
+ protected abstract int getAuthDataLength();
}
diff --git a/src/java/com/android/ike/ikev2/message/IkeAuthPskPayload.java b/src/java/com/android/ike/ikev2/message/IkeAuthPskPayload.java
index 63f45dd5..213e24a3 100644
--- a/src/java/com/android/ike/ikev2/message/IkeAuthPskPayload.java
+++ b/src/java/com/android/ike/ikev2/message/IkeAuthPskPayload.java
@@ -16,9 +16,10 @@
package com.android.ike.ikev2.message;
-import com.android.ike.ikev2.exceptions.IkeException;
-
import java.nio.ByteBuffer;
+import java.security.InvalidKeyException;
+
+import javax.crypto.Mac;
/**
* IkeAuthPskPayload represents an Authentication Payload using Pre-Shared Key to do authentication.
@@ -27,25 +28,79 @@ import java.nio.ByteBuffer;
* Protocol Version 2 (IKEv2).
*/
public final class IkeAuthPskPayload extends IkeAuthPayload {
+ // Hex of ASCII characters "Key Pad for IKEv2" for calculating PSK signature.
+ private static final byte[] IKE_KEY_PAD_STRING_ASCII_HEX_BYTES = {
+ (byte) 0x4b, (byte) 0x65, (byte) 0x79, (byte) 0x20,
+ (byte) 0x50, (byte) 0x61, (byte) 0x64, (byte) 0x20,
+ (byte) 0x66, (byte) 0x6f, (byte) 0x72, (byte) 0x20,
+ (byte) 0x49, (byte) 0x4b, (byte) 0x45, (byte) 0x76,
+ (byte) 0x32
+ };
+
public final byte[] signature;
- protected IkeAuthPskPayload(boolean critical, byte[] authData) throws IkeException {
+ /**
+ * Construct IkeAuthPskPayload for received IKE packet in the context of {@link
+ * IkePayloadFactory}.
+ */
+ protected IkeAuthPskPayload(boolean critical, byte[] authData) {
super(critical, IkeAuthPayload.AUTH_METHOD_PRE_SHARED_KEY);
signature = authData;
}
+ /**
+ * Construct IkeAuthPskPayload for an outbound IKE packet.
+ *
+ * <p>Since IKE library is always a client, outbound IkeAuthPskPayload always signs IKE
+ * initiator's SignedOctets, which is concatenation of the IKE_INIT request message, the Nonce
+ * of IKE responder and the signed ID-Initiator payload body.
+ *
+ * @param psk locally stored pre-shared key
+ * @param ikeInitBytes IKE_INIT request for calculating IKE initiator's SignedOctets.
+ * @param nonce nonce of IKE responder for calculating IKE initiator's SignedOctets.
+ * @param idPayloadBodyBytes ID-Initiator payload body for calculating IKE initiator's
+ * SignedOctets.
+ * @param prfMac locally store PRF
+ * @param prfKeyBytes locally store PRF keys
+ */
+ public IkeAuthPskPayload(
+ byte[] psk,
+ byte[] ikeInitBytes,
+ byte[] nonce,
+ byte[] idPayloadBodyBytes,
+ Mac prfMac,
+ byte[] prfKeyBytes) {
+ super(false, IkeAuthPayload.AUTH_METHOD_PRE_SHARED_KEY);
+ signature =
+ calculatePskSignature(
+ psk, ikeInitBytes, nonce, idPayloadBodyBytes, prfMac, prfKeyBytes);
+ }
+
+ private static byte[] calculatePskSignature(
+ byte[] psk,
+ byte[] ikeInitBytes,
+ byte[] nonce,
+ byte[] idPayloadBodyBytes,
+ Mac prfMac,
+ byte[] prfKeyBytes) {
+ try {
+ byte[] signingKeyBytes = signWithPrf(prfMac, psk, IKE_KEY_PAD_STRING_ASCII_HEX_BYTES);
+ byte[] dataToSignBytes =
+ getSignedOctets(ikeInitBytes, nonce, idPayloadBodyBytes, prfMac, prfKeyBytes);
+ return signWithPrf(prfMac, signingKeyBytes, dataToSignBytes);
+ } catch (InvalidKeyException e) {
+ throw new IllegalArgumentException("Locally stored PRF key is invalid: ", e);
+ }
+ }
+
@Override
- protected void encodeToByteBuffer(@PayloadType int nextPayload, ByteBuffer byteBuffer) {
- // TODO: Implement it.
- throw new UnsupportedOperationException(
- "It is not supported to encode a " + getTypeString());
+ protected void encodeAuthDataToByteBuffer(ByteBuffer byteBuffer) {
+ byteBuffer.put(signature);
}
@Override
- protected int getPayloadLength() {
- // TODO: Implement it.
- throw new UnsupportedOperationException(
- "It is not supported to get payload length of " + getTypeString());
+ protected int getAuthDataLength() {
+ return signature.length;
}
@Override
diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthPayloadTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthPayloadTest.java
index a67f04c4..7c630b76 100644
--- a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthPayloadTest.java
+++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthPayloadTest.java
@@ -28,7 +28,7 @@ import javax.crypto.Mac;
public final class IkeAuthPayloadTest {
private static final String PSK_AUTH_PAYLOAD_HEX_STRING =
"02000000df7c038aefaaa32d3f44b228b52a332744dfb2c1";
- private static final String PSK_AUTH_PAYLOAD_SIGNATRUE_HEX_STRING =
+ private static final String PSK_AUTH_PAYLOAD_SIGNATURE_HEX_STRING =
"df7c038aefaaa32d3f44b228b52a332744dfb2c1";
private static final String PSK_ID_PAYLOAD_HEX_STRING = "010000000a50500d";
private static final String PSK_SKP_HEX_STRING = "094787780EE466E2CB049FA327B43908BC57E485";
@@ -89,7 +89,7 @@ public final class IkeAuthPayloadTest {
assertTrue(payload instanceof IkeAuthPskPayload);
byte[] expectedSignature =
- TestUtils.hexStringToByteArray(PSK_AUTH_PAYLOAD_SIGNATRUE_HEX_STRING);
+ TestUtils.hexStringToByteArray(PSK_AUTH_PAYLOAD_SIGNATURE_HEX_STRING);
assertArrayEquals(expectedSignature, ((IkeAuthPskPayload) payload).signature);
}
diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthPskPayloadTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthPskPayloadTest.java
new file mode 100644
index 00000000..398e9626
--- /dev/null
+++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthPskPayloadTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import java.nio.ByteBuffer;
+
+import javax.crypto.Mac;
+
+
+public final class IkeAuthPskPayloadTest {
+ private static final String PSK_AUTH_PAYLOAD_HEX_STRING =
+ "2100001c02000000df7c038aefaaa32d3f44b228b52a332744dfb2c1";
+ private static final String PSK_AUTH_PAYLOAD_SIGNATURE_HEX_STRING =
+ "df7c038aefaaa32d3f44b228b52a332744dfb2c1";
+
+ private static final String PSK_IKE_INIT_REQUEST_HEX_STRING =
+ "5f54bf6d8b48e6e1000000000000000021202208"
+ + "0000000000000150220000300000002c01010004"
+ + "0300000c0100000c800e00800300000803000002"
+ + "0300000804000002000000080200000228000088"
+ + "00020000b4a2faf4bb54878ae21d638512ece55d"
+ + "9236fc5046ab6cef82220f421f3ce6361faf3656"
+ + "4ecb6d28798a94aad7b2b4b603ddeaaa5630adb9"
+ + "ece8ac37534036040610ebdd92f46bef84f0be7d"
+ + "b860351843858f8acf87056e272377f70c9f2d81"
+ + "e29c7b0ce4f291a3a72476bb0b278fd4b7b0a4c2"
+ + "6bbeb08214c707137607958729000024c39b7f36"
+ + "8f4681b89fa9b7be6465abd7c5f68b6ed5d3b4c7"
+ + "2cb4240eb5c464122900001c00004004e54f73b7"
+ + "d83f6beb881eab2051d8663f421d10b02b00001c"
+ + "00004005d915368ca036004cb578ae3e3fb26850"
+ + "9aeab19000000020699369228741c6d4ca094c93"
+ + "e242c9de19e7b7c60000000500000500";
+ private static final String PSK_NONCE_RESP_HEX_STRING =
+ "9756112ca539f5c25abacc7ee92b73091942a9c06950f98848f1af1694c4ddff";
+ private static final String PSK_ID_INITIATOR_PAYLOAD_HEX_STRING = "010000000a50500d";
+
+ private static final String PSK_HEX_STRING = "6A756E69706572313233";
+ private static final String PSK_SKP_HEX_STRING = "094787780EE466E2CB049FA327B43908BC57E485";
+
+ private static final String PRF_HMAC_SHA1_ALGO_NAME = "HmacSHA1";
+
+ @Test
+ public void testBuildOutboundIkeAuthPskPayload() throws Exception {
+ byte[] psk = TestUtils.hexStringToByteArray(PSK_HEX_STRING);
+ byte[] ikeInitBytes = TestUtils.hexStringToByteArray(PSK_IKE_INIT_REQUEST_HEX_STRING);
+ byte[] nonce = TestUtils.hexStringToByteArray(PSK_NONCE_RESP_HEX_STRING);
+ byte[] idPayloadBodyBytes =
+ TestUtils.hexStringToByteArray(PSK_ID_INITIATOR_PAYLOAD_HEX_STRING);
+ byte[] prfKeyBytes = TestUtils.hexStringToByteArray(PSK_SKP_HEX_STRING);
+ Mac prfMac = Mac.getInstance(PRF_HMAC_SHA1_ALGO_NAME, IkeMessage.getSecurityProvider());
+
+ IkeAuthPskPayload payload =
+ new IkeAuthPskPayload(
+ psk, ikeInitBytes, nonce, idPayloadBodyBytes, prfMac, prfKeyBytes);
+
+ assertEquals(IkeAuthPayload.AUTH_METHOD_PRE_SHARED_KEY, payload.authMethod);
+ byte[] expectedSignature =
+ TestUtils.hexStringToByteArray(PSK_AUTH_PAYLOAD_SIGNATURE_HEX_STRING);
+ assertArrayEquals(expectedSignature, payload.signature);
+
+ // Verify payload length
+ int payloadLength = payload.getPayloadLength();
+ byte[] expectedPayload = TestUtils.hexStringToByteArray(PSK_AUTH_PAYLOAD_HEX_STRING);
+ assertEquals(expectedPayload.length, payloadLength);
+
+ // Verify encoding
+ ByteBuffer byteBuffer = ByteBuffer.allocate(payloadLength);
+ payload.encodeToByteBuffer(IkePayload.PAYLOAD_TYPE_SA, byteBuffer);
+ assertArrayEquals(expectedPayload, byteBuffer.array());
+ }
+}