diff options
author | evitayan <evitayan@google.com> | 2019-02-08 16:14:19 -0800 |
---|---|---|
committer | evitayan <evitayan@google.com> | 2019-02-14 13:05:34 -0800 |
commit | 4b255a59d01857ebc4a508106a8917e6b3710745 (patch) | |
tree | 82da3634a468ff04144727caafc3611229800bbf | |
parent | a82e2910b79091e539328ccb7f296e0b9981aaf1 (diff) | |
download | ike-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
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()); + } +} |