diff options
author | Yan Yan <evitayan@google.com> | 2019-03-26 13:36:56 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-03-26 13:36:56 -0700 |
commit | 3a74cae3d5b191b6a1ba66bd066d17279eaa59dc (patch) | |
tree | a8bf102d89dcb09807b08a2ceafdff2f4f903da4 | |
parent | cb30e81491950a4eb0d3c35dbf920c52388a0d64 (diff) | |
parent | 7a77ef4b33c8a44fef75b768f30fb39932fae79f (diff) | |
download | ike-3a74cae3d5b191b6a1ba66bd066d17279eaa59dc.tar.gz |
Merge "Support IkeSessionOptions for basic IKE SA setup"
am: 7a77ef4b33
Change-Id: Ib923e28e66a825235f2f290335e21ab56e692cce
5 files changed, 219 insertions, 18 deletions
diff --git a/src/java/com/android/ike/ikev2/IkeSessionOptions.java b/src/java/com/android/ike/ikev2/IkeSessionOptions.java index 66ef94d6..fe06b85a 100644 --- a/src/java/com/android/ike/ikev2/IkeSessionOptions.java +++ b/src/java/com/android/ike/ikev2/IkeSessionOptions.java @@ -16,9 +16,107 @@ package com.android.ike.ikev2; +import android.net.IpSecManager.UdpEncapsulationSocket; + +import com.android.ike.ikev2.message.IkePayload; + +import java.net.InetAddress; +import java.util.LinkedList; +import java.util.List; + /** - * IkeSessionOptions contains all configurations including cryptographic algorithm set of an IKE SA. + * IkeSessionOptions contains all user provided configurations for negotiating an IKE SA. + * + * <p>TODO: Make this doc more user-friendly. */ public class IkeSessionOptions { - // TODO: Implement it. + private final InetAddress mServerAddress; + private final UdpEncapsulationSocket mUdpEncapSocket; + private final SaProposal[] mSaProposals; + private final boolean mIsIkeFragmentationSupported; + + private IkeSessionOptions( + InetAddress serverAddress, + UdpEncapsulationSocket udpEncapsulationSocket, + SaProposal[] proposals, + boolean isIkeFragmentationSupported) { + mServerAddress = serverAddress; + mUdpEncapSocket = udpEncapsulationSocket; + mSaProposals = proposals; + mIsIkeFragmentationSupported = isIkeFragmentationSupported; + } + + /** Package private */ + InetAddress getServerAddress() { + return mServerAddress; + } + /** Package private */ + UdpEncapsulationSocket getUdpEncapsulationSocket() { + return mUdpEncapSocket; + } + /** Package private */ + SaProposal[] getSaProposals() { + return mSaProposals; + } + /** Package private */ + boolean isIkeFragmentationSupported() { + return mIsIkeFragmentationSupported; + } + + /** This class can be used to incrementally construct a IkeSessionOptions. */ + public static final class Builder { + private final InetAddress mServerAddress; + private final UdpEncapsulationSocket mUdpEncapSocket; + private final List<SaProposal> mSaProposalList = new LinkedList<>(); + + private boolean mIsIkeFragmentationSupported = false; + + /** + * Returns a new Builder for an IkeSessionOptions. + * + * @param serverAddress IP address of remote IKE server. + * @param udpEncapsulationSocket {@link IpSecManager.UdpEncapsulationSocket} for sending and + * receiving IKE message. + * @return Builder for an IkeSessionOptions. + */ + public Builder(InetAddress serverAddress, UdpEncapsulationSocket udpEncapsulationSocket) { + mServerAddress = serverAddress; + mUdpEncapSocket = udpEncapsulationSocket; + } + + /** + * Adds an IKE SA proposal to IkeSessionOptions being built. + * + * @param proposal IKE SA proposal. + * @return Builder for an IkeSessionOptions. + * @throws IllegalArgumentException if input proposal is not IKE SA proposal. + */ + public Builder addSaProposal(SaProposal proposal) { + if (proposal.mProtocolId != IkePayload.PROTOCOL_ID_IKE) { + throw new IllegalArgumentException( + "Expected IKE SA Proposal but received Child SA proposal"); + } + mSaProposalList.add(proposal); + return this; + } + + /** + * Validates, builds and returns the IkeSessionOptions + * + * @return IkeSessionOptions the validated IkeSessionOptions + * @throws IllegalStateException if no IKE SA proposal is provided + */ + public IkeSessionOptions build() { + if (mSaProposalList.isEmpty()) { + throw new IllegalArgumentException("IKE SA proposal not found"); + } + return new IkeSessionOptions( + mServerAddress, + mUdpEncapSocket, + mSaProposalList.toArray(new SaProposal[mSaProposalList.size()]), + mIsIkeFragmentationSupported); + } + + // TODO: add methods for supporting IKE fragmentation. + } } diff --git a/src/java/com/android/ike/ikev2/SaProposal.java b/src/java/com/android/ike/ikev2/SaProposal.java index f932be24..3883404a 100644 --- a/src/java/com/android/ike/ikev2/SaProposal.java +++ b/src/java/com/android/ike/ikev2/SaProposal.java @@ -474,7 +474,7 @@ public final class SaProposal { * @return SaProposal the validated SaProposal. * @throws IllegalArgumentException if SaProposal is invalid. */ - public SaProposal buildOrThrow() { + public SaProposal build() { EncryptionTransform[] encryptionTransforms = buildEncryptAlgosOrThrow(); PrfTransform[] prfTransforms = buildPrfsOrThrow(); IntegrityTransform[] integrityTransforms = diff --git a/tests/iketests/src/java/com/android/ike/ikev2/IkeSessionOptionsTest.java b/tests/iketests/src/java/com/android/ike/ikev2/IkeSessionOptionsTest.java new file mode 100644 index 00000000..bdaf135a --- /dev/null +++ b/tests/iketests/src/java/com/android/ike/ikev2/IkeSessionOptionsTest.java @@ -0,0 +1,103 @@ +/* + * 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; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.fail; + +import android.content.Context; +import android.net.IpSecManager; +import android.net.IpSecManager.UdpEncapsulationSocket; + +import androidx.test.InstrumentationRegistry; + +import libcore.net.InetAddressUtils; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.net.Inet4Address; + +public final class IkeSessionOptionsTest { + private static final Inet4Address IPV4_ADDRESS = + (Inet4Address) (InetAddressUtils.parseNumericAddress("192.0.2.100")); + + private UdpEncapsulationSocket mUdpEncapSocket; + + @Before + public void setUp() throws Exception { + Context context = InstrumentationRegistry.getContext(); + IpSecManager ipSecManager = (IpSecManager) context.getSystemService(Context.IPSEC_SERVICE); + mUdpEncapSocket = ipSecManager.openUdpEncapsulationSocket(); + } + + @After + public void tearDown() throws Exception { + mUdpEncapSocket.close(); + } + + @Test + public void testBuild() throws Exception { + SaProposal saProposal = + SaProposal.Builder.newIkeSaProposalBuilder() + .addEncryptionAlgorithm( + SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8, + SaProposal.KEY_LEN_AES_128) + .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC) + .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP) + .build(); + + IkeSessionOptions sessionOptions = + new IkeSessionOptions.Builder(IPV4_ADDRESS, mUdpEncapSocket) + .addSaProposal(saProposal) + .build(); + + assertEquals(IPV4_ADDRESS, sessionOptions.getServerAddress()); + assertEquals(mUdpEncapSocket, sessionOptions.getUdpEncapsulationSocket()); + assertArrayEquals(new SaProposal[] {saProposal}, sessionOptions.getSaProposals()); + assertFalse(sessionOptions.isIkeFragmentationSupported()); + } + + @Test + public void testBuildWithoutSaProposal() throws Exception { + try { + new IkeSessionOptions.Builder(IPV4_ADDRESS, mUdpEncapSocket).build(); + fail("Expected to fail due to absence of SA proposal."); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void testBuildWithChildSaProposal() throws Exception { + SaProposal saProposal = + SaProposal.Builder.newChildSaProposalBuilder(true) + .addEncryptionAlgorithm( + SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8, + SaProposal.KEY_LEN_AES_128) + .build(); + try { + new IkeSessionOptions.Builder(IPV4_ADDRESS, mUdpEncapSocket) + .addSaProposal(saProposal) + .build(); + fail("Expected to fail due to wrong type of SA proposal."); + } catch (IllegalArgumentException expected) { + } + } +} diff --git a/tests/iketests/src/java/com/android/ike/ikev2/SaProposalTest.java b/tests/iketests/src/java/com/android/ike/ikev2/SaProposalTest.java index 2ce2a9d9..428c028d 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/SaProposalTest.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/SaProposalTest.java @@ -64,7 +64,7 @@ public final class SaProposalTest { .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96) .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC) .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP) - .buildOrThrow(); + .build(); assertEquals(IkePayload.PROTOCOL_ID_IKE, proposal.mProtocolId); assertArrayEquals( @@ -87,7 +87,7 @@ public final class SaProposalTest { SaProposal.KEY_LEN_AES_128) .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC) .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP) - .buildOrThrow(); + .build(); assertEquals(IkePayload.PROTOCOL_ID_IKE, proposal.mProtocolId); assertArrayEquals( @@ -107,7 +107,7 @@ public final class SaProposalTest { SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8, SaProposal.KEY_LEN_AES_128) .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_NONE) - .buildOrThrow(); + .build(); assertEquals(IkePayload.PROTOCOL_ID_ESP, proposal.mProtocolId); assertArrayEquals( @@ -127,7 +127,7 @@ public final class SaProposalTest { builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES) .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_NONE) .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP) - .buildOrThrow(); + .build(); assertEquals(IkePayload.PROTOCOL_ID_ESP, proposal.mProtocolId); assertArrayEquals( @@ -143,7 +143,7 @@ public final class SaProposalTest { public void testBuildEncryptAlgosWithNoAlgorithm() throws Exception { Builder builder = Builder.newIkeSaProposalBuilder(); try { - builder.buildOrThrow(); + builder.build(); fail("Expected to fail when no encryption algorithm is proposed."); } catch (IllegalArgumentException expected) { @@ -179,7 +179,7 @@ public final class SaProposalTest { public void testBuildIkeProposalWithoutPrf() throws Exception { Builder builder = Builder.newIkeSaProposalBuilder(); try { - builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES).buildOrThrow(); + builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES).build(); fail("Expected to fail when PRF is not provided in IKE SA proposal."); } catch (IllegalArgumentException expected) { @@ -192,7 +192,7 @@ public final class SaProposalTest { try { builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES) .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1) - .buildOrThrow(); + .build(); fail("Expected to fail when PRF is provided in Child SA proposal."); } catch (IllegalArgumentException expected) { @@ -209,7 +209,7 @@ public final class SaProposalTest { builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12) .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_NONE) .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96) - .buildOrThrow(); + .build(); fail("Expected to fail when not-none integrity algorithm is proposed with AEAD"); } catch (IllegalArgumentException expected) { @@ -225,7 +225,7 @@ public final class SaProposalTest { try { builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES) .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1) - .buildOrThrow(); + .build(); fail( "Expected to fail when" @@ -245,7 +245,7 @@ public final class SaProposalTest { .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1) .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_NONE) .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96) - .buildOrThrow(); + .build(); fail( "Expected to fail when none-value integrity algorithm is proposed" @@ -262,7 +262,7 @@ public final class SaProposalTest { builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES) .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96) .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC) - .buildOrThrow(); + .build(); fail("Expected to fail when no DH Group is proposed in IKE SA proposal."); } catch (IllegalArgumentException expected) { @@ -279,7 +279,7 @@ public final class SaProposalTest { .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC) .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP) .addDhGroup(SaProposal.DH_GROUP_NONE) - .buildOrThrow(); + .build(); fail("Expected to fail when none-value DH Group is proposed in IKE SA proposal."); } catch (IllegalArgumentException expected) { @@ -295,7 +295,7 @@ public final class SaProposalTest { builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES) .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96) .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP) - .buildOrThrow(); + .build(); fail( "Expected to fail when" diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeSaPayloadTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeSaPayloadTest.java index b0d927d8..2a47362c 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeSaPayloadTest.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeSaPayloadTest.java @@ -153,7 +153,7 @@ public final class IkeSaPayloadTest { .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96) .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP) .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1) - .buildOrThrow(); + .build(); mSaProposalTwo = SaProposal.Builder.newIkeSaProposalBuilder() @@ -166,7 +166,7 @@ public final class IkeSaPayloadTest { .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC) .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP) .addDhGroup(SaProposal.DH_GROUP_2048_BIT_MODP) - .buildOrThrow(); + .build(); mTwoSaProposalsArray = new SaProposal[] {mSaProposalOne, mSaProposalTwo}; } |